You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@karaf.apache.org by gn...@apache.org on 2014/04/10 16:15:23 UTC

[01/59] [abbrv] [KARAF-2852] Merge features/core and features/command

Repository: karaf
Updated Branches:
  refs/heads/master 025a8ec93 -> 48ef3aa01


http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/src/test/java/org/apache/karaf/features/internal/service/BundleManagerTest.java
----------------------------------------------------------------------
diff --git a/features/src/test/java/org/apache/karaf/features/internal/service/BundleManagerTest.java b/features/src/test/java/org/apache/karaf/features/internal/service/BundleManagerTest.java
new file mode 100644
index 0000000..bed8104
--- /dev/null
+++ b/features/src/test/java/org/apache/karaf/features/internal/service/BundleManagerTest.java
@@ -0,0 +1,64 @@
+/*
+ * 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.karaf.features.internal.service;
+
+import org.apache.karaf.features.TestBase;
+
+public class BundleManagerTest extends TestBase {
+
+    /*
+    @Test
+    public void testfindBundlestoRefreshWithHostToRefresh() throws Exception {
+        Bundle hostBundle = createDummyBundle(12345l, "Host", headers());
+        Bundle fragmentBundle = createDummyBundle(54321l, "fragment", headers(Constants.FRAGMENT_HOST, "Host"));
+
+        BundleContext bundleContext = EasyMock.createMock(BundleContext.class);
+        BundleManager bundleManager = new BundleManager(bundleContext);
+
+        // Host was already installed, fragment is new
+        Set<Bundle> existing = new HashSet<Bundle>(Arrays.asList(hostBundle, fragmentBundle));
+        Set<Bundle> installed = new HashSet<Bundle>(Arrays.asList(fragmentBundle));
+        
+        replay(bundleContext);
+        Set<Bundle> bundles = bundleManager.findBundlesWithFragmentsToRefresh(existing, installed);
+        EasyMock.verify(bundleContext);
+
+        Assert.assertEquals(1, bundles.size());
+        Assert.assertEquals(hostBundle, bundles.iterator().next());
+    }
+    
+    @Test
+    public void testfindBundlestoRefreshWithOptionalPackages() throws Exception {
+        Bundle exporterBundle = createDummyBundle(12345l, "exporter", headers(Constants.EXPORT_PACKAGE, "org.my.package"));
+        Bundle importerBundle = createDummyBundle(54321l, "importer", headers(Constants.IMPORT_PACKAGE, "org.my.package;resolution:=optional"));
+
+        BundleContext bundleContext = EasyMock.createMock(BundleContext.class);
+        BundleManager bundleManager = new BundleManager(bundleContext);
+
+        // Importer was already installed, exporter is new
+        Set<Bundle> existing = new HashSet<Bundle>(Arrays.asList(importerBundle, exporterBundle));
+        Set<Bundle> installed = new HashSet<Bundle>(Arrays.asList(exporterBundle));
+        
+        replay(bundleContext);
+        Set<Bundle> bundles = bundleManager.findBundlesWithOptionalPackagesToRefresh(existing, installed);
+        EasyMock.verify(bundleContext);
+
+        Assert.assertEquals(1, bundles.size());
+        Assert.assertEquals(importerBundle, bundles.iterator().next());
+    }
+    */
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/src/test/java/org/apache/karaf/features/internal/service/FeaturesServiceImplTest.java
----------------------------------------------------------------------
diff --git a/features/src/test/java/org/apache/karaf/features/internal/service/FeaturesServiceImplTest.java b/features/src/test/java/org/apache/karaf/features/internal/service/FeaturesServiceImplTest.java
new file mode 100644
index 0000000..b8b5fc0
--- /dev/null
+++ b/features/src/test/java/org/apache/karaf/features/internal/service/FeaturesServiceImplTest.java
@@ -0,0 +1,167 @@
+/*
+ * 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.karaf.features.internal.service;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.fail;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Map;
+
+import org.apache.karaf.features.Feature;
+import org.apache.karaf.features.TestBase;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Test cases for {@link org.apache.karaf.features.internal.service.FeaturesServiceImpl}
+ */
+public class FeaturesServiceImplTest extends TestBase {
+    
+    File dataFile;
+
+    @Before
+    public void setUp() throws IOException {
+        dataFile = File.createTempFile("features", null, null);
+    }
+
+    @Test
+    public void testGetFeature() throws Exception {
+        Feature transactionFeature = feature("transaction", "1.0.0");
+        final Map<String, Map<String, Feature>> features = features(transactionFeature);
+        final FeaturesServiceImpl impl = new FeaturesServiceImpl(null, null, new Storage(), null, null, null, "", null, null, null) {
+            protected Map<String,Map<String,Feature>> getFeatures() throws Exception {
+                return features;
+            }
+        };
+        assertNotNull(impl.getFeature("transaction", org.apache.karaf.features.internal.model.Feature.DEFAULT_VERSION));
+        assertSame(transactionFeature, impl.getFeature("transaction", org.apache.karaf.features.internal.model.Feature.DEFAULT_VERSION));
+    }
+    
+    @Test
+    public void testGetFeatureStripVersion() throws Exception {
+        final FeaturesServiceImpl impl = new FeaturesServiceImpl(null, null, new Storage(), null, null, null, "", null, null, null) {
+            protected Map<String,Map<String,Feature>> getFeatures() throws Exception {
+                return features(feature("transaction", "1.0.0"));
+            }
+        };
+        Feature feature = impl.getFeature("transaction", "  1.0.0  ");
+        assertNotNull(feature);
+        assertSame("transaction", feature.getName());
+    }
+    
+    @Test
+    public void testGetFeatureNotAvailable() throws Exception {
+        final FeaturesServiceImpl impl = new FeaturesServiceImpl(null, null, new Storage(), null, null, null, "", null, null, null) {
+            protected Map<String,Map<String,Feature>> getFeatures() throws Exception {
+                return features(feature("transaction", "1.0.0"));
+            }
+        };
+        assertNull(impl.getFeature("activemq", org.apache.karaf.features.internal.model.Feature.DEFAULT_VERSION));
+    }
+    
+    @Test
+    public void testGetFeatureHighestAvailable() throws Exception {
+        final Map<String, Map<String, Feature>> features = features(
+                feature("transaction", "1.0.0"),
+                feature("transaction", "2.0.0")
+        );
+        final FeaturesServiceImpl impl = new FeaturesServiceImpl(null, null, new Storage(), null, null, null, "", null, null, null) {
+            protected Map<String,Map<String,Feature>> getFeatures() throws Exception {
+                return features;
+            }
+        };
+        assertNotNull(impl.getFeature("transaction", org.apache.karaf.features.internal.model.Feature.DEFAULT_VERSION));
+        assertSame("2.0.0", impl.getFeature("transaction", org.apache.karaf.features.internal.model.Feature.DEFAULT_VERSION).getVersion());
+    }
+
+    /**
+     * This test ensures that every feature get installed only once, even if it appears multiple times in the list
+     * of transitive feature dependencies (KARAF-1600)
+     */
+    /*
+    @Test
+    @SuppressWarnings("unchecked")
+    public void testNoDuplicateFeaturesInstallation() throws Exception {
+        final List<Feature> installed = new LinkedList<Feature>();
+        BundleManager bundleManager = EasyMock.createMock(BundleManager.class);
+        expect(bundleManager.installBundleIfNeeded(EasyMock.anyObject(String.class), EasyMock.anyInt(), EasyMock.anyObject(String.class)))
+            .andReturn(new BundleInstallerResult(createDummyBundle(1l, "", headers()), true)).anyTimes();
+        bundleManager.refreshBundles(EasyMock.anyObject(Set.class), EasyMock.anyObject(Set.class), EasyMock.anyObject(EnumSet.class));
+        EasyMock.expectLastCall();
+        final FeaturesServiceImpl impl = new FeaturesServiceImpl(bundleManager, null) {
+            // override methods which refers to bundle context to avoid mocking everything
+            @Override
+            protected boolean loadState() {
+                return true;
+            }
+
+            @Override
+            protected void saveState() {
+
+            }
+
+            @Override
+            protected void doInstallFeature(InstallationState state, Feature feature, boolean verbose) throws Exception {
+                installed.add(feature);
+
+                super.doInstallFeature(state, feature, verbose);
+            }
+
+        };
+        replay(bundleManager);
+        impl.addRepository(getClass().getResource("repo2.xml").toURI());
+        impl.installFeature("all");
+
+        // copying the features to a set to filter out the duplicates
+        Set<Feature> noduplicates = new HashSet<Feature>();
+        noduplicates.addAll(installed);
+
+        assertEquals("Every feature should only have been installed once", installed.size(), noduplicates.size());
+    }
+
+    @Test
+    public void testGetOptionalImportsOnly() {
+        BundleManager bundleManager = new BundleManager(null, 0l);
+
+        List<Clause> result = bundleManager.getOptionalImports("org.apache.karaf,org.apache.karaf.optional;resolution:=optional");
+        assertEquals("One optional import expected", 1, result.size());
+        assertEquals("org.apache.karaf.optional", result.get(0).getName());
+
+        result = bundleManager.getOptionalImports(null);
+        assertNotNull(result);
+        assertEquals("No optional imports expected", 0, result.size());
+    }
+    */
+
+    static class Storage extends StateStorage {
+        @Override
+        protected InputStream getInputStream() throws IOException {
+            return null;
+        }
+        @Override
+        protected OutputStream getOutputStream() throws IOException {
+            return null;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/src/test/java/org/apache/karaf/features/internal/service/FeaturesValidationTest.java
----------------------------------------------------------------------
diff --git a/features/src/test/java/org/apache/karaf/features/internal/service/FeaturesValidationTest.java b/features/src/test/java/org/apache/karaf/features/internal/service/FeaturesValidationTest.java
new file mode 100644
index 0000000..f3ca2e6
--- /dev/null
+++ b/features/src/test/java/org/apache/karaf/features/internal/service/FeaturesValidationTest.java
@@ -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.karaf.features.internal.service;
+
+import org.junit.Test;
+
+import static org.junit.Assert.fail;
+
+public class FeaturesValidationTest {
+
+    @Test
+    public void testNoNs() throws Exception {
+        FeatureValidationUtil.validate(getClass().getResource("f01.xml").toURI());
+    }
+
+    @Test
+    public void testNs10() throws Exception {
+        FeatureValidationUtil.validate(getClass().getResource("f02.xml").toURI());
+    }
+
+    @Test
+    public void testNs10NoName() throws Exception {
+        FeatureValidationUtil.validate(getClass().getResource("f03.xml").toURI());
+    }
+
+    @Test
+    public void testNs11() throws Exception {
+        FeatureValidationUtil.validate(getClass().getResource("f04.xml").toURI());
+    }
+
+    @Test
+    public void testNs12() throws Exception {
+        FeatureValidationUtil.validate(getClass().getResource("f06.xml").toURI());
+    }
+
+    @Test
+    public void testNs11NoName() throws Exception {
+        try {
+            FeatureValidationUtil.validate(getClass().getResource("f05.xml").toURI());
+            fail("Validation should have failed");
+        } catch (Exception e) {
+            // ok
+        }
+    }
+
+    @Test
+    public void testNs13() throws Exception {
+        FeatureValidationUtil.validate(getClass().getResource("f07.xml").toURI());
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/src/test/java/org/apache/karaf/features/internal/service/OverridesTest.java
----------------------------------------------------------------------
diff --git a/features/src/test/java/org/apache/karaf/features/internal/service/OverridesTest.java b/features/src/test/java/org/apache/karaf/features/internal/service/OverridesTest.java
new file mode 100644
index 0000000..d9093d5
--- /dev/null
+++ b/features/src/test/java/org/apache/karaf/features/internal/service/OverridesTest.java
@@ -0,0 +1,202 @@
+/*
+ * 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.karaf.features.internal.service;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.felix.utils.manifest.Clause;
+import org.apache.felix.utils.manifest.Parser;
+import org.apache.karaf.features.BundleInfo;
+import org.apache.karaf.features.internal.model.Bundle;
+import org.apache.karaf.features.internal.resolver.ResourceBuilder;
+import org.apache.karaf.features.internal.resolver.UriNamespace;
+import org.junit.Before;
+import org.junit.Test;
+import org.ops4j.pax.tinybundles.core.TinyBundles;
+import org.osgi.framework.BundleException;
+import org.osgi.resource.Resource;
+
+import static org.apache.karaf.features.internal.resolver.UriNamespace.getUri;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+public class OverridesTest {
+
+    private String bsn = "bsn";
+    private Resource b100;
+    private Resource b101;
+    private Resource b102;
+    private Resource b110;
+    private Resource c100;
+    private Resource c101;
+    private Resource c110;
+
+    @Before
+    public void setUp() throws BundleException {
+        b100 = resource("karaf-100.jar")
+                .set("Bundle-SymbolicName", bsn)
+                .set("Bundle-Version", "1.0.0")
+                .build();
+
+        b101 = resource("karaf-101.jar")
+                .set("Bundle-SymbolicName", bsn)
+                .set("Bundle-Version", "1.0.1")
+                .build();
+
+        b102 = resource("karaf-102.jar")
+                .set("Bundle-SymbolicName", bsn)
+                .set("Bundle-Version", "1.0.2")
+                .build();
+
+        b110 = resource("karaf-110.jar")
+                .set("Bundle-SymbolicName", bsn)
+                .set("Bundle-Version", "1.1.0")
+                .build();
+
+        c100 = resource("karafc-100.jar")
+                .set("Bundle-SymbolicName", bsn)
+                .set("Bundle-Version", "1.0.0")
+                .set("Bundle-Vendor", "Apache")
+                .build();
+
+        c101 = resource("karafc-101.jar")
+                .set("Bundle-SymbolicName", bsn)
+                .set("Bundle-Version", "1.0.1")
+                .set("Bundle-Vendor", "NotApache")
+                .build();
+
+        c110 = resource("karafc-110.jar")
+                .set("Bundle-SymbolicName", bsn)
+                .set("Bundle-Version", "1.1.0")
+                .set("Bundle-Vendor", "NotApache")
+                .build();
+    }
+
+    @Test
+    public void testDifferentVendors() throws IOException {
+        Map<String, Resource> map = asResourceMap(c100, c101, c110);
+        assertEquals(c100, map.get(getUri(c100)));
+        Overrides.override(map, Arrays.asList(getUri(c101), getUri(c110)));
+        assertEquals(c101, map.get(getUri(c100)));
+    }
+
+    @Test
+    public void testMatching101() throws IOException {
+        Map<String, Resource> map = asResourceMap(b100, b101, b110);
+        assertEquals(b100, map.get(getUri(b100)));
+        Overrides.override(map, Arrays.asList(getUri(b101), getUri(b110)));
+        assertEquals(b101, map.get(getUri(b100)));
+    }
+
+    @Test
+    public void testMatching102() throws IOException {
+        Map<String, Resource> map = asResourceMap(b100, b101, b102, b110);
+        assertEquals(b100, map.get(getUri(b100)));
+        Overrides.override(map, Arrays.asList(getUri(b101), getUri(b102), getUri(b110)));
+        assertEquals(b102, map.get(getUri(b100)));
+    }
+
+    @Test
+    public void testMatchingRange() throws IOException {
+        Map<String, Resource> map = asResourceMap(b100, b101, b110);
+        assertEquals(b100, map.get(getUri(b100)));
+        Overrides.override(map, Arrays.asList(getUri(b101), getUri(b110) + ";range=\"[1.0, 2.0)\""));
+        assertEquals(b110, map.get(getUri(b100)));
+    }
+
+    @Test
+    public void testNotMatching() throws IOException {
+        Map<String, Resource> map = asResourceMap(b100, b110);
+        assertEquals(b100, map.get(getUri(b100)));
+        Overrides.override(map, Arrays.asList(getUri(b110)));
+        assertEquals(b100, map.get(getUri(b100)));
+    }
+
+    @Test
+    public void testLoadOverrides() {
+        Set<String> overrides = Overrides.loadOverrides(getClass().getResource("overrides.properties").toExternalForm());
+        assertEquals(2, overrides.size());
+
+        Clause karafAdminCommand = null;
+        Clause karafAdminCore = null;
+        for (Clause clause : Parser.parseClauses(overrides.toArray(new String[overrides.size()]))) {
+            if (clause.getName().equals("mvn:org.apache.karaf.admin/org.apache.karaf.admin.command/2.3.0.redhat-61033X")) {
+                karafAdminCommand = clause;
+            }
+            if (clause.getName().equals("mvn:org.apache.karaf.admin/org.apache.karaf.admin.core/2.3.0.redhat-61033X")) {
+                karafAdminCore = clause;
+            }
+        }
+        assertNotNull("Missing admin.command bundle override", karafAdminCommand);
+        assertNotNull("Missing admin.core bundle override", karafAdminCore);
+        assertNotNull("Missing range on admin.core override", karafAdminCore.getAttribute(Overrides.OVERRIDE_RANGE));
+    }
+
+    /**
+     * Copies the content of {@link java.io.InputStream} to {@link java.io.OutputStream}.
+     *
+     * @param input
+     * @param output
+     * @throws java.io.IOException
+     */
+    private void copy(final InputStream input, final OutputStream output) throws IOException {
+        byte[] buffer = new byte[1024 * 16];
+        int n;
+        while (-1 != (n = input.read(buffer))) {
+            output.write(buffer, 0, n);
+            output.flush();
+        }
+        input.close();
+        output.close();
+    }
+
+    static Builder resource(String uri) {
+        return new Builder(uri);
+    }
+
+    static Map<String, Resource> asResourceMap(Resource... resources) {
+        Map<String, Resource> map = new HashMap<String, Resource>();
+        for (Resource resource : resources) {
+            map.put(getUri(resource), resource);
+        }
+        return map;
+    }
+
+    static class Builder {
+        String uri;
+        Map<String,String> headers = new HashMap<String,String>();
+        Builder(String uri) {
+            this.uri = uri;
+            this.headers.put("Bundle-ManifestVersion", "2");
+        }
+        Builder set(String key, String value) {
+            this.headers.put(key, value);
+            return this;
+        }
+        Resource build() throws BundleException {
+            return ResourceBuilder.build(uri, headers);
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/src/test/resources/org/apache/karaf/features/internal/service/f01.xml
----------------------------------------------------------------------
diff --git a/features/src/test/resources/org/apache/karaf/features/internal/service/f01.xml b/features/src/test/resources/org/apache/karaf/features/internal/service/f01.xml
new file mode 100644
index 0000000..814c722
--- /dev/null
+++ b/features/src/test/resources/org/apache/karaf/features/internal/service/f01.xml
@@ -0,0 +1,92 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+      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.
+-->
+<features name="karaf-2.0.0">
+    <feature name="spring" version="3.0.3.RELEASE">
+        <bundle>mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.aopalliance/1.0_6</bundle>
+        <bundle>mvn:org.springframework/spring-core/3.0.3.RELEASE</bundle>
+        <bundle>mvn:org.springframework/spring-asm/3.0.3.RELEASE</bundle>
+        <bundle>mvn:org.springframework/spring-expression/3.0.3.RELEASE</bundle>
+        <bundle>mvn:org.springframework/spring-beans/3.0.3.RELEASE</bundle>
+        <bundle>mvn:org.springframework/spring-aop/3.0.3.RELEASE</bundle>
+        <bundle>mvn:org.springframework/spring-context/3.0.3.RELEASE</bundle>
+        <bundle>mvn:org.springframework/spring-context-support/3.0.3.RELEASE</bundle>
+    </feature>
+    <feature name="spring-dm" version="1.2.0">
+        <feature version="3.0.3.RELEASE">spring</feature>
+        <bundle>mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.cglib/2.2.2_1</bundle>
+        <bundle>mvn:org.springframework.osgi/spring-osgi-io/1.2.0</bundle>
+        <bundle>mvn:org.springframework.osgi/spring-osgi-core/1.2.0</bundle>
+        <bundle>mvn:org.springframework.osgi/spring-osgi-extender/1.2.0</bundle>
+        <bundle>mvn:org.springframework.osgi/spring-osgi-annotation/1.2.0</bundle>
+        <bundle>mvn:org.apache.karaf.deployer/org.apache.karaf.deployer.spring/2.0.0</bundle>
+    </feature>
+    <feature name="wrapper" version="2.0.0">
+        <bundle>mvn:org.apache.karaf.shell/org.apache.karaf.shell.wrapper/2.0.0</bundle>
+    </feature>
+    <feature name="obr" version="2.0.0">
+        <bundle>mvn:org.apache.felix/org.apache.felix.bundlerepository/1.6.4</bundle>
+        <bundle>mvn:org.apache.karaf.shell/org.apache.karaf.shell.obr/2.0.0</bundle>
+        <bundle>mvn:org.apache.karaf.features/org.apache.karaf.features.obr/2.0.0</bundle>
+    </feature>
+    <feature name="http" version="2.0.0">
+        <config name="org.ops4j.pax.web">
+            org.osgi.service.http.port=8181
+        </config>
+        <bundle>mvn:org.apache.geronimo.specs/geronimo-servlet_2.5_spec/1.1.2</bundle>
+        <bundle>mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.jetty-bundle/6.1.22_1</bundle>
+        <bundle>mvn:org.ops4j.pax.web/pax-web-api/0.7.2</bundle>
+        <bundle>mvn:org.ops4j.pax.web/pax-web-spi/0.7.2</bundle>
+        <bundle>mvn:org.ops4j.pax.web/pax-web-runtime/0.7.2</bundle>
+        <bundle>mvn:org.ops4j.pax.web/pax-web-jetty/0.7.2</bundle>
+    </feature>
+    <feature name="war" version="2.0.0">
+        <feature version="2.0.0">http</feature>
+        <bundle>mvn:org.ops4j.pax.web/pax-web-jsp/0.7.2</bundle>
+        <bundle>mvn:org.ops4j.pax.web/pax-web-extender-war/0.7.2</bundle>
+        <bundle>mvn:org.ops4j.pax.web/pax-web-extender-whiteboard/0.7.2</bundle>
+        <bundle>mvn:org.ops4j.pax.url/pax-url-war/1.1.3</bundle>
+        <bundle>mvn:org.apache.karaf.deployer/org.apache.karaf.deployer.war/2.0.0</bundle>
+    </feature>
+    <feature name="webconsole" version="2.0.0">
+        <feature version="2.0.0">http</feature>
+        <config name="org.apache.karaf.webconsole">
+            realm=karaf
+        </config>
+        <bundle>mvn:org.apache.felix/org.apache.felix.metatype/1.0.2</bundle>
+        <bundle>mvn:org.apache.karaf.webconsole/org.apache.karaf.webconsole.branding/2.0.0</bundle>
+        <bundle>mvn:org.apache.felix/org.apache.felix.webconsole/3.1.0</bundle>
+        <bundle>mvn:org.apache.karaf.webconsole/org.apache.karaf.webconsole.admin/2.0.0</bundle>
+        <bundle>mvn:org.apache.karaf.webconsole/org.apache.karaf.webconsole.features/2.0.0</bundle>
+        <bundle>mvn:org.apache.karaf.webconsole/org.apache.karaf.webconsole.gogo/2.0.0</bundle>
+    </feature>
+    <feature name="ssh" version="2.0.0">
+        <config name="org.apache.karaf.shell.ssh">
+            sshPort=8101
+            sshHost=0.0.0.0
+            sshRealm=karaf
+        </config>
+        <bundle>mvn:org.apache.mina/mina-core/2.0.0-RC1</bundle>
+        <bundle>mvn:org.apache.sshd/sshd-core/0.4.0</bundle>
+        <bundle>mvn:org.apache.karaf.shell/org.apache.karaf.shell.ssh/2.0.0</bundle>
+    </feature>
+    <feature name="management" version="2.0.0">
+        <bundle>mvn:org.apache.karaf/org.apache.karaf.management/2.0.0</bundle>
+        <bundle>mvn:org.apache.aries.jmx/org.apache.aries.jmx/0.1-r964701</bundle>
+        <bundle>mvn:org.apache.aries.jmx/org.apache.aries.jmx.blueprint/0.1-r964701</bundle>
+    </feature>
+</features>

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/src/test/resources/org/apache/karaf/features/internal/service/f02.xml
----------------------------------------------------------------------
diff --git a/features/src/test/resources/org/apache/karaf/features/internal/service/f02.xml b/features/src/test/resources/org/apache/karaf/features/internal/service/f02.xml
new file mode 100644
index 0000000..1578faa
--- /dev/null
+++ b/features/src/test/resources/org/apache/karaf/features/internal/service/f02.xml
@@ -0,0 +1,164 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+      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.
+-->
+<features name="karaf-2.2.0" xmlns="http://karaf.apache.org/xmlns/features/v1.0.0">
+    <feature name="spring" version="2.5.6.SEC02" resolver="(obr)">
+        <bundle dependency='true'>mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.aopalliance/1.0_6</bundle>
+        <bundle>mvn:org.springframework/spring-core/2.5.6.SEC02</bundle>
+        <bundle>mvn:org.springframework/spring-beans/2.5.6.SEC02</bundle>
+        <bundle>mvn:org.springframework/spring-aop/2.5.6.SEC02</bundle>
+        <bundle>mvn:org.springframework/spring-context/2.5.6.SEC02</bundle>
+        <bundle>mvn:org.springframework/spring-context-support/2.5.6.SEC02</bundle>
+    </feature>
+    <feature name="spring-web" version="2.5.6.SEC02" resolver="(obr)">
+    	<feature version="2.5.6.SEC02">spring</feature>
+    	<feature version="2.2.0">http</feature>
+    	<bundle>mvn:org.springframework/spring-web/2.5.6.SEC02</bundle>
+		<bundle>mvn:org.springframework/spring-webmvc/2.5.6.SEC02</bundle>
+    </feature>
+    <feature name="spring" version="3.0.5.RELEASE" resolver="(obr)">
+        <bundle dependency='true'>mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.aopalliance/1.0_6</bundle>
+        <bundle>mvn:org.springframework/spring-core/3.0.5.RELEASE</bundle>
+        <bundle>mvn:org.springframework/spring-asm/3.0.5.RELEASE</bundle>
+        <bundle>mvn:org.springframework/spring-expression/3.0.5.RELEASE</bundle>
+        <bundle>mvn:org.springframework/spring-beans/3.0.5.RELEASE</bundle>
+        <bundle>mvn:org.springframework/spring-aop/3.0.5.RELEASE</bundle>
+        <bundle>mvn:org.springframework/spring-context/3.0.5.RELEASE</bundle>
+        <bundle>mvn:org.springframework/spring-context-support/3.0.5.RELEASE</bundle>
+    </feature>
+    <feature name="spring-web" version="3.0.5.RELEASE" resolver="(obr)">
+    	<feature version="3.0.5.RELEASE">spring</feature>
+    	<feature version="2.2.0">http</feature>
+    	<bundle>mvn:org.springframework/spring-web/3.0.5.RELEASE</bundle>
+		<bundle>mvn:org.springframework/spring-webmvc/3.0.5.RELEASE</bundle>
+    </feature>
+    <feature name="spring-dm" version="1.2.1" resolver="(obr)">
+        <feature version="[2.5.6,4)">spring</feature>
+        <bundle dependency='true'>mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.cglib/2.2.2_1</bundle>
+        <bundle>mvn:org.springframework.osgi/spring-osgi-io/1.2.1</bundle>
+        <bundle>mvn:org.springframework.osgi/spring-osgi-core/1.2.1</bundle>
+        <bundle>mvn:org.springframework.osgi/spring-osgi-extender/1.2.1</bundle>
+        <bundle>mvn:org.springframework.osgi/spring-osgi-annotation/1.2.1</bundle>
+        <bundle>mvn:org.apache.karaf.deployer/org.apache.karaf.deployer.spring/2.2.0</bundle>
+    </feature>
+    <feature name="spring-dm-web" version="1.2.1" resolver="(obr)">
+    	<feature version="1.2.1">spring-dm</feature>
+    	<feature version="[2.5.6,4)">spring-web</feature>
+    	<feature version="2.2.0">http</feature>
+		<bundle>mvn:org.springframework.osgi/spring-osgi-web/1.2.1</bundle>
+    </feature>
+    <feature name="wrapper" version="2.2.0">
+        <bundle>mvn:org.apache.karaf.shell/org.apache.karaf.shell.wrapper/2.2.0</bundle>
+    </feature>
+    <feature name="obr" version="2.2.0">
+        <bundle>mvn:org.apache.felix/org.apache.felix.bundlerepository/1.6.4</bundle>
+        <bundle>mvn:org.apache.karaf.shell/org.apache.karaf.shell.obr/2.2.0</bundle>
+        <bundle>mvn:org.apache.karaf.features/org.apache.karaf.features.obr/2.2.0</bundle>
+    </feature>
+    <feature name="config" version="2.2.0">
+        <bundle start-level='30'>mvn:org.apache.karaf.shell/org.apache.karaf.shell.config/2.2.0</bundle>
+    </feature>
+	<feature name="jetty" version="7.2.2.v20101205" resolver="(obr)">
+		<bundle dependency='true'>mvn:org.apache.geronimo.specs/geronimo-servlet_2.5_spec/1.1.2</bundle>
+        <bundle dependency='true'>mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.asm/3.3_1</bundle>
+	    <bundle>mvn:org.eclipse.jetty/jetty-util/7.2.2.v20101205</bundle>
+	    <bundle>mvn:org.eclipse.jetty/jetty-io/7.2.2.v20101205</bundle>
+	    <bundle>mvn:org.eclipse.jetty/jetty-http/7.2.2.v20101205</bundle>
+	    <bundle>mvn:org.eclipse.jetty/jetty-continuation/7.2.2.v20101205</bundle>
+	    <bundle>mvn:org.eclipse.jetty/jetty-server/7.2.2.v20101205</bundle>
+	    <bundle>mvn:org.eclipse.jetty/jetty-security/7.2.2.v20101205</bundle>
+	    <bundle>mvn:org.eclipse.jetty/jetty-servlet/7.2.2.v20101205</bundle>
+    	<bundle>mvn:org.eclipse.jetty/jetty-xml/7.2.2.v20101205</bundle>
+	</feature>
+	<feature name="jetty-jaas" version="7.2.2.v20101205" resolver="(obr)">
+		<feature version="[7.0,8.0)">jetty</feature>
+		<bundle dependency='true'>mvn:javax.mail/mail/1.4.3</bundle>
+		<bundle dependency='true'>mvn:org.apache.geronimo.specs/geronimo-jta_1.1_spec/1.1.1</bundle>
+		<bundle>mvn:org.eclipse.jetty/jetty-webapp/7.2.2.v20101205</bundle>
+		<bundle>mvn:org.eclipse.jetty/jetty-jndi/7.2.2.v20101205</bundle>
+		<bundle>mvn:org.eclipse.jetty/jetty-plus/7.2.2.v20101205</bundle>
+	</feature>
+    <feature name="http" version="2.2.0" resolver="(obr)">
+    	<configfile finalname="/etc/jetty.xml">mvn:org.apache.karaf/apache-karaf/2.2.0/xml/jettyconfig</configfile>
+		<config name="org.ops4j.pax.web">
+            org.osgi.service.http.port=8181
+            javax.servlet.context.tempdir=${karaf.data}/pax-web-jsp
+            org.ops4j.pax.web.config.file=${karaf.etc}/jetty.xml
+        </config>
+        <feature version="[7.0,8.0)">jetty</feature>
+    	<bundle>mvn:org.ops4j.pax.web/pax-web-api/1.0.1</bundle>
+        <bundle>mvn:org.ops4j.pax.web/pax-web-spi/1.0.1</bundle>
+        <bundle>mvn:org.ops4j.pax.web/pax-web-runtime/1.0.1</bundle>
+        <bundle>mvn:org.ops4j.pax.web/pax-web-jetty/1.0.1</bundle>
+    </feature>
+    <feature name="war" version="2.2.0" resolver="(obr)">
+        <config name="org.ops4j.pax.url.war">
+            org.ops4j.pax.url.war.importPaxLoggingPackages=true
+        </config>
+        <feature>http</feature>
+        <bundle start-level='30'>mvn:org.apache.karaf.shell/org.apache.karaf.shell.web/2.2.0</bundle>
+        <bundle>mvn:org.ops4j.pax.web/pax-web-jsp/1.0.1</bundle>
+        <bundle>mvn:org.ops4j.pax.web/pax-web-extender-war/1.0.1</bundle>
+        <bundle>mvn:org.ops4j.pax.web/pax-web-extender-whiteboard/1.0.1</bundle>
+        <bundle>mvn:org.ops4j.pax.web/pax-web-deployer/1.0.1</bundle>
+        <bundle>mvn:org.ops4j.pax.url/pax-url-war/1.2.5</bundle>
+    </feature>
+    <feature name="kar" version="2.2.0">
+        <bundle>mvn:org.apache.karaf.deployer/org.apache.karaf.deployer.kar/2.2.0</bundle>
+    </feature>
+    <feature name="webconsole-base" version="2.2.0">
+        <config name="org.apache.karaf.webconsole">
+            realm=karaf
+        </config>
+        <feature>http</feature>
+        <bundle>mvn:org.apache.felix/org.apache.felix.metatype/1.0.4</bundle>
+        <bundle>mvn:org.apache.karaf.webconsole/org.apache.karaf.webconsole.branding/2.2.0</bundle>
+        <bundle>mvn:org.apache.karaf.webconsole/org.apache.karaf.webconsole.console/2.2.0</bundle>
+    </feature>
+    <feature name="webconsole" version="2.2.0">
+        <feature version="2.2.0">webconsole-base</feature>
+        <bundle>mvn:org.apache.karaf.webconsole/org.apache.karaf.webconsole.admin/2.2.0</bundle>
+        <bundle>mvn:org.apache.karaf.webconsole/org.apache.karaf.webconsole.features/2.2.0</bundle>
+        <bundle>mvn:org.apache.karaf.webconsole/org.apache.karaf.webconsole.gogo/2.2.0</bundle>
+		<bundle>mvn:org.apache.felix/org.apache.felix.webconsole.plugins.event/1.0.2</bundle>
+    </feature>
+    <feature name="ssh" version="2.2.0">
+        <config name="org.apache.karaf.shell">
+            sshPort=8101
+            sshHost=0.0.0.0
+            sshRealm=karaf
+            hostKey=${karaf.etc}/host.key
+        </config>
+        <bundle dependency='true'>mvn:org.apache.mina/mina-core/2.0.1</bundle>
+        <bundle dependency='true'>mvn:org.apache.sshd/sshd-core/0.5.0</bundle>
+        <bundle>mvn:org.apache.karaf.shell/org.apache.karaf.shell.ssh/2.2.0</bundle>
+    </feature>
+    <feature name="management" version="2.2.0">
+        <bundle>mvn:org.apache.karaf/org.apache.karaf.management/2.2.0</bundle>
+        <bundle>mvn:org.apache.aries.jmx/org.apache.aries.jmx/0.3</bundle>
+        <bundle>mvn:org.apache.aries.jmx/org.apache.aries.jmx.blueprint/0.3</bundle>
+    </feature>
+    <feature name="eventadmin" version="2.2.0">
+		<bundle start-level='30'>mvn:org.apache.felix/org.apache.felix.eventadmin/1.2.8</bundle>
+    </feature>
+    <feature name="jasypt-encryption" version="2.2.0" resolver="(obr)">
+        <bundle dependency='true'>mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.commons-codec/1.3_3</bundle>
+        <bundle dependency='true'>mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.commons-lang/2.4_4</bundle>
+        <bundle dependency='true'>mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.jasypt/1.7_1</bundle>
+        <bundle>mvn:org.apache.karaf.jaas/org.apache.karaf.jaas.jasypt/2.2.0</bundle>
+    </feature>
+</features>

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/src/test/resources/org/apache/karaf/features/internal/service/f03.xml
----------------------------------------------------------------------
diff --git a/features/src/test/resources/org/apache/karaf/features/internal/service/f03.xml b/features/src/test/resources/org/apache/karaf/features/internal/service/f03.xml
new file mode 100644
index 0000000..c058095
--- /dev/null
+++ b/features/src/test/resources/org/apache/karaf/features/internal/service/f03.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+    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.
+-->
+<features xmlns="http://karaf.apache.org/xmlns/features/v1.0.0">
+    <feature name="spring" version="2.5.6.SEC02" resolver="(obr)">
+        <bundle dependency='true'>mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.aopalliance/1.0_6</bundle>
+        <bundle>mvn:org.springframework/spring-core/2.5.6.SEC02</bundle>
+        <bundle>mvn:org.springframework/spring-beans/2.5.6.SEC02</bundle>
+        <bundle>mvn:org.springframework/spring-aop/2.5.6.SEC02</bundle>
+        <bundle>mvn:org.springframework/spring-context/2.5.6.SEC02</bundle>
+        <bundle>mvn:org.springframework/spring-context-support/2.5.6.SEC02</bundle>
+    </feature>
+</features>

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/src/test/resources/org/apache/karaf/features/internal/service/f04.xml
----------------------------------------------------------------------
diff --git a/features/src/test/resources/org/apache/karaf/features/internal/service/f04.xml b/features/src/test/resources/org/apache/karaf/features/internal/service/f04.xml
new file mode 100644
index 0000000..85f28ad
--- /dev/null
+++ b/features/src/test/resources/org/apache/karaf/features/internal/service/f04.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+    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.
+-->
+<features name="karaf" xmlns="http://karaf.apache.org/xmlns/features/v1.1.0">
+    <feature name="spring" version="2.5.6.SEC02" resolver="(obr)">
+        <bundle dependency='true'>mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.aopalliance/1.0_6</bundle>
+        <bundle>mvn:org.springframework/spring-core/2.5.6.SEC02</bundle>
+        <bundle>mvn:org.springframework/spring-beans/2.5.6.SEC02</bundle>
+        <bundle>mvn:org.springframework/spring-aop/2.5.6.SEC02</bundle>
+        <bundle>mvn:org.springframework/spring-context/2.5.6.SEC02</bundle>
+        <bundle>mvn:org.springframework/spring-context-support/2.5.6.SEC02</bundle>
+    </feature>
+</features>
+

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/src/test/resources/org/apache/karaf/features/internal/service/f05.xml
----------------------------------------------------------------------
diff --git a/features/src/test/resources/org/apache/karaf/features/internal/service/f05.xml b/features/src/test/resources/org/apache/karaf/features/internal/service/f05.xml
new file mode 100644
index 0000000..15d84e2
--- /dev/null
+++ b/features/src/test/resources/org/apache/karaf/features/internal/service/f05.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+    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.
+-->
+<features xmlns="http://karaf.apache.org/xmlns/features/v1.1.0">
+    <feature name="spring" version="2.5.6.SEC02" resolver="(obr)">
+        <bundle dependency='true'>mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.aopalliance/1.0_6</bundle>
+        <bundle>mvn:org.springframework/spring-core/2.5.6.SEC02</bundle>
+        <bundle>mvn:org.springframework/spring-beans/2.5.6.SEC02</bundle>
+        <bundle>mvn:org.springframework/spring-aop/2.5.6.SEC02</bundle>
+        <bundle>mvn:org.springframework/spring-context/2.5.6.SEC02</bundle>
+        <bundle>mvn:org.springframework/spring-context-support/2.5.6.SEC02</bundle>
+    </feature>
+</features>
+

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/src/test/resources/org/apache/karaf/features/internal/service/f06.xml
----------------------------------------------------------------------
diff --git a/features/src/test/resources/org/apache/karaf/features/internal/service/f06.xml b/features/src/test/resources/org/apache/karaf/features/internal/service/f06.xml
new file mode 100644
index 0000000..496cbdb
--- /dev/null
+++ b/features/src/test/resources/org/apache/karaf/features/internal/service/f06.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+    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.
+-->
+<features name="karaf" xmlns="http://karaf.apache.org/xmlns/features/v1.2.0">
+    <feature name="spring" version="2.5.6.SEC02" resolver="(obr)">
+        <bundle dependency='true'>mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.aopalliance/1.0_4</bundle>
+        <bundle>mvn:org.springframework/spring-core/2.5.6.SEC02</bundle>
+        <bundle>mvn:org.springframework/spring-beans/2.5.6.SEC02</bundle>
+        <bundle>mvn:org.springframework/spring-aop/2.5.6.SEC02</bundle>
+        <bundle>mvn:org.springframework/spring-context/2.5.6.SEC02</bundle>
+        <bundle>mvn:org.springframework/spring-context-support/2.5.6.SEC02</bundle>
+        <conditional>
+            <condition>http</condition>
+            <bundle>mvn:org.springframework/spring-web/2.5.6.SEC02</bundle>
+        </conditional>
+    </feature>
+</features>
+

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/src/test/resources/org/apache/karaf/features/internal/service/f07.xml
----------------------------------------------------------------------
diff --git a/features/src/test/resources/org/apache/karaf/features/internal/service/f07.xml b/features/src/test/resources/org/apache/karaf/features/internal/service/f07.xml
new file mode 100644
index 0000000..5b7dd90
--- /dev/null
+++ b/features/src/test/resources/org/apache/karaf/features/internal/service/f07.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+    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.
+-->
+<features name="karaf" xmlns="http://karaf.apache.org/xmlns/features/v1.3.0">
+    <feature name="spring" version="2.5.6.SEC02" resolver="(obr)">
+        <bundle dependency='true'>mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.aopalliance/1.0_4</bundle>
+        <bundle>mvn:org.springframework/spring-core/2.5.6.SEC02</bundle>
+        <bundle>mvn:org.springframework/spring-beans/2.5.6.SEC02</bundle>
+        <bundle>mvn:org.springframework/spring-aop/2.5.6.SEC02</bundle>
+        <bundle>mvn:org.springframework/spring-context/2.5.6.SEC02</bundle>
+        <bundle>mvn:org.springframework/spring-context-support/2.5.6.SEC02</bundle>
+        <conditional>
+            <condition>http</condition>
+            <bundle>mvn:org.springframework/spring-web/2.5.6.SEC02</bundle>
+        </conditional>
+        <capability>
+            service-reference;effective:=active;objectClass=org.apache.aries.proxy.ProxyManager
+        </capability>
+    </feature>
+</features>
+

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/src/test/resources/org/apache/karaf/features/internal/service/overrides.properties
----------------------------------------------------------------------
diff --git a/features/src/test/resources/org/apache/karaf/features/internal/service/overrides.properties b/features/src/test/resources/org/apache/karaf/features/internal/service/overrides.properties
new file mode 100644
index 0000000..d34fa7e
--- /dev/null
+++ b/features/src/test/resources/org/apache/karaf/features/internal/service/overrides.properties
@@ -0,0 +1,23 @@
+
+################################################################################
+#
+#    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.
+#
+################################################################################
+
+# Sample etc/overrides.properties file for testing purposes
+mvn:org.apache.karaf.admin/org.apache.karaf.admin.command/2.3.0.redhat-61033X
+mvn:org.apache.karaf.admin/org.apache.karaf.admin.core/2.3.0.redhat-61033X;range=[2.3.0,2.5)

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/src/test/resources/org/apache/karaf/features/internal/service/repo2.xml
----------------------------------------------------------------------
diff --git a/features/src/test/resources/org/apache/karaf/features/internal/service/repo2.xml b/features/src/test/resources/org/apache/karaf/features/internal/service/repo2.xml
new file mode 100644
index 0000000..5fd51d0
--- /dev/null
+++ b/features/src/test/resources/org/apache/karaf/features/internal/service/repo2.xml
@@ -0,0 +1,41 @@
+<!--
+
+    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.
+-->
+<features name="repo2">
+    <feature name="common">
+        <bundle>b1</bundle>
+    </feature>
+    <feature name="f1">
+        <feature>common</feature>
+        <bundle>b2</bundle>
+    </feature>
+    <feature name="f2">
+        <feature>common</feature>
+        <feature>f1</feature>
+        <bundle>b3</bundle>
+    </feature>
+    <feature name="f3">
+        <feature>f1</feature>
+        <feature>f2</feature>
+    	<bundle>b4</bundle>
+    </feature>
+    <feature name="all">
+        <feature>f1</feature>
+        <feature>f2</feature>
+        <feature>f3</feature>
+    </feature>
+</features>

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/src/test/resources/org/apache/karaf/features/repo1.xml
----------------------------------------------------------------------
diff --git a/features/src/test/resources/org/apache/karaf/features/repo1.xml b/features/src/test/resources/org/apache/karaf/features/repo1.xml
new file mode 100644
index 0000000..641ef12
--- /dev/null
+++ b/features/src/test/resources/org/apache/karaf/features/repo1.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+    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.
+-->
+<features name="test" xmlns="http://karaf.apache.org/xmlns/features/v1.1.0">
+    <repository>urn:r1</repository>
+    <feature name="f1" region="foo">
+        <config name="c1">
+            k=v
+        </config>
+        <bundle>b1</bundle>
+        <bundle>b2</bundle>
+    </feature>
+    <feature name="f2">
+        <feature>f1</feature>
+        <bundle>b3</bundle>
+    </feature>
+    <feature name="f3">
+    	<configfile finalname="cf1" override="true">cfloc</configfile>
+    	<bundle>b4</bundle> 
+    </feature>
+</features>

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/src/test/resources/org/apache/karaf/features/repo2.xml
----------------------------------------------------------------------
diff --git a/features/src/test/resources/org/apache/karaf/features/repo2.xml b/features/src/test/resources/org/apache/karaf/features/repo2.xml
new file mode 100644
index 0000000..f5e96ae
--- /dev/null
+++ b/features/src/test/resources/org/apache/karaf/features/repo2.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+    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.
+-->
+<features name="test" xmlns="http://karaf.apache.org/xmlns/features/v1.0.0">
+    <repository>
+        urn:r1
+    </repository>
+    <feature name="f1" region="foo">
+        <config name="c1">
+            k=v
+        </config>
+        <bundle>b1</bundle>
+        <bundle>b2</bundle>
+    </feature>
+    <feature name="f2">
+        <feature>f1</feature>
+        <bundle>b3</bundle>
+    </feature>
+    <feature name="f3">
+    	<configfile finalname="cf1" override="true">cfloc</configfile>
+    	<bundle>b4</bundle> 
+    </feature>
+</features>

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/src/test/resources/org/apache/karaf/features/repo3.xml
----------------------------------------------------------------------
diff --git a/features/src/test/resources/org/apache/karaf/features/repo3.xml b/features/src/test/resources/org/apache/karaf/features/repo3.xml
new file mode 100644
index 0000000..ffe08ed
--- /dev/null
+++ b/features/src/test/resources/org/apache/karaf/features/repo3.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+    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.
+-->
+<features name="test" xmlns="http://karaf.apache.org/xmlns/features/v1.3.0">
+    <feature name="f1">
+        <capability>
+            cap
+        </capability>
+        <requirement>
+            req
+        </requirement>
+    </feature>
+</features>


[48/59] [abbrv] [KARAF-2852] Merge wrapper/core and wrapper/command

Posted by gn...@apache.org.
http://git-wip-us.apache.org/repos/asf/karaf/blob/4182735c/wrapper/core/src/main/resources/org/apache/karaf/wrapper/internal/aix/ppc32/karaf-wrapper
----------------------------------------------------------------------
diff --git a/wrapper/core/src/main/resources/org/apache/karaf/wrapper/internal/aix/ppc32/karaf-wrapper b/wrapper/core/src/main/resources/org/apache/karaf/wrapper/internal/aix/ppc32/karaf-wrapper
deleted file mode 100755
index 5215c2e..0000000
Binary files a/wrapper/core/src/main/resources/org/apache/karaf/wrapper/internal/aix/ppc32/karaf-wrapper and /dev/null differ

http://git-wip-us.apache.org/repos/asf/karaf/blob/4182735c/wrapper/core/src/main/resources/org/apache/karaf/wrapper/internal/aix/ppc32/libwrapper.a
----------------------------------------------------------------------
diff --git a/wrapper/core/src/main/resources/org/apache/karaf/wrapper/internal/aix/ppc32/libwrapper.a b/wrapper/core/src/main/resources/org/apache/karaf/wrapper/internal/aix/ppc32/libwrapper.a
deleted file mode 100755
index 4bcc342..0000000
Binary files a/wrapper/core/src/main/resources/org/apache/karaf/wrapper/internal/aix/ppc32/libwrapper.a and /dev/null differ

http://git-wip-us.apache.org/repos/asf/karaf/blob/4182735c/wrapper/core/src/main/resources/org/apache/karaf/wrapper/internal/aix/ppc64/karaf-wrapper
----------------------------------------------------------------------
diff --git a/wrapper/core/src/main/resources/org/apache/karaf/wrapper/internal/aix/ppc64/karaf-wrapper b/wrapper/core/src/main/resources/org/apache/karaf/wrapper/internal/aix/ppc64/karaf-wrapper
deleted file mode 100755
index 6ba0351..0000000
Binary files a/wrapper/core/src/main/resources/org/apache/karaf/wrapper/internal/aix/ppc64/karaf-wrapper and /dev/null differ

http://git-wip-us.apache.org/repos/asf/karaf/blob/4182735c/wrapper/core/src/main/resources/org/apache/karaf/wrapper/internal/aix/ppc64/libwrapper.a
----------------------------------------------------------------------
diff --git a/wrapper/core/src/main/resources/org/apache/karaf/wrapper/internal/aix/ppc64/libwrapper.a b/wrapper/core/src/main/resources/org/apache/karaf/wrapper/internal/aix/ppc64/libwrapper.a
deleted file mode 100755
index b569e3f..0000000
Binary files a/wrapper/core/src/main/resources/org/apache/karaf/wrapper/internal/aix/ppc64/libwrapper.a and /dev/null differ

http://git-wip-us.apache.org/repos/asf/karaf/blob/4182735c/wrapper/core/src/main/resources/org/apache/karaf/wrapper/internal/all/karaf-wrapper.jar
----------------------------------------------------------------------
diff --git a/wrapper/core/src/main/resources/org/apache/karaf/wrapper/internal/all/karaf-wrapper.jar b/wrapper/core/src/main/resources/org/apache/karaf/wrapper/internal/all/karaf-wrapper.jar
deleted file mode 100644
index 4db355b..0000000
Binary files a/wrapper/core/src/main/resources/org/apache/karaf/wrapper/internal/all/karaf-wrapper.jar and /dev/null differ

http://git-wip-us.apache.org/repos/asf/karaf/blob/4182735c/wrapper/core/src/main/resources/org/apache/karaf/wrapper/internal/hpux/parisc64/karaf-wrapper
----------------------------------------------------------------------
diff --git a/wrapper/core/src/main/resources/org/apache/karaf/wrapper/internal/hpux/parisc64/karaf-wrapper b/wrapper/core/src/main/resources/org/apache/karaf/wrapper/internal/hpux/parisc64/karaf-wrapper
deleted file mode 100755
index ad883d7..0000000
Binary files a/wrapper/core/src/main/resources/org/apache/karaf/wrapper/internal/hpux/parisc64/karaf-wrapper and /dev/null differ

http://git-wip-us.apache.org/repos/asf/karaf/blob/4182735c/wrapper/core/src/main/resources/org/apache/karaf/wrapper/internal/hpux/parisc64/libwrapper.sl
----------------------------------------------------------------------
diff --git a/wrapper/core/src/main/resources/org/apache/karaf/wrapper/internal/hpux/parisc64/libwrapper.sl b/wrapper/core/src/main/resources/org/apache/karaf/wrapper/internal/hpux/parisc64/libwrapper.sl
deleted file mode 100755
index 08adc52..0000000
Binary files a/wrapper/core/src/main/resources/org/apache/karaf/wrapper/internal/hpux/parisc64/libwrapper.sl and /dev/null differ

http://git-wip-us.apache.org/repos/asf/karaf/blob/4182735c/wrapper/core/src/main/resources/org/apache/karaf/wrapper/internal/linux/karaf-wrapper
----------------------------------------------------------------------
diff --git a/wrapper/core/src/main/resources/org/apache/karaf/wrapper/internal/linux/karaf-wrapper b/wrapper/core/src/main/resources/org/apache/karaf/wrapper/internal/linux/karaf-wrapper
deleted file mode 100644
index 7e00645..0000000
Binary files a/wrapper/core/src/main/resources/org/apache/karaf/wrapper/internal/linux/karaf-wrapper and /dev/null differ

http://git-wip-us.apache.org/repos/asf/karaf/blob/4182735c/wrapper/core/src/main/resources/org/apache/karaf/wrapper/internal/linux/libwrapper.so
----------------------------------------------------------------------
diff --git a/wrapper/core/src/main/resources/org/apache/karaf/wrapper/internal/linux/libwrapper.so b/wrapper/core/src/main/resources/org/apache/karaf/wrapper/internal/linux/libwrapper.so
deleted file mode 100644
index 2cc4ab3..0000000
Binary files a/wrapper/core/src/main/resources/org/apache/karaf/wrapper/internal/linux/libwrapper.so and /dev/null differ

http://git-wip-us.apache.org/repos/asf/karaf/blob/4182735c/wrapper/core/src/main/resources/org/apache/karaf/wrapper/internal/linux64/karaf-wrapper
----------------------------------------------------------------------
diff --git a/wrapper/core/src/main/resources/org/apache/karaf/wrapper/internal/linux64/karaf-wrapper b/wrapper/core/src/main/resources/org/apache/karaf/wrapper/internal/linux64/karaf-wrapper
deleted file mode 100644
index 3128b95..0000000
Binary files a/wrapper/core/src/main/resources/org/apache/karaf/wrapper/internal/linux64/karaf-wrapper and /dev/null differ

http://git-wip-us.apache.org/repos/asf/karaf/blob/4182735c/wrapper/core/src/main/resources/org/apache/karaf/wrapper/internal/linux64/libwrapper.so
----------------------------------------------------------------------
diff --git a/wrapper/core/src/main/resources/org/apache/karaf/wrapper/internal/linux64/libwrapper.so b/wrapper/core/src/main/resources/org/apache/karaf/wrapper/internal/linux64/libwrapper.so
deleted file mode 100644
index 24197bf..0000000
Binary files a/wrapper/core/src/main/resources/org/apache/karaf/wrapper/internal/linux64/libwrapper.so and /dev/null differ

http://git-wip-us.apache.org/repos/asf/karaf/blob/4182735c/wrapper/core/src/main/resources/org/apache/karaf/wrapper/internal/macosx/karaf-wrapper
----------------------------------------------------------------------
diff --git a/wrapper/core/src/main/resources/org/apache/karaf/wrapper/internal/macosx/karaf-wrapper b/wrapper/core/src/main/resources/org/apache/karaf/wrapper/internal/macosx/karaf-wrapper
deleted file mode 100644
index 0165db0..0000000
Binary files a/wrapper/core/src/main/resources/org/apache/karaf/wrapper/internal/macosx/karaf-wrapper and /dev/null differ

http://git-wip-us.apache.org/repos/asf/karaf/blob/4182735c/wrapper/core/src/main/resources/org/apache/karaf/wrapper/internal/macosx/libwrapper.jnilib
----------------------------------------------------------------------
diff --git a/wrapper/core/src/main/resources/org/apache/karaf/wrapper/internal/macosx/libwrapper.jnilib b/wrapper/core/src/main/resources/org/apache/karaf/wrapper/internal/macosx/libwrapper.jnilib
deleted file mode 100644
index 6356705..0000000
Binary files a/wrapper/core/src/main/resources/org/apache/karaf/wrapper/internal/macosx/libwrapper.jnilib and /dev/null differ

http://git-wip-us.apache.org/repos/asf/karaf/blob/4182735c/wrapper/core/src/main/resources/org/apache/karaf/wrapper/internal/macosx/org.apache.karaf.KARAF.plist
----------------------------------------------------------------------
diff --git a/wrapper/core/src/main/resources/org/apache/karaf/wrapper/internal/macosx/org.apache.karaf.KARAF.plist b/wrapper/core/src/main/resources/org/apache/karaf/wrapper/internal/macosx/org.apache.karaf.KARAF.plist
deleted file mode 100644
index 1c18918..0000000
--- a/wrapper/core/src/main/resources/org/apache/karaf/wrapper/internal/macosx/org.apache.karaf.KARAF.plist
+++ /dev/null
@@ -1,36 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-
-    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.
-    -->
-<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<dict>
-	<key>ProcessType</key>
-	<string>Background</string>
-	<key>KeepAlive</key>
-	<false/>
-	<key>Label</key>
-	<string>org.apache.karaf.KARAF</string>
-	<key>ProgramArguments</key>
-	<array>
-		<!-- path to your KARAF-service wrapper -->
-		<string>${karaf.home}/bin/${name}-service</string>
-		<string>console</string>
-	</array>
-	<key>RunAtLoad</key>
-	<true/>
-</dict>
-</plist>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/karaf/blob/4182735c/wrapper/core/src/main/resources/org/apache/karaf/wrapper/internal/solaris/sparc32/karaf-wrapper
----------------------------------------------------------------------
diff --git a/wrapper/core/src/main/resources/org/apache/karaf/wrapper/internal/solaris/sparc32/karaf-wrapper b/wrapper/core/src/main/resources/org/apache/karaf/wrapper/internal/solaris/sparc32/karaf-wrapper
deleted file mode 100755
index 7cac208..0000000
Binary files a/wrapper/core/src/main/resources/org/apache/karaf/wrapper/internal/solaris/sparc32/karaf-wrapper and /dev/null differ

http://git-wip-us.apache.org/repos/asf/karaf/blob/4182735c/wrapper/core/src/main/resources/org/apache/karaf/wrapper/internal/solaris/sparc32/libwrapper.so
----------------------------------------------------------------------
diff --git a/wrapper/core/src/main/resources/org/apache/karaf/wrapper/internal/solaris/sparc32/libwrapper.so b/wrapper/core/src/main/resources/org/apache/karaf/wrapper/internal/solaris/sparc32/libwrapper.so
deleted file mode 100755
index 4093262..0000000
Binary files a/wrapper/core/src/main/resources/org/apache/karaf/wrapper/internal/solaris/sparc32/libwrapper.so and /dev/null differ

http://git-wip-us.apache.org/repos/asf/karaf/blob/4182735c/wrapper/core/src/main/resources/org/apache/karaf/wrapper/internal/solaris/sparc64/karaf-wrapper
----------------------------------------------------------------------
diff --git a/wrapper/core/src/main/resources/org/apache/karaf/wrapper/internal/solaris/sparc64/karaf-wrapper b/wrapper/core/src/main/resources/org/apache/karaf/wrapper/internal/solaris/sparc64/karaf-wrapper
deleted file mode 100755
index 91257c6..0000000
Binary files a/wrapper/core/src/main/resources/org/apache/karaf/wrapper/internal/solaris/sparc64/karaf-wrapper and /dev/null differ

http://git-wip-us.apache.org/repos/asf/karaf/blob/4182735c/wrapper/core/src/main/resources/org/apache/karaf/wrapper/internal/solaris/sparc64/libwrapper.so
----------------------------------------------------------------------
diff --git a/wrapper/core/src/main/resources/org/apache/karaf/wrapper/internal/solaris/sparc64/libwrapper.so b/wrapper/core/src/main/resources/org/apache/karaf/wrapper/internal/solaris/sparc64/libwrapper.so
deleted file mode 100755
index 008bef6..0000000
Binary files a/wrapper/core/src/main/resources/org/apache/karaf/wrapper/internal/solaris/sparc64/libwrapper.so and /dev/null differ

http://git-wip-us.apache.org/repos/asf/karaf/blob/4182735c/wrapper/core/src/main/resources/org/apache/karaf/wrapper/internal/solaris/x86/karaf-wrapper
----------------------------------------------------------------------
diff --git a/wrapper/core/src/main/resources/org/apache/karaf/wrapper/internal/solaris/x86/karaf-wrapper b/wrapper/core/src/main/resources/org/apache/karaf/wrapper/internal/solaris/x86/karaf-wrapper
deleted file mode 100755
index bdec254..0000000
Binary files a/wrapper/core/src/main/resources/org/apache/karaf/wrapper/internal/solaris/x86/karaf-wrapper and /dev/null differ

http://git-wip-us.apache.org/repos/asf/karaf/blob/4182735c/wrapper/core/src/main/resources/org/apache/karaf/wrapper/internal/solaris/x86/libwrapper.so
----------------------------------------------------------------------
diff --git a/wrapper/core/src/main/resources/org/apache/karaf/wrapper/internal/solaris/x86/libwrapper.so b/wrapper/core/src/main/resources/org/apache/karaf/wrapper/internal/solaris/x86/libwrapper.so
deleted file mode 100755
index 963ff49..0000000
Binary files a/wrapper/core/src/main/resources/org/apache/karaf/wrapper/internal/solaris/x86/libwrapper.so and /dev/null differ

http://git-wip-us.apache.org/repos/asf/karaf/blob/4182735c/wrapper/core/src/main/resources/org/apache/karaf/wrapper/internal/solaris/x86_64/karaf-wrapper
----------------------------------------------------------------------
diff --git a/wrapper/core/src/main/resources/org/apache/karaf/wrapper/internal/solaris/x86_64/karaf-wrapper b/wrapper/core/src/main/resources/org/apache/karaf/wrapper/internal/solaris/x86_64/karaf-wrapper
deleted file mode 100755
index 6bd165e..0000000
Binary files a/wrapper/core/src/main/resources/org/apache/karaf/wrapper/internal/solaris/x86_64/karaf-wrapper and /dev/null differ

http://git-wip-us.apache.org/repos/asf/karaf/blob/4182735c/wrapper/core/src/main/resources/org/apache/karaf/wrapper/internal/solaris/x86_64/libwrapper.so
----------------------------------------------------------------------
diff --git a/wrapper/core/src/main/resources/org/apache/karaf/wrapper/internal/solaris/x86_64/libwrapper.so b/wrapper/core/src/main/resources/org/apache/karaf/wrapper/internal/solaris/x86_64/libwrapper.so
deleted file mode 100755
index 0d52ffa..0000000
Binary files a/wrapper/core/src/main/resources/org/apache/karaf/wrapper/internal/solaris/x86_64/libwrapper.so and /dev/null differ

http://git-wip-us.apache.org/repos/asf/karaf/blob/4182735c/wrapper/core/src/main/resources/org/apache/karaf/wrapper/internal/unix/karaf-service
----------------------------------------------------------------------
diff --git a/wrapper/core/src/main/resources/org/apache/karaf/wrapper/internal/unix/karaf-service b/wrapper/core/src/main/resources/org/apache/karaf/wrapper/internal/unix/karaf-service
deleted file mode 100644
index a7ca8bb..0000000
--- a/wrapper/core/src/main/resources/org/apache/karaf/wrapper/internal/unix/karaf-service
+++ /dev/null
@@ -1,557 +0,0 @@
-#! /bin/sh
-
-# ------------------------------------------------------------------------
-# 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.
-# ------------------------------------------------------------------------
-
-# If require, set the JAVA_HOME to launch the wrapper
-#
-#JAVA_HOME=
-#
-
-# Application
-APP_NAME="${name}"
-APP_LONG_NAME="${displayName}"
-
-# Wrapper
-WRAPPER_CMD="${karaf.base}/bin/${APP_NAME}-wrapper"
-WRAPPER_CONF="${karaf.etc}/${APP_NAME}-wrapper.conf"
-
-# Priority at which to run the wrapper.  See "man nice" for valid priorities.
-#  nice is only used if a priority is specified.
-PRIORITY=
-
-# Location of the data folder.
-DATADIR="${karaf.data}"
-
-# Location of the pid file.
-PIDDIR="${karaf.data}"
-
-# If uncommented, causes the Wrapper to be shutdown using an anchor file.
-#  When launched with the 'start' command, it will also ignore all INT and
-#  TERM signals.
-#IGNORE_SIGNALS=true
-
-# If specified, the Wrapper will be run as the specified user.
-# IMPORTANT - Make sure that the user has the required privileges to write
-#  the PID file and wrapper.log files.  Failure to be able to write the log
-#  file will cause the Wrapper to exit without any way to write out an error
-#  message.
-# NOTE - This will set the user which is used to run the Wrapper as well as
-#  the JVM and is not useful in situations where a privileged resource or
-#  port needs to be allocated prior to the user being changed.
-#RUN_AS_USER=
-
-# The following two lines are used by the chkconfig command. Change as is
-#  appropriate for your application.  They should remain commented.
-# chkconfig: 2345 20 80
-# description: ${displayName}
-
-# Do not modify anything beyond this point
-#-----------------------------------------------------------------------------
-
-# Get the fully qualified path to the script
-case $0 in
-    /*)
-        SCRIPT="$0"
-        ;;
-    *)
-        PWD=`pwd`
-        SCRIPT="$PWD/$0"
-        ;;
-esac
-
-# Resolve the true real path without any sym links.
-CHANGED=true
-while [ "X$CHANGED" != "X" ]
-do
-    # Change spaces to ":" so the tokens can be parsed.
-    SCRIPT=`echo $SCRIPT | sed -e 's; ;:;g'`
-    # Get the real path to this script, resolving any symbolic links
-    TOKENS=`echo $SCRIPT | sed -e 's;/; ;g'`
-    REALPATH=
-    for C in $TOKENS; do
-        REALPATH="$REALPATH/$C"
-        while [ -h "$REALPATH" ] ; do
-            LS="`ls -ld "$REALPATH"`"
-            LINK="`expr "$LS" : '.*-> \(.*\)$'`"
-            if expr "$LINK" : '/.*' > /dev/null; then
-                REALPATH="$LINK"
-            else
-                REALPATH="`dirname "$REALPATH"`""/$LINK"
-            fi
-        done
-    done
-    # Change ":" chars back to spaces.
-    REALPATH=`echo $REALPATH | sed -e 's;:; ;g'`
-
-    if [ "$REALPATH" = "$SCRIPT" ]
-    then
-        CHANGED=""
-    else
-        SCRIPT="$REALPATH"
-    fi
-done
-
-# Change the current directory to the location of the script
-cd "`dirname "$REALPATH"`"
-REALDIR=`pwd`
-
-# If the PIDDIR is relative, set its value relative to the full REALPATH to avoid problems if
-#  the working directory is later changed.
-FIRST_CHAR=`echo $PIDDIR | cut -c1,1`
-if [ "$FIRST_CHAR" != "/" ]
-then
-    PIDDIR=$REALDIR/$PIDDIR
-fi
-# Same test for WRAPPER_CMD
-FIRST_CHAR=`echo $WRAPPER_CMD | cut -c1,1`
-if [ "$FIRST_CHAR" != "/" ]
-then
-    WRAPPER_CMD=$REALDIR/$WRAPPER_CMD
-fi
-# Same test for WRAPPER_CONF
-FIRST_CHAR=`echo $WRAPPER_CONF | cut -c1,1`
-if [ "$FIRST_CHAR" != "/" ]
-then
-    WRAPPER_CONF=$REALDIR/$WRAPPER_CONF
-fi
-
-# Process ID
-ANCHORFILE="$PIDDIR/$APP_NAME.anchor"
-PIDFILE="$PIDDIR/$APP_NAME.pid"
-LOCKDIR="/var/lock/subsys"
-LOCKFILE="$LOCKDIR/$APP_NAME"
-pid=""
-
-# Resolve the location of the 'ps' command
-PSEXE="/usr/bin/ps"
-if [ ! -x $PSEXE ]
-then
-    PSEXE="/bin/ps"
-    if [ ! -x $PSEXE ]
-    then
-        echo "Unable to locate 'ps'."
-        echo "Please report this message along with the location of the command on your system."
-        exit 1
-    fi
-fi
-
-# Resolve the os
-DIST_OS=`uname -s | tr [:upper:] [:lower:] | tr -d [:blank:]`
-case "$DIST_OS" in
-    'sunos')
-        DIST_OS="solaris"
-        ;;
-    'hp-ux' | 'hp-ux64')
-        DIST_OS="hpux"
-        ;;
-    'darwin')
-        DIST_OS="macosx"
-        ;;
-    'unix_sv')
-        DIST_OS="unixware"
-        ;;
-esac
-
-# Resolve the architecture
-DIST_ARCH=`uname -p | tr [:upper:] [:lower:] | tr -d [:blank:]`
-if [ "$DIST_ARCH" = "unknown" ]
-then
-    DIST_ARCH=`uname -m | tr [:upper:] [:lower:] | tr -d [:blank:]`
-fi
-case "$DIST_ARCH" in
-    'amd64' | 'ia32' | 'ia64' | 'i386' | 'i486' | 'i586' | 'i686' | 'x86_64')
-        DIST_ARCH="x86"
-        ;;
-    'ip27')
-        DIST_ARCH="mips"
-        ;;
-    'power' | 'powerpc' | 'power_pc' | 'ppc64')
-        DIST_ARCH="ppc"
-        ;;
-    'pa_risc' | 'pa-risc')
-        DIST_ARCH="parisc"
-        ;;
-    'sun4u' | 'sparcv9')
-        DIST_ARCH="sparc"
-        ;;
-    '9000/800')
-        DIST_ARCH="parisc"
-        ;;
-esac
-
-# Decide on the wrapper binary to use.
-# If a 32-bit wrapper binary exists then it will work on 32 or 64 bit
-#  platforms, if the 64-bit binary exists then the distribution most
-#  likely wants to use long names.  Otherwise, look for the default.
-# For macosx, we also want to look for universal binaries.
-WRAPPER_TEST_CMD="$WRAPPER_CMD-$DIST_OS-$DIST_ARCH-32"
-if [ -x $WRAPPER_TEST_CMD ]
-then
-    WRAPPER_CMD="$WRAPPER_TEST_CMD"
-else
-    if [ "$DIST_OS" = "macosx" ]
-    then
-        WRAPPER_TEST_CMD="$WRAPPER_CMD-$DIST_OS-universal-32"
-        if [ -x $WRAPPER_TEST_CMD ]
-        then
-            WRAPPER_CMD="$WRAPPER_TEST_CMD"
-        else
-            WRAPPER_TEST_CMD="$WRAPPER_CMD-$DIST_OS-$DIST_ARCH-64"
-            if [ -x $WRAPPER_TEST_CMD ]
-            then
-                WRAPPER_CMD="$WRAPPER_TEST_CMD"
-            else
-                WRAPPER_TEST_CMD="$WRAPPER_CMD-$DIST_OS-universal-64"
-                if [ -x $WRAPPER_TEST_CMD ]
-                then
-                    WRAPPER_CMD="$WRAPPER_TEST_CMD"
-                else
-                    if [ ! -x $WRAPPER_CMD ]
-                    then
-                        echo "Unable to locate any of the following binaries:"
-                        echo "  $WRAPPER_CMD-$DIST_OS-$DIST_ARCH-32"
-                        echo "  $WRAPPER_CMD-$DIST_OS-universal-32"
-                        echo "  $WRAPPER_CMD-$DIST_OS-$DIST_ARCH-64"
-                        echo "  $WRAPPER_CMD-$DIST_OS-universal-64"
-                        echo "  $WRAPPER_CMD"
-                        exit 1
-                    fi
-                fi
-            fi
-        fi
-    else
-        WRAPPER_TEST_CMD="$WRAPPER_CMD-$DIST_OS-$DIST_ARCH-64"
-        if [ -x $WRAPPER_TEST_CMD ]
-        then
-            WRAPPER_CMD="$WRAPPER_TEST_CMD"
-        else
-            if [ ! -x $WRAPPER_CMD ]
-            then
-                echo "Unable to locate any of the following binaries:"
-                echo "  $WRAPPER_CMD-$DIST_OS-$DIST_ARCH-32"
-                echo "  $WRAPPER_CMD-$DIST_OS-$DIST_ARCH-64"
-                echo "  $WRAPPER_CMD"
-                exit 1
-            fi
-        fi
-    fi
-fi
-
-# Build the nice clause
-if [ "X$PRIORITY" = "X" ]
-then
-    CMDNICE=""
-else
-    CMDNICE="nice -$PRIORITY"
-fi
-
-# Build the anchor file clause.
-if [ "X$IGNORE_SIGNALS" = "X" ]
-then
-   ANCHORPROP=
-   IGNOREPROP=
-else
-   ANCHORPROP=wrapper.anchorfile=$ANCHORFILE
-   IGNOREPROP=wrapper.ignore_signals=TRUE
-fi
-
-# Build the lock file clause.  Only create a lock file if the lock directory exists on this platform.
-if [ -d $LOCKDIR ]
-then
-    LOCKPROP=wrapper.lockfile=$LOCKFILE
-else
-    LOCKPROP=
-fi
-
-checkUser() {
-    # Check the configured user.  If necessary rerun this script as the desired user.
-    if [ "X$RUN_AS_USER" != "X" ]
-    then
-        # Resolve the location of the 'id' command
-        IDEXE="/usr/xpg4/bin/id"
-        if [ ! -x $IDEXE ]
-        then
-            IDEXE="/usr/bin/id"
-            if [ ! -x $IDEXE ]
-            then
-                echo "Unable to locate 'id'."
-                echo "Please report this message along with the location of the command on your system."
-                exit 1
-            fi
-        fi
-
-        if [ "`$IDEXE -u -n`" = "$RUN_AS_USER" ]
-        then
-            # Already running as the configured user.  Avoid password prompts by not calling su.
-            RUN_AS_USER=""
-        fi
-    fi
-    if [ "X$RUN_AS_USER" != "X" ]
-    then
-        # If LOCKPROP and $RUN_AS_USER are defined then the new user will most likely not be
-        # able to create the lock file.  The Wrapper will be able to update this file once it
-        # is created but will not be able to delete it on shutdown.  If $2 is defined then
-        # the lock file should be created for the current command
-        if [ "X$LOCKPROP" != "X" ]
-        then
-            if [ "X$2" != "X" ]
-            then
-                # Resolve the primary group
-                RUN_AS_GROUP=`groups $RUN_AS_USER | awk '{print $3}' | tail -1`
-                if [ "X$RUN_AS_GROUP" = "X" ]
-                then
-                    RUN_AS_GROUP=$RUN_AS_USER
-                fi
-                touch $LOCKFILE
-                chown $RUN_AS_USER:$RUN_AS_GROUP $LOCKFILE
-            fi
-        fi
-
-        # Still want to change users, recurse.  This means that the user will only be
-        #  prompted for a password once.
-        su -m $RUN_AS_USER -s /bin/sh -c "$REALPATH $1"
-        RETVAL=$?
-
-        # Now that we are the original user again, we may need to clean up the lock file.
-        if [ "X$LOCKPROP" != "X" ]
-        then
-            getpid
-            if [ "X$pid" = "X" ]
-            then
-                # Wrapper is not running so make sure the lock file is deleted.
-                if [ -f $LOCKFILE ]
-                then
-                    rm $LOCKFILE
-                fi
-            fi
-        fi
-
-        exit $RETVAL
-    fi
-}
-
-getpid() {
-    if [ -f $PIDFILE ]
-    then
-        if [ -r $PIDFILE ]
-        then
-            pid=`cat $PIDFILE`
-            if [ "X$pid" != "X" ]
-            then
-                # It is possible that 'a' process with the pid exists but that it is not the
-                #  correct process.  This can happen in a number of cases, but the most
-                #  common is during system startup after an unclean shutdown.
-                # The ps statement below looks for the specific wrapper command running as
-                #  the pid.  If it is not found then the pid file is considered to be stale.
-                if [ "$DIST_OS" = "solaris" ]
-                then
-                    pidtest=`$PSEXE -p $pid -o comm | grep $WRAPPER_CMD | tail -1`
-                else
-                    pidtest=`$PSEXE -p $pid -o command | grep $WRAPPER_CMD | tail -1`
-                fi
-                if [ "X$pidtest" = "X" ]
-                then
-                    # This is a stale pid file.
-                    rm -f $PIDFILE
-                    echo "Removed stale pid file: $PIDFILE"
-                    pid=""
-                fi
-            fi
-        else
-            echo "Cannot read $PIDFILE."
-            exit 1
-        fi
-    fi
-}
-
-testpid() {
-    pid=`$PSEXE -p $pid | grep $pid | grep -v grep | awk '{print $1}' | tail -1`
-    if [ "X$pid" = "X" ]
-    then
-        # Process is gone so remove the pid file.
-        rm -f $PIDFILE
-        pid=""
-    fi
-}
-
-console() {
-    echo "Running $APP_LONG_NAME..."
-    getpid
-    if [ "X$pid" = "X" ]
-    then
-        COMMAND_LINE="$CMDNICE $WRAPPER_CMD $WRAPPER_CONF wrapper.syslog.ident=$APP_NAME wrapper.pidfile=$PIDFILE $ANCHORPROP $LOCKPROP"
-        exec $COMMAND_LINE
-    else
-        echo "$APP_LONG_NAME is already running."
-        exit 1
-    fi
-}
-
-start() {
-    echo "Starting $APP_LONG_NAME..."
-    getpid
-    if [ "X$pid" = "X" ]
-    then
-        if [ ! -d $DATADIR ]; then
-            mkdir $DATADIR
-        fi
-        if [ ! -d $DATADIR/log ]; then
-            mkdir $DATADIR/log
-        fi
-        COMMAND_LINE="$CMDNICE $WRAPPER_CMD $WRAPPER_CONF wrapper.syslog.ident=$APP_NAME wrapper.pidfile=$PIDFILE wrapper.daemonize=TRUE $ANCHORPROP $IGNOREPROP $LOCKPROP"
-        exec $COMMAND_LINE
-    else
-        echo "$APP_LONG_NAME is already running."
-        exit 1
-    fi
-}
-
-stopit() {
-    echo "Stopping $APP_LONG_NAME..."
-    getpid
-    if [ "X$pid" = "X" ]
-    then
-        echo "$APP_LONG_NAME was not running."
-    else
-        if [ "X$IGNORE_SIGNALS" = "X" ]
-        then
-            # Running so try to stop it.
-            kill $pid
-            if [ $? -ne 0 ]
-            then
-                # An explanation for the failure should have been given
-                echo "Unable to stop $APP_LONG_NAME."
-                exit 1
-            fi
-        else
-            rm -f $ANCHORFILE
-            if [ -f $ANCHORFILE ]
-            then
-                # An explanation for the failure should have been given
-                echo "Unable to stop $APP_LONG_NAME."
-                exit 1
-            fi
-        fi
-
-        # We can not predict how long it will take for the wrapper to
-        #  actually stop as it depends on settings in wrapper.conf.
-        #  Loop until it does.
-        savepid=$pid
-        CNT=0
-        TOTCNT=0
-        while [ "X$pid" != "X" ]
-        do
-            # Show a waiting message every 5 seconds.
-            if [ "$CNT" -lt "5" ]
-            then
-                CNT=`expr $CNT + 1`
-            else
-                echo "Waiting for $APP_LONG_NAME to exit..."
-                CNT=0
-            fi
-            TOTCNT=`expr $TOTCNT + 1`
-
-            sleep 1
-
-            testpid
-        done
-
-        pid=$savepid
-        testpid
-        if [ "X$pid" != "X" ]
-        then
-            echo "Failed to stop $APP_LONG_NAME."
-            exit 1
-        else
-            echo "Stopped $APP_LONG_NAME."
-        fi
-    fi
-}
-
-status() {
-    getpid
-    if [ "X$pid" = "X" ]
-    then
-        echo "$APP_LONG_NAME is not running."
-        exit 1
-    else
-        echo "$APP_LONG_NAME is running ($pid)."
-        exit 0
-    fi
-}
-
-dump() {
-    echo "Dumping $APP_LONG_NAME..."
-    getpid
-    if [ "X$pid" = "X" ]
-    then
-        echo "$APP_LONG_NAME was not running."
-
-    else
-        kill -3 $pid
-
-        if [ $? -ne 0 ]
-        then
-            echo "Failed to dump $APP_LONG_NAME."
-            exit 1
-        else
-            echo "Dumped $APP_LONG_NAME."
-        fi
-    fi
-}
-
-case "$1" in
-
-    'console')
-        checkUser $1 touchlock
-        console
-        ;;
-
-    'start')
-        checkUser $1 touchlock
-        start
-        ;;
-
-    'stop')
-        checkUser $1
-        stopit
-        ;;
-
-    'restart')
-        checkUser $1 touchlock
-        stopit
-        start
-        ;;
-
-    'status')
-        checkUser $1
-        status
-        ;;
-
-    'dump')
-        checkUser $1
-        dump
-        ;;
-
-    *)
-        echo "Usage: $0 { console | start | stop | restart | status | dump }"
-        exit 1
-        ;;
-esac
-
-exit 0

http://git-wip-us.apache.org/repos/asf/karaf/blob/4182735c/wrapper/core/src/main/resources/org/apache/karaf/wrapper/internal/unix/karaf-wrapper.conf
----------------------------------------------------------------------
diff --git a/wrapper/core/src/main/resources/org/apache/karaf/wrapper/internal/unix/karaf-wrapper.conf b/wrapper/core/src/main/resources/org/apache/karaf/wrapper/internal/unix/karaf-wrapper.conf
deleted file mode 100644
index a3f98a5..0000000
--- a/wrapper/core/src/main/resources/org/apache/karaf/wrapper/internal/unix/karaf-wrapper.conf
+++ /dev/null
@@ -1,135 +0,0 @@
-# ------------------------------------------------------------------------
-# 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.
-# ------------------------------------------------------------------------
-
-#********************************************************************
-# Wrapper Properties
-#********************************************************************
-set.default.JAVA_HOME=${java.home}
-set.default.KARAF_HOME=${karaf.home}
-set.default.KARAF_BASE=${karaf.base}
-set.default.KARAF_DATA=${karaf.data}
-set.default.KARAF_ETC=${karaf.etc}
-
-# Java Application
-wrapper.working.dir=%KARAF_BASE%
-wrapper.java.command=%JAVA_HOME%/bin/java
-wrapper.java.mainclass=org.apache.karaf.wrapper.internal.Main
-wrapper.java.classpath.1=%KARAF_HOME%/lib/karaf-wrapper.jar
-wrapper.java.classpath.2=%KARAF_HOME%/lib/karaf.jar
-wrapper.java.classpath.3=%KARAF_HOME%/lib/karaf-jmx-boot.jar
-wrapper.java.classpath.4=%KARAF_HOME%/lib/karaf-jaas-boot.jar
-wrapper.java.classpath.5=%KARAF_HOME%/lib/karaf-wrapper-main.jar
-wrapper.java.classpath.6=%KARAF_HOME%/lib/karaf-org.osgi.core.jar
-wrapper.java.library.path.1=%KARAF_HOME%/lib/
-
-# Application Parameters.  Add parameters as needed starting from 1
-#wrapper.app.parameter.1=
-
-# JVM Parameters            
-# note that n is the parameter number starting from 1.
-wrapper.java.additional.1=-Dkaraf.home=%KARAF_HOME%
-wrapper.java.additional.2=-Dkaraf.base=%KARAF_BASE%
-wrapper.java.additional.3=-Dkaraf.data=%KARAF_DATA%
-wrapper.java.additional.4=-Dkaraf.etc=%KARAF_ETC%
-wrapper.java.additional.5=-Dcom.sun.management.jmxremote
-wrapper.java.additional.6=-Djavax.management.builder.initial=org.apache.karaf.management.boot.KarafMBeanServerBuilder
-wrapper.java.additional.7=-Dkaraf.startLocalConsole=false
-wrapper.java.additional.8=-Dkaraf.startRemoteShell=true
-wrapper.java.additional.9=-Djava.endorsed.dirs=%JAVA_HOME%/jre/lib/endorsed:%JAVA_HOME%/lib/endorsed:%KARAF_HOME%/lib/endorsed
-wrapper.java.additional.10=-Djava.ext.dirs=%JAVA_HOME%/jre/lib/ext:%JAVA_HOME%/lib/ext:%KARAF_HOME%/lib/ext
-
-# Uncomment to enable jmx
-#wrapper.java.additional.n=-Dcom.sun.management.jmxremote.port=1616
-#wrapper.java.additional.n=-Dcom.sun.management.jmxremote.authenticate=false
-#wrapper.java.additional.n=-Dcom.sun.management.jmxremote.ssl=false
-
-# Uncomment to enable YourKit profiling
-#wrapper.java.additional.n=-Xrunyjpagent
-
-# Uncomment to enable remote debugging
-#wrapper.java.additional.n=-Xdebug -Xnoagent -Djava.compiler=NONE
-#wrapper.java.additional.n=-Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005
-
-# Initial Java Heap Size (in MB)
-#wrapper.java.initmemory=3
-
-# Maximum Java Heap Size (in MB)
-wrapper.java.maxmemory=512
-
-
-#********************************************************************
-# Wrapper Logging Properties
-#********************************************************************
-# Format of output for the console.  (See docs for formats)
-wrapper.console.format=PM
-
-# Log Level for console output.  (See docs for log levels)
-wrapper.console.loglevel=INFO
-
-# Log file to use for wrapper output logging.
-wrapper.logfile=%KARAF_DATA%/log/wrapper.log
-
-# Format of output for the log file.  (See docs for formats)
-wrapper.logfile.format=LPTM
-
-# Log Level for log file output.  (See docs for log levels)
-wrapper.logfile.loglevel=INFO
-
-# Maximum size that the log file will be allowed to grow to before
-#  the log is rolled. Size is specified in bytes.  The default value
-#  of 0, disables log rolling.  May abbreviate with the 'k' (kb) or
-#  'm' (mb) suffix.  For example: 10m = 10 megabytes.
-wrapper.logfile.maxsize=10m
-
-# Maximum number of rolled log files which will be allowed before old
-#  files are deleted.  The default value of 0 implies no limit.
-wrapper.logfile.maxfiles=5
-
-# Log Level for sys/event log output.  (See docs for log levels)
-wrapper.syslog.loglevel=NONE
-
-#********************************************************************
-# Wrapper Windows Properties
-#********************************************************************
-# Title to use when running as a console
-wrapper.console.title=${name}
-
-#********************************************************************
-# Wrapper Windows NT/2000/XP Service Properties
-#********************************************************************
-# WARNING - Do not modify any of these properties when an application
-#  using this configuration file has been installed as a service.
-#  Please uninstall the service before modifying this section.  The
-#  service can then be reinstalled.
-
-# Name of the service
-wrapper.ntservice.name=${name}
-
-# Display name of the service
-wrapper.ntservice.displayname=${displayName}
-
-# Description of the service
-wrapper.ntservice.description=${description}
-
-# Service dependencies.  Add dependencies as needed starting from 1
-wrapper.ntservice.dependency.1=
-
-# Mode in which the service is installed.  AUTO_START or DEMAND_START
-wrapper.ntservice.starttype=${startType}
-
-# Allow the service to interact with the desktop.
-wrapper.ntservice.interactive=false

http://git-wip-us.apache.org/repos/asf/karaf/blob/4182735c/wrapper/core/src/main/resources/org/apache/karaf/wrapper/internal/windows/karaf-service.bat
----------------------------------------------------------------------
diff --git a/wrapper/core/src/main/resources/org/apache/karaf/wrapper/internal/windows/karaf-service.bat b/wrapper/core/src/main/resources/org/apache/karaf/wrapper/internal/windows/karaf-service.bat
deleted file mode 100644
index 0dd0474..0000000
--- a/wrapper/core/src/main/resources/org/apache/karaf/wrapper/internal/windows/karaf-service.bat
+++ /dev/null
@@ -1,51 +0,0 @@
-@echo off
-
-REM ------------------------------------------------------------------------
-REM Licensed to the Apache Software Foundation (ASF) under one or more
-REM contributor license agreements.  See the NOTICE file distributed with
-REM this work for additional information regarding copyright ownership.
-REM The ASF licenses this file to You under the Apache License, Version 2.0
-REM (the "License"); you may not use this file except in compliance with
-REM the License.  You may obtain a copy of the License at
-REM
-REM http://www.apache.org/licenses/LICENSE-2.0
-REM
-REM Unless required by applicable law or agreed to in writing, software
-REM distributed under the License is distributed on an "AS IS" BASIS,
-REM WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-REM See the License for the specific language governing permissions and
-REM limitations under the License.
-REM ------------------------------------------------------------------------
-
-setlocal
-
-set APP_NAME=${name}
-set APP_LONG_NAME=${displayName}
-set APP_BASE=${karaf.base}
-set APP_ETC=${karaf.etc}
-
-if ""%1"" == ""run"" goto doRun
-if ""%1"" == ""install"" goto doInstall
-if ""%1"" == ""remove"" goto doRemove
-
-echo Usage:  karaf-service ( commands ... )
-echo commands:
-echo   run               Start %APP_NAME% in the current console
-echo   install           Install %APP_NAME% as a Windows service
-echo   remove            Remove the %APP_NAME% Windows service
-goto end
-
-:doRun
-"%APP_BASE%\bin\%APP_NAME%-wrapper.exe" -c "%APP_ETC%\%APP_NAME%-wrapper.conf"
-goto end
-
-:doInstall
-"%APP_BASE%\bin\%APP_NAME%-wrapper.exe" -i "%APP_ETC%\%APP_NAME%-wrapper.conf"
-goto end
-
-:doRemove
-"%APP_BASE%\bin\%APP_NAME%-wrapper.exe" -r "%APP_ETC%\%APP_NAME%-wrapper.conf"
-goto end
-
-:end
-if not "%PAUSE%" == "" pause

http://git-wip-us.apache.org/repos/asf/karaf/blob/4182735c/wrapper/core/src/main/resources/org/apache/karaf/wrapper/internal/windows/karaf-wrapper.conf
----------------------------------------------------------------------
diff --git a/wrapper/core/src/main/resources/org/apache/karaf/wrapper/internal/windows/karaf-wrapper.conf b/wrapper/core/src/main/resources/org/apache/karaf/wrapper/internal/windows/karaf-wrapper.conf
deleted file mode 100644
index def40f7..0000000
--- a/wrapper/core/src/main/resources/org/apache/karaf/wrapper/internal/windows/karaf-wrapper.conf
+++ /dev/null
@@ -1,135 +0,0 @@
-# ------------------------------------------------------------------------
-# 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.
-# ------------------------------------------------------------------------
-
-#********************************************************************
-# Wrapper Properties
-#********************************************************************
-set.default.JAVA_HOME=${java.home}
-set.default.KARAF_HOME=${karaf.home}
-set.default.KARAF_BASE=${karaf.base}
-set.default.KARAF_DATA=${karaf.data}
-set.default.KARAF_ETC=${karaf.etc}
-
-# Java Application
-wrapper.working.dir=%KARAF_BASE%
-wrapper.java.command=%JAVA_HOME%/bin/java
-wrapper.java.mainclass=org.apache.karaf.wrapper.internal.Main
-wrapper.java.classpath.1=%KARAF_HOME%/lib/karaf-wrapper.jar
-wrapper.java.classpath.2=%KARAF_HOME%/lib/karaf.jar
-wrapper.java.classpath.3=%KARAF_HOME%/lib/karaf-jmx-boot.jar
-wrapper.java.classpath.4=%KARAF_HOME%/lib/karaf-jaas-boot.jar
-wrapper.java.classpath.5=%KARAF_HOME%/lib/karaf-wrapper-main.jar
-wrapper.java.classpath.6=%KARAF_HOME%/lib/karaf-org.osgi.core.jar
-wrapper.java.library.path.1=%KARAF_HOME%/lib/
-
-# Application Parameters.  Add parameters as needed starting from 1
-#wrapper.app.parameter.1=
-
-# JVM Parameters
-# note that n is the parameter number starting from 1.
-wrapper.java.additional.1=-Dkaraf.home="%KARAF_HOME%"
-wrapper.java.additional.2=-Dkaraf.base="%KARAF_BASE%"
-wrapper.java.additional.3=-Dkaraf.data="%KARAF_DATA%"
-wrapper.java.additional.4=-Dkaraf.etc="%KARAF_ETC%"
-wrapper.java.additional.5=-Dcom.sun.management.jmxremote
-wrapper.java.additional.6=-Djavax.management.builder.initial=org.apache.karaf.management.boot.KarafMBeanServerBuilder
-wrapper.java.additional.7=-Dkaraf.startLocalConsole=false
-wrapper.java.additional.8=-Dkaraf.startRemoteShell=true
-wrapper.java.additional.9=-Djava.endorsed.dirs="%JAVA_HOME%/jre/lib/endorsed;%JAVA_HOME%/lib/endorsed;%KARAF_HOME%/lib/endorsed"
-wrapper.java.additional.10=-Djava.ext.dirs="%JAVA_HOME%/jre/lib/ext;%JAVA_HOME%/lib/ext;%KARAF_HOME%/lib/ext"
-
-# Uncomment to enable jmx
-#wrapper.java.additional.n=-Dcom.sun.management.jmxremote.port=1616
-#wrapper.java.additional.n=-Dcom.sun.management.jmxremote.authenticate=false
-#wrapper.java.additional.n=-Dcom.sun.management.jmxremote.ssl=false
-
-# Uncomment to enable YourKit profiling
-#wrapper.java.additional.n=-Xrunyjpagent
-
-# Uncomment to enable remote debugging
-#wrapper.java.additional.n=-Xdebug -Xnoagent -Djava.compiler=NONE
-#wrapper.java.additional.n=-Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005
-
-# Initial Java Heap Size (in MB)
-#wrapper.java.initmemory=3
-
-# Maximum Java Heap Size (in MB)
-wrapper.java.maxmemory=512
-
-
-#********************************************************************
-# Wrapper Logging Properties
-#********************************************************************
-# Format of output for the console.  (See docs for formats)
-wrapper.console.format=PM
-
-# Log Level for console output.  (See docs for log levels)
-wrapper.console.loglevel=INFO
-
-# Log file to use for wrapper output logging.
-wrapper.logfile=%KARAF_DATA%/log/wrapper.log
-
-# Format of output for the log file.  (See docs for formats)
-wrapper.logfile.format=LPTM
-
-# Log Level for log file output.  (See docs for log levels)
-wrapper.logfile.loglevel=INFO
-
-# Maximum size that the log file will be allowed to grow to before
-#  the log is rolled. Size is specified in bytes.  The default value
-#  of 0, disables log rolling.  May abbreviate with the 'k' (kb) or
-#  'm' (mb) suffix.  For example: 10m = 10 megabytes.
-wrapper.logfile.maxsize=10m
-
-# Maximum number of rolled log files which will be allowed before old
-#  files are deleted.  The default value of 0 implies no limit.
-wrapper.logfile.maxfiles=5
-
-# Log Level for sys/event log output.  (See docs for log levels)
-wrapper.syslog.loglevel=NONE
-
-#********************************************************************
-# Wrapper Windows Properties
-#********************************************************************
-# Title to use when running as a console
-wrapper.console.title=${name}
-
-#********************************************************************
-# Wrapper Windows NT/2000/XP Service Properties
-#********************************************************************
-# WARNING - Do not modify any of these properties when an application
-#  using this configuration file has been installed as a service.
-#  Please uninstall the service before modifying this section.  The
-#  service can then be reinstalled.
-
-# Name of the service
-wrapper.ntservice.name=${name}
-
-# Display name of the service
-wrapper.ntservice.displayname=${displayName}
-
-# Description of the service
-wrapper.ntservice.description=${description}
-
-# Service dependencies.  Add dependencies as needed starting from 1
-wrapper.ntservice.dependency.1=
-
-# Mode in which the service is installed.  AUTO_START or DEMAND_START
-wrapper.ntservice.starttype=${startType}
-
-# Allow the service to interact with the desktop.
-wrapper.ntservice.interactive=false

http://git-wip-us.apache.org/repos/asf/karaf/blob/4182735c/wrapper/core/src/main/resources/org/apache/karaf/wrapper/internal/windows/karaf-wrapper.exe
----------------------------------------------------------------------
diff --git a/wrapper/core/src/main/resources/org/apache/karaf/wrapper/internal/windows/karaf-wrapper.exe b/wrapper/core/src/main/resources/org/apache/karaf/wrapper/internal/windows/karaf-wrapper.exe
deleted file mode 100644
index b4cfc55..0000000
Binary files a/wrapper/core/src/main/resources/org/apache/karaf/wrapper/internal/windows/karaf-wrapper.exe and /dev/null differ

http://git-wip-us.apache.org/repos/asf/karaf/blob/4182735c/wrapper/core/src/main/resources/org/apache/karaf/wrapper/internal/windows/wrapper.dll
----------------------------------------------------------------------
diff --git a/wrapper/core/src/main/resources/org/apache/karaf/wrapper/internal/windows/wrapper.dll b/wrapper/core/src/main/resources/org/apache/karaf/wrapper/internal/windows/wrapper.dll
deleted file mode 100644
index cb553c1..0000000
Binary files a/wrapper/core/src/main/resources/org/apache/karaf/wrapper/internal/windows/wrapper.dll and /dev/null differ

http://git-wip-us.apache.org/repos/asf/karaf/blob/4182735c/wrapper/core/src/main/resources/org/apache/karaf/wrapper/internal/windows64/karaf-service.bat
----------------------------------------------------------------------
diff --git a/wrapper/core/src/main/resources/org/apache/karaf/wrapper/internal/windows64/karaf-service.bat b/wrapper/core/src/main/resources/org/apache/karaf/wrapper/internal/windows64/karaf-service.bat
deleted file mode 100644
index 0dd0474..0000000
--- a/wrapper/core/src/main/resources/org/apache/karaf/wrapper/internal/windows64/karaf-service.bat
+++ /dev/null
@@ -1,51 +0,0 @@
-@echo off
-
-REM ------------------------------------------------------------------------
-REM Licensed to the Apache Software Foundation (ASF) under one or more
-REM contributor license agreements.  See the NOTICE file distributed with
-REM this work for additional information regarding copyright ownership.
-REM The ASF licenses this file to You under the Apache License, Version 2.0
-REM (the "License"); you may not use this file except in compliance with
-REM the License.  You may obtain a copy of the License at
-REM
-REM http://www.apache.org/licenses/LICENSE-2.0
-REM
-REM Unless required by applicable law or agreed to in writing, software
-REM distributed under the License is distributed on an "AS IS" BASIS,
-REM WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-REM See the License for the specific language governing permissions and
-REM limitations under the License.
-REM ------------------------------------------------------------------------
-
-setlocal
-
-set APP_NAME=${name}
-set APP_LONG_NAME=${displayName}
-set APP_BASE=${karaf.base}
-set APP_ETC=${karaf.etc}
-
-if ""%1"" == ""run"" goto doRun
-if ""%1"" == ""install"" goto doInstall
-if ""%1"" == ""remove"" goto doRemove
-
-echo Usage:  karaf-service ( commands ... )
-echo commands:
-echo   run               Start %APP_NAME% in the current console
-echo   install           Install %APP_NAME% as a Windows service
-echo   remove            Remove the %APP_NAME% Windows service
-goto end
-
-:doRun
-"%APP_BASE%\bin\%APP_NAME%-wrapper.exe" -c "%APP_ETC%\%APP_NAME%-wrapper.conf"
-goto end
-
-:doInstall
-"%APP_BASE%\bin\%APP_NAME%-wrapper.exe" -i "%APP_ETC%\%APP_NAME%-wrapper.conf"
-goto end
-
-:doRemove
-"%APP_BASE%\bin\%APP_NAME%-wrapper.exe" -r "%APP_ETC%\%APP_NAME%-wrapper.conf"
-goto end
-
-:end
-if not "%PAUSE%" == "" pause

http://git-wip-us.apache.org/repos/asf/karaf/blob/4182735c/wrapper/core/src/main/resources/org/apache/karaf/wrapper/internal/windows64/karaf-wrapper.conf
----------------------------------------------------------------------
diff --git a/wrapper/core/src/main/resources/org/apache/karaf/wrapper/internal/windows64/karaf-wrapper.conf b/wrapper/core/src/main/resources/org/apache/karaf/wrapper/internal/windows64/karaf-wrapper.conf
deleted file mode 100644
index def40f7..0000000
--- a/wrapper/core/src/main/resources/org/apache/karaf/wrapper/internal/windows64/karaf-wrapper.conf
+++ /dev/null
@@ -1,135 +0,0 @@
-# ------------------------------------------------------------------------
-# 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.
-# ------------------------------------------------------------------------
-
-#********************************************************************
-# Wrapper Properties
-#********************************************************************
-set.default.JAVA_HOME=${java.home}
-set.default.KARAF_HOME=${karaf.home}
-set.default.KARAF_BASE=${karaf.base}
-set.default.KARAF_DATA=${karaf.data}
-set.default.KARAF_ETC=${karaf.etc}
-
-# Java Application
-wrapper.working.dir=%KARAF_BASE%
-wrapper.java.command=%JAVA_HOME%/bin/java
-wrapper.java.mainclass=org.apache.karaf.wrapper.internal.Main
-wrapper.java.classpath.1=%KARAF_HOME%/lib/karaf-wrapper.jar
-wrapper.java.classpath.2=%KARAF_HOME%/lib/karaf.jar
-wrapper.java.classpath.3=%KARAF_HOME%/lib/karaf-jmx-boot.jar
-wrapper.java.classpath.4=%KARAF_HOME%/lib/karaf-jaas-boot.jar
-wrapper.java.classpath.5=%KARAF_HOME%/lib/karaf-wrapper-main.jar
-wrapper.java.classpath.6=%KARAF_HOME%/lib/karaf-org.osgi.core.jar
-wrapper.java.library.path.1=%KARAF_HOME%/lib/
-
-# Application Parameters.  Add parameters as needed starting from 1
-#wrapper.app.parameter.1=
-
-# JVM Parameters
-# note that n is the parameter number starting from 1.
-wrapper.java.additional.1=-Dkaraf.home="%KARAF_HOME%"
-wrapper.java.additional.2=-Dkaraf.base="%KARAF_BASE%"
-wrapper.java.additional.3=-Dkaraf.data="%KARAF_DATA%"
-wrapper.java.additional.4=-Dkaraf.etc="%KARAF_ETC%"
-wrapper.java.additional.5=-Dcom.sun.management.jmxremote
-wrapper.java.additional.6=-Djavax.management.builder.initial=org.apache.karaf.management.boot.KarafMBeanServerBuilder
-wrapper.java.additional.7=-Dkaraf.startLocalConsole=false
-wrapper.java.additional.8=-Dkaraf.startRemoteShell=true
-wrapper.java.additional.9=-Djava.endorsed.dirs="%JAVA_HOME%/jre/lib/endorsed;%JAVA_HOME%/lib/endorsed;%KARAF_HOME%/lib/endorsed"
-wrapper.java.additional.10=-Djava.ext.dirs="%JAVA_HOME%/jre/lib/ext;%JAVA_HOME%/lib/ext;%KARAF_HOME%/lib/ext"
-
-# Uncomment to enable jmx
-#wrapper.java.additional.n=-Dcom.sun.management.jmxremote.port=1616
-#wrapper.java.additional.n=-Dcom.sun.management.jmxremote.authenticate=false
-#wrapper.java.additional.n=-Dcom.sun.management.jmxremote.ssl=false
-
-# Uncomment to enable YourKit profiling
-#wrapper.java.additional.n=-Xrunyjpagent
-
-# Uncomment to enable remote debugging
-#wrapper.java.additional.n=-Xdebug -Xnoagent -Djava.compiler=NONE
-#wrapper.java.additional.n=-Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005
-
-# Initial Java Heap Size (in MB)
-#wrapper.java.initmemory=3
-
-# Maximum Java Heap Size (in MB)
-wrapper.java.maxmemory=512
-
-
-#********************************************************************
-# Wrapper Logging Properties
-#********************************************************************
-# Format of output for the console.  (See docs for formats)
-wrapper.console.format=PM
-
-# Log Level for console output.  (See docs for log levels)
-wrapper.console.loglevel=INFO
-
-# Log file to use for wrapper output logging.
-wrapper.logfile=%KARAF_DATA%/log/wrapper.log
-
-# Format of output for the log file.  (See docs for formats)
-wrapper.logfile.format=LPTM
-
-# Log Level for log file output.  (See docs for log levels)
-wrapper.logfile.loglevel=INFO
-
-# Maximum size that the log file will be allowed to grow to before
-#  the log is rolled. Size is specified in bytes.  The default value
-#  of 0, disables log rolling.  May abbreviate with the 'k' (kb) or
-#  'm' (mb) suffix.  For example: 10m = 10 megabytes.
-wrapper.logfile.maxsize=10m
-
-# Maximum number of rolled log files which will be allowed before old
-#  files are deleted.  The default value of 0 implies no limit.
-wrapper.logfile.maxfiles=5
-
-# Log Level for sys/event log output.  (See docs for log levels)
-wrapper.syslog.loglevel=NONE
-
-#********************************************************************
-# Wrapper Windows Properties
-#********************************************************************
-# Title to use when running as a console
-wrapper.console.title=${name}
-
-#********************************************************************
-# Wrapper Windows NT/2000/XP Service Properties
-#********************************************************************
-# WARNING - Do not modify any of these properties when an application
-#  using this configuration file has been installed as a service.
-#  Please uninstall the service before modifying this section.  The
-#  service can then be reinstalled.
-
-# Name of the service
-wrapper.ntservice.name=${name}
-
-# Display name of the service
-wrapper.ntservice.displayname=${displayName}
-
-# Description of the service
-wrapper.ntservice.description=${description}
-
-# Service dependencies.  Add dependencies as needed starting from 1
-wrapper.ntservice.dependency.1=
-
-# Mode in which the service is installed.  AUTO_START or DEMAND_START
-wrapper.ntservice.starttype=${startType}
-
-# Allow the service to interact with the desktop.
-wrapper.ntservice.interactive=false

http://git-wip-us.apache.org/repos/asf/karaf/blob/4182735c/wrapper/core/src/main/resources/org/apache/karaf/wrapper/internal/windows64/karaf-wrapper.exe
----------------------------------------------------------------------
diff --git a/wrapper/core/src/main/resources/org/apache/karaf/wrapper/internal/windows64/karaf-wrapper.exe b/wrapper/core/src/main/resources/org/apache/karaf/wrapper/internal/windows64/karaf-wrapper.exe
deleted file mode 100755
index db2ddda..0000000
Binary files a/wrapper/core/src/main/resources/org/apache/karaf/wrapper/internal/windows64/karaf-wrapper.exe and /dev/null differ

http://git-wip-us.apache.org/repos/asf/karaf/blob/4182735c/wrapper/core/src/main/resources/org/apache/karaf/wrapper/internal/windows64/wrapper.dll
----------------------------------------------------------------------
diff --git a/wrapper/core/src/main/resources/org/apache/karaf/wrapper/internal/windows64/wrapper.dll b/wrapper/core/src/main/resources/org/apache/karaf/wrapper/internal/windows64/wrapper.dll
deleted file mode 100644
index f07fc9e..0000000
Binary files a/wrapper/core/src/main/resources/org/apache/karaf/wrapper/internal/windows64/wrapper.dll and /dev/null differ

http://git-wip-us.apache.org/repos/asf/karaf/blob/4182735c/wrapper/pom.xml
----------------------------------------------------------------------
diff --git a/wrapper/pom.xml b/wrapper/pom.xml
index 3c809b9..6f36786 100644
--- a/wrapper/pom.xml
+++ b/wrapper/pom.xml
@@ -10,7 +10,7 @@
         (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
+            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,
@@ -29,13 +29,105 @@
     </parent>
 
     <groupId>org.apache.karaf.wrapper</groupId>
-    <artifactId>wrapper</artifactId>
-    <packaging>pom</packaging>
-    <name>Apache Karaf :: Wrapper</name>
-
-    <modules>
-        <module>core</module>
-        <module>command</module>
-    </modules>
+    <artifactId>org.apache.karaf.wrapper.core</artifactId>
+    <packaging>bundle</packaging>
+    <name>Apache Karaf :: Wrapper :: Core</name>
+    <description>
+        Core implementation and integration of the Java Service Wrapper.
+        It provides a complete integration of Karaf with your Operating System.
+    </description>
+
+    <properties>
+        <appendedResourcesDirectory>${basedir}/../../etc/appended-resources</appendedResourcesDirectory>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>org.osgi.core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.karaf</groupId>
+            <artifactId>org.apache.karaf.main</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.karaf.shell</groupId>
+            <artifactId>org.apache.karaf.shell.core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>tanukisoft</groupId>
+            <artifactId>wrapper</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-api</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-jdk14</artifactId>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <resources>
+            <resource>
+                <directory>${project.basedir}/src/main/resources</directory>
+                <includes>
+                    <include>**/*</include>
+                </includes>
+            </resource>
+            <resource>
+                <directory>${project.basedir}/src/main/resources</directory>
+                <filtering>true</filtering>
+                <includes>
+                    <include>**/*.info</include>
+                </includes>
+            </resource>
+        </resources>
+        <plugins>
+            <plugin>
+                <groupId>org.codehaus.mojo</groupId>
+                <artifactId>exec-maven-plugin</artifactId>
+                <configuration>
+                    <mainClass>Main</mainClass>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+                <configuration>
+                    <instructions>
+                        <Export-Package>
+                            org.apache.karaf.wrapper,
+                            org.apache.karaf.wrapper.management
+                        </Export-Package>
+                        <Private-Package>
+                            org.apache.karaf.wrapper.commands,
+                            org.apache.karaf.wrapper.internal,
+                            org.apache.karaf.wrapper.internal.osgi,
+                            org.apache.karaf.wrapper.management.internal,
+                            org.tanukisoftware.wrapper*,
+                            org.apache.karaf.main*,
+                            org.apache.karaf.util.tracker
+                        </Private-Package>
+                        <Import-Package>
+                            !org.apache.felix.utils.properties,
+                            !org.apache.karaf.util.locks,
+                            !org.apache.karaf.info,
+                            *
+                        </Import-Package>
+                        <Bundle-Activator>
+                            org.apache.karaf.wrapper.internal.osgi.Activator
+                        </Bundle-Activator>
+                        <Karaf-Commands>
+                            org.apache.karaf.wrapper.commands
+                        </Karaf-Commands>
+                    </instructions>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
 
 </project>

http://git-wip-us.apache.org/repos/asf/karaf/blob/4182735c/wrapper/src/main/java/org/apache/karaf/wrapper/WrapperService.java
----------------------------------------------------------------------
diff --git a/wrapper/src/main/java/org/apache/karaf/wrapper/WrapperService.java b/wrapper/src/main/java/org/apache/karaf/wrapper/WrapperService.java
new file mode 100644
index 0000000..fb05a16
--- /dev/null
+++ b/wrapper/src/main/java/org/apache/karaf/wrapper/WrapperService.java
@@ -0,0 +1,42 @@
+/*
+ * 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.karaf.wrapper;
+
+import java.io.File;
+
+/**
+ * Interface describing the Wrapper service.
+ */
+public interface WrapperService {
+
+    /**
+     * Install the Karaf container as a system service in the OS.
+     */
+    public void install() throws Exception;
+
+    /**
+     * Install the Karaf container as a system service in the OS.
+     *
+     * @param name The service name that will be used when installing the service.
+     * @param displayName The display name of the service.
+     * @param description The description of the service.
+     * @param startType Mode in which the service is installed. AUTO_START or DEMAND_START.
+     * @return an array containing the wrapper configuration file (index 0) and the service file (index 1)
+     */
+    public File[] install(String name, String displayName, String description, String startType) throws Exception;
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/4182735c/wrapper/src/main/java/org/apache/karaf/wrapper/commands/Install.java
----------------------------------------------------------------------
diff --git a/wrapper/src/main/java/org/apache/karaf/wrapper/commands/Install.java b/wrapper/src/main/java/org/apache/karaf/wrapper/commands/Install.java
new file mode 100644
index 0000000..346f6f1
--- /dev/null
+++ b/wrapper/src/main/java/org/apache/karaf/wrapper/commands/Install.java
@@ -0,0 +1,199 @@
+/*
+ * 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.karaf.wrapper.commands;
+
+import java.io.File;
+
+import org.apache.karaf.shell.api.action.Action;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.Option;
+import org.apache.karaf.shell.api.action.lifecycle.Reference;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.apache.karaf.wrapper.WrapperService;
+
+import static org.apache.karaf.shell.support.ansi.SimpleAnsi.INTENSITY_BOLD;
+import static org.apache.karaf.shell.support.ansi.SimpleAnsi.INTENSITY_NORMAL;
+
+/**
+ * Installs the Karaf instance as a service in your operating system.
+ */
+@Command(scope = "wrapper", name = "install", description = "Install the container as a system service in the OS.")
+@Service
+public class Install implements Action {
+
+	@Option(name = "-n", aliases = { "--name" }, description = "The service name that will be used when installing the service. (Default: karaf)", required = false, multiValued = false)
+	private String name = "karaf";
+
+	@Option(name = "-d", aliases = { "--display" }, description = "The display name of the service.", required = false, multiValued = false)
+	private String displayName = "karaf";
+
+	@Option(name = "-D", aliases = { "--description" }, description = "The description of the service.", required = false, multiValued = false)
+	private String description = "";
+
+	@Option(name = "-s", aliases = { "--start-type" }, description = "Mode in which the service is installed. AUTO_START or DEMAND_START (Default: AUTO_START)", required = false, multiValued = false)
+	private String startType = "AUTO_START";
+
+    @Reference
+	private WrapperService wrapperService;
+
+    @Override
+	public Object execute() throws Exception {
+        File[] wrapperPaths = wrapperService.install(name, displayName, description, startType);
+
+        String os = System.getProperty("os.name", "Unknown");
+        File wrapperConf = wrapperPaths[0];
+        File serviceFile = wrapperPaths[1];
+
+        System.out.println("");
+        System.out.println("Setup complete.  You may wish to tweak the JVM properties in the wrapper configuration file:");
+        System.out.println("\t" + wrapperConf.getPath());
+        System.out.println("before installing and starting the service.");
+        System.out.println("");
+        if (os.startsWith("Win")) {
+            System.out.println("");
+            System.out.println(INTENSITY_BOLD + "MS Windows system detected:" + INTENSITY_NORMAL);
+            System.out.println("To install the service, run: ");
+            System.out.println("  C:> " + serviceFile.getPath() + " install");
+            System.out.println("");
+            System.out.println("Once installed, to start the service run: ");
+            System.out.println("  C:> net start \"" + name + "\"");
+            System.out.println("");
+            System.out.println("Once running, to stop the service run: ");
+            System.out.println("  C:> net stop \"" + name + "\"");
+            System.out.println("");
+            System.out.println("Once stopped, to remove the installed the service run: ");
+            System.out.println("  C:> " + serviceFile.getPath() + " remove");
+            System.out.println("");
+        } else if (os.startsWith("Mac OS X")) {
+            System.out.println("");
+            System.out.println(INTENSITY_BOLD + "Mac OS X system detected:" + INTENSITY_NORMAL);
+            System.out.println("to add bin/org.apache.karaf.KARAF as user service move this file into ~/Library/LaunchAgents/");  
+            System.out.println("> mv bin/org.apache.karaf.KARAF.plist ~/Library/LaunchAgents/");
+            System.out.println("");
+            System.out.println("to add org.apache.karaf.KARAF as system service move this into /Library/LaunchDaemons");  
+            System.out.println("> sudo mv bin/org.apache.karaf.KARAF.plist /Library/LaunchDaemons/");  
+            System.out.println("change owner and rights");  
+            System.out.println("> sudo chown root:wheel /Library/LaunchDaemons/org.apache.karaf.KARAF.plist");  
+            System.out.println("> sudo chmod u=rw,g=r,o=r /Library/LaunchDaemons/org.apache.karaf.KARAF.plist");  
+            System.out.println(""); 
+            System.out.println("test your service");  
+            System.out.println("> launchctl load ~/Library/LaunchAgents/org.apache.karaf.KARAF.plist");  
+            System.out.println("> launchctl start org.apache.karaf.KARAF");  
+            System.out.println("> launchctl stop org.apache.karaf.KARAF");  
+            System.out.println("");  
+            System.out.println("after restart your session or system");  
+            System.out.println("you can use launchctl command to start and stop your service");  
+            System.out.println("");  
+            System.out.println("for removing the service call");  
+            System.out.println("> launchctl remove org.apache.karaf.KARAF");  
+            System.out.println("");
+        } else if (os.startsWith("Linux")) {
+
+            File debianVersion = new File("/etc/debian_version");
+            File redhatRelease = new File("/etc/redhat-release");
+
+            if (redhatRelease.exists()) {
+                System.out.println("");
+                System.out.println(INTENSITY_BOLD + "RedHat/Fedora/CentOS Linux system detected:" + INTENSITY_NORMAL);
+                System.out.println("  To install the service:");
+                System.out.println("    $ ln -s " + serviceFile.getPath() + " /etc/init.d/");
+                System.out.println("    $ chkconfig " + serviceFile.getName() + " --add");
+                System.out.println("");
+                System.out.println("  To start the service when the machine is rebooted:");
+                System.out.println("    $ chkconfig " + serviceFile.getName() + " on");
+                System.out.println("");
+                System.out.println("  To disable starting the service when the machine is rebooted:");
+                System.out.println("    $ chkconfig " + serviceFile.getName() + " off");
+                System.out.println("");
+                System.out.println("  To start the service:");
+                System.out.println("    $ service " + serviceFile.getName() + " start");
+                System.out.println("");
+                System.out.println("  To stop the service:");
+                System.out.println("    $ service " + serviceFile.getName() + " stop");
+                System.out.println("");
+                System.out.println("  To uninstall the service :");
+                System.out.println("    $ chkconfig " + serviceFile.getName() + " --del");
+                System.out.println("    $ rm /etc/init.d/" + serviceFile.getPath());
+            } else if (debianVersion.exists()) {
+                System.out.println("");
+                System.out.println(INTENSITY_BOLD + "Ubuntu/Debian Linux system detected:" + INTENSITY_NORMAL);
+                System.out.println("  To install the service:");
+                System.out.println("    $ ln -s " + serviceFile.getPath() + " /etc/init.d/");
+                System.out.println("");
+                System.out.println("  To start the service when the machine is rebooted:");
+                System.out.println("    $ update-rc.d " + serviceFile.getName() + " defaults");
+                System.out.println("");
+                System.out.println("  To disable starting the service when the machine is rebooted:");
+                System.out.println("    $ update-rc.d -f " + serviceFile.getName() + " remove");
+                System.out.println("");
+                System.out.println("  To start the service:");
+                System.out.println("    $ /etc/init.d/" + serviceFile.getName() + " start");
+                System.out.println("");
+                System.out.println("  To stop the service:");
+                System.out.println("    $ /etc/init.d/" + serviceFile.getName() + " stop");
+                System.out.println("");
+                System.out.println("  To uninstall the service :");
+                System.out.println("    $ rm /etc/init.d/" + serviceFile.getName());
+            } else {
+				System.out.println("");
+                System.out.println(INTENSITY_BOLD + "On Redhat/Fedora/CentOS Systems:" + INTENSITY_NORMAL);
+				System.out.println("  To install the service:");
+				System.out.println("    $ ln -s "+serviceFile.getPath()+" /etc/init.d/");
+				System.out.println("    $ chkconfig "+serviceFile.getName()+" --add");
+				System.out.println("");
+				System.out.println("  To start the service when the machine is rebooted:");
+				System.out.println("    $ chkconfig "+serviceFile.getName()+" on");
+				System.out.println("");
+				System.out.println("  To disable starting the service when the machine is rebooted:");
+				System.out.println("    $ chkconfig "+serviceFile.getName()+" off");
+				System.out.println("");
+				System.out.println("  To start the service:");
+				System.out.println("    $ service "+serviceFile.getName()+" start");
+				System.out.println("");
+				System.out.println("  To stop the service:");
+				System.out.println("    $ service "+serviceFile.getName()+" stop");
+				System.out.println("");
+				System.out.println("  To uninstall the service :");
+				System.out.println("    $ chkconfig "+serviceFile.getName()+" --del");
+				System.out.println("    $ rm /etc/init.d/"+serviceFile.getName());
+
+				System.out.println("");
+                System.out.println(INTENSITY_BOLD + "On Ubuntu/Debian Systems:" + INTENSITY_NORMAL);
+				System.out.println("  To install the service:");
+				System.out.println("    $ ln -s "+serviceFile.getPath()+" /etc/init.d/");
+				System.out.println("");
+				System.out.println("  To start the service when the machine is rebooted:");
+				System.out.println("    $ update-rc.d "+serviceFile.getName()+" defaults");
+				System.out.println("");
+				System.out.println("  To disable starting the service when the machine is rebooted:");
+				System.out.println("    $ update-rc.d -f "+serviceFile.getName()+" remove");
+				System.out.println("");
+				System.out.println("  To start the service:");
+				System.out.println("    $ /etc/init.d/"+serviceFile.getName()+" start");
+				System.out.println("");
+				System.out.println("  To stop the service:");
+				System.out.println("    $ /etc/init.d/"+serviceFile.getName()+" stop");
+				System.out.println("");
+				System.out.println("  To uninstall the service :");
+				System.out.println("    $ rm /etc/init.d/"+serviceFile.getName());
+            }
+
+        }
+
+        return null;
+    }
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/4182735c/wrapper/src/main/java/org/apache/karaf/wrapper/internal/Main.java
----------------------------------------------------------------------
diff --git a/wrapper/src/main/java/org/apache/karaf/wrapper/internal/Main.java b/wrapper/src/main/java/org/apache/karaf/wrapper/internal/Main.java
new file mode 100644
index 0000000..8f3060e
--- /dev/null
+++ b/wrapper/src/main/java/org/apache/karaf/wrapper/internal/Main.java
@@ -0,0 +1,146 @@
+/*
+ * 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.karaf.wrapper.internal;
+
+import org.apache.karaf.main.ShutdownCallback;
+import org.tanukisoftware.wrapper.WrapperListener;
+import org.tanukisoftware.wrapper.WrapperManager;
+
+/**
+ * Java Service Wrapper Main class
+ */
+public class Main extends Thread implements WrapperListener, ShutdownCallback {
+
+    private org.apache.karaf.main.Main main;
+    private volatile boolean destroying;
+
+    /*---------------------------------------------------------------
+     * Constructors
+     *-------------------------------------------------------------*/
+    private Main() {
+    }
+
+    /*---------------------------------------------------------------
+     * WrapperListener Methods
+     *-------------------------------------------------------------*/
+
+    /**
+     * The start method is called when the WrapperManager is signaled by the
+     * native Wrapper code that it can start its application.  This
+     * method call is expected to return, so a new thread should be launched
+     * if necessary.
+     *
+     * @param args List of arguments used to initialize the application.
+     * @return Any error code if the application should exit on completion
+     *         of the start method.  If there were no problems then this
+     *         method should return null.
+     */
+    public Integer start(String[] args) {
+        main = new org.apache.karaf.main.Main(args);
+        try {
+            main.launch();
+            main.setShutdownCallback(this);
+            start();
+            return null;
+        } catch (Throwable ex) {
+            System.err.println("Could not create framework: " + ex);
+            ex.printStackTrace();
+            return -1;
+        }
+    }
+
+    public void run() {
+        try {
+            main.awaitShutdown();
+            if (!destroying) {
+                WrapperManager.stop(main.getExitCode());
+            }
+        } catch (Exception e) {
+            // Ignore
+        }
+    }
+
+    /**
+     * Called when the application is shutting down.  The Wrapper assumes that
+     * this method will return fairly quickly.  If the shutdown code code
+     * could potentially take a long time, then WrapperManager.signalStopping()
+     * should be called to extend the timeout period.  If for some reason,
+     * the stop method can not return, then it must call
+     * WrapperManager.stopped() to avoid warning messages from the Wrapper.
+     *
+     * @param exitCode The suggested exit code that will be returned to the OS
+     *                 when the JVM exits.
+     * @return The exit code to actually return to the OS.  In most cases, this
+     *         should just be the value of exitCode, however the user code has
+     *         the option of changing the exit code if there are any problems
+     *         during shutdown.
+     */
+    public int stop(int exitCode) {
+        try {
+            destroying = true;
+            if (!main.destroy()) {
+                System.err.println("Timeout waiting for Karaf to shutdown");
+                return -3;
+            }
+        } catch (Throwable ex) {
+            System.err.println("Error occured shutting down framework: " + ex);
+            ex.printStackTrace();
+            return -2;
+        }
+
+        return main.getExitCode();
+    }
+
+    /**
+     * Call-back method is called by the @{link org.apache.karaf.main.Main} for Signaling
+     * that the stopping process is in progress and the wrapper doesn't kill the JVM.
+     */
+    public void waitingForShutdown(int delay) {
+        WrapperManager.signalStopping(delay);
+    }
+
+    /**
+     * Called whenever the native Wrapper code traps a system control signal
+     * against the Java process.  It is up to the callback to take any actions
+     * necessary.  Possible values are: WrapperManager.WRAPPER_CTRL_C_EVENT,
+     * WRAPPER_CTRL_CLOSE_EVENT, WRAPPER_CTRL_LOGOFF_EVENT, or
+     * WRAPPER_CTRL_SHUTDOWN_EVENT
+     *
+     * @param event The system control signal.
+     */
+    public void controlEvent(int event) {
+        if ((event == WrapperManager.WRAPPER_CTRL_LOGOFF_EVENT)
+                && (WrapperManager.isLaunchedAsService())) {
+            // Ignore
+        } else {
+            WrapperManager.stop(0);
+            // Will not get here.
+        }
+    }
+
+    /*---------------------------------------------------------------
+     * Main Method
+     *-------------------------------------------------------------*/
+    public static void main(String[] args) {
+        // Start the application.  If the JVM was launched from the native
+        //  Wrapper then the application will wait for the native Wrapper to
+        //  call the application's start method.  Otherwise the start method
+        //  will be called immediately.
+        WrapperManager.start(new Main(), args);
+    }
+
+}
\ No newline at end of file


[44/59] [abbrv] [KARAF-2852] Merge obr/core and obr/command

Posted by gn...@apache.org.
http://git-wip-us.apache.org/repos/asf/karaf/blob/b0a20b83/obr/core/src/main/java/org/apache/karaf/obr/core/internal/ObrMBeanImpl.java
----------------------------------------------------------------------
diff --git a/obr/core/src/main/java/org/apache/karaf/obr/core/internal/ObrMBeanImpl.java b/obr/core/src/main/java/org/apache/karaf/obr/core/internal/ObrMBeanImpl.java
deleted file mode 100644
index c182165..0000000
--- a/obr/core/src/main/java/org/apache/karaf/obr/core/internal/ObrMBeanImpl.java
+++ /dev/null
@@ -1,203 +0,0 @@
-/*
- * 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.karaf.obr.core.internal;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import javax.management.MBeanException;
-import javax.management.NotCompliantMBeanException;
-import javax.management.StandardMBean;
-import javax.management.openmbean.CompositeData;
-import javax.management.openmbean.CompositeDataSupport;
-import javax.management.openmbean.CompositeType;
-import javax.management.openmbean.OpenType;
-import javax.management.openmbean.SimpleType;
-import javax.management.openmbean.TabularData;
-import javax.management.openmbean.TabularDataSupport;
-import javax.management.openmbean.TabularType;
-
-import org.apache.felix.bundlerepository.Repository;
-import org.apache.felix.bundlerepository.RepositoryAdmin;
-import org.apache.felix.bundlerepository.Resolver;
-import org.apache.felix.bundlerepository.Resource;
-import org.apache.karaf.obr.core.ObrMBean;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.InvalidSyntaxException;
-import org.osgi.framework.Version;
-
-/**
- * Implementation of the OBR MBean.
- */
-public class ObrMBeanImpl extends StandardMBean implements ObrMBean {
-
-    private static final char VERSION_DELIM = ',';
-
-    private BundleContext bundleContext;
-    private RepositoryAdmin repositoryAdmin;
-
-    public ObrMBeanImpl(BundleContext bundleContext, RepositoryAdmin repositoryAdmin) throws NotCompliantMBeanException {
-        super(ObrMBean.class);
-        this.bundleContext = bundleContext;
-        this.repositoryAdmin = repositoryAdmin;
-    }
-
-    public List<String> getUrls() {
-        Repository[] repositories = repositoryAdmin.listRepositories();
-        List<String> urls = new ArrayList<String>();
-        for (int i = 0; i < repositories.length; i++) {
-            urls.add(repositories[i].getURI());
-        }
-        return urls;
-    }
-
-    public TabularData getBundles() throws MBeanException {
-        try {
-            CompositeType bundleType = new CompositeType("OBR Resource", "Bundle available in the OBR",
-                    new String[]{"presentationname", "symbolicname", "version"},
-                    new String[]{"Presentation Name", "Symbolic Name", "Version"},
-                    new OpenType[]{SimpleType.STRING, SimpleType.STRING, SimpleType.STRING});
-            TabularType tableType = new TabularType("OBR Resources", "Table of all resources/bundles available in the OBR",
-                    bundleType, new String[]{"symbolicname", "version"});
-            TabularData table = new TabularDataSupport(tableType);
-
-            Resource[] resources = repositoryAdmin.discoverResources("(|(presentationname=*)(symbolicname=*))");
-            for (int i = 0; i < resources.length; i++) {
-                try {
-                    CompositeData data = new CompositeDataSupport(bundleType,
-                            new String[]{"presentationname", "symbolicname", "version"},
-                            new Object[]{resources[i].getPresentationName(), resources[i].getSymbolicName(), resources[i].getVersion().toString()});
-                    table.put(data);
-                } catch (Exception e) {
-                    e.printStackTrace();
-                }
-            }
-
-            return table;
-        } catch (Exception e) {
-            throw new MBeanException(null, e.getMessage());
-        }
-    }
-
-    public void addUrl(String url) throws MBeanException {
-        try {
-            repositoryAdmin.addRepository(url);
-        } catch (Exception e) {
-            throw new MBeanException(null, e.getMessage());
-        }
-    }
-
-    public void removeUrl(String url) {
-        repositoryAdmin.removeRepository(url);
-    }
-
-    public void refreshUrl(String url) throws MBeanException {
-        try {
-            repositoryAdmin.addRepository(url);
-        } catch (Exception e) {
-            throw new MBeanException(null, e.getMessage());
-        }
-    }
-
-    public void deployBundle(String bundle) throws MBeanException {
-        try {
-            deployBundle(bundle, false, false);
-        } catch (Exception e) {
-            throw new MBeanException(null, e.getMessage());
-        }
-    }
-
-    public void deployBundle(String bundle, boolean start, boolean deployOptional) throws MBeanException {
-        try {
-            Resolver resolver = repositoryAdmin.resolver();
-            String[] target = getTarget(bundle);
-            Resource resource = selectNewestVersion(searchRepository(repositoryAdmin, target[0], target[1]));
-            if (resource == null) {
-                throw new IllegalArgumentException("Unknown bundle " + target[0]);
-            }
-            resolver.add(resource);
-            if ((resolver.getAddedResources() != null) &&
-                    (resolver.getAddedResources().length > 0)) {
-                if (resolver.resolve(deployOptional ? 0 : Resolver.NO_OPTIONAL_RESOURCES)) {
-                    try {
-                        resolver.deploy(start ? Resolver.START : 0);
-                    } catch (IllegalStateException ex) {
-                        throw new IllegalStateException("Can't deploy using OBR", ex);
-                    }
-                }
-            }
-        } catch (Exception e) {
-            throw new MBeanException(null, e.getMessage());
-        }
-    }
-
-    private Resource[] searchRepository(RepositoryAdmin admin, String targetId, String targetVersion) throws InvalidSyntaxException {
-        // Try to see if the targetId is a bundle ID.
-        try {
-            Bundle bundle = bundleContext.getBundle(Long.parseLong(targetId));
-            targetId = bundle.getSymbolicName();
-        } catch (NumberFormatException ex) {
-            // It was not a number, so ignore.
-        }
-
-        // The targetId may be a bundle name or a bundle symbolic name,
-        // so create the appropriate LDAP query.
-        StringBuffer sb = new StringBuffer("(|(presentationname=");
-        sb.append(targetId);
-        sb.append(")(symbolicname=");
-        sb.append(targetId);
-        sb.append("))");
-        if (targetVersion != null) {
-            sb.insert(0, "(&");
-            sb.append("(version=");
-            sb.append(targetVersion);
-            sb.append("))");
-        }
-        return admin.discoverResources(sb.toString());
-    }
-
-    private Resource selectNewestVersion(Resource[] resources) {
-        int idx = -1;
-        Version v = null;
-        for (int i = 0; (resources != null) && (i < resources.length); i++) {
-            if (i == 0) {
-                idx = 0;
-                v = resources[i].getVersion();
-            } else {
-                Version vtmp = resources[i].getVersion();
-                if (vtmp.compareTo(v) > 0) {
-                    idx = i;
-                    v = vtmp;
-                }
-            }
-        }
-        return (idx < 0) ? null : resources[idx];
-    }
-
-    private String[] getTarget(String bundle) {
-        String[] target;
-        int idx = bundle.indexOf(VERSION_DELIM);
-        if (idx > 0) {
-            target = new String[]{bundle.substring(0, idx), bundle.substring(idx + 1)};
-        } else {
-            target = new String[]{bundle, null};
-        }
-        return target;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/b0a20b83/obr/core/src/main/resources/OSGI-INF/blueprint/blueprint.xml
----------------------------------------------------------------------
diff --git a/obr/core/src/main/resources/OSGI-INF/blueprint/blueprint.xml b/obr/core/src/main/resources/OSGI-INF/blueprint/blueprint.xml
deleted file mode 100644
index 4fbe9fb..0000000
--- a/obr/core/src/main/resources/OSGI-INF/blueprint/blueprint.xml
+++ /dev/null
@@ -1,34 +0,0 @@
-<?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"
-    xmlns:cm="http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.1.0"
-    xmlns:ext="http://aries.apache.org/blueprint/xmlns/blueprint-ext/v1.0.0">
-
-    <ext:property-placeholder />
-
-    <reference id="repositoryAdmin" interface="org.apache.felix.bundlerepository.RepositoryAdmin"/>
-
-    <bean id="obrMBean" class="org.apache.karaf.obr.core.internal.ObrMBeanImpl">
-        <argument ref="blueprintBundleContext"/>
-        <argument ref="repositoryAdmin"/>
-    </bean>
-
-    <service ref="obrMBean" auto-export="interfaces">
-        <service-properties>
-            <entry key="jmx.objectname" value="org.apache.karaf:type=obr,name=${karaf.name}"/>
-        </service-properties>
-    </service>
-
-</blueprint>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/karaf/blob/b0a20b83/obr/core/src/main/resources/OSGI-INF/bundle.info
----------------------------------------------------------------------
diff --git a/obr/core/src/main/resources/OSGI-INF/bundle.info b/obr/core/src/main/resources/OSGI-INF/bundle.info
deleted file mode 100644
index e14433c..0000000
--- a/obr/core/src/main/resources/OSGI-INF/bundle.info
+++ /dev/null
@@ -1,25 +0,0 @@
-h1. Synopsis
-
-${project.name}
-
-${project.description}
-
-Maven URL:
-[mvn:${project.groupId}/${project.artifactId}/${project.version}]
-
-h1. Description
-
-The obr mbean management bundle exposes an OBR MBean that can be used with any JMX client (for instance JConsole).
-
-The OBR MBean allows quite the same actions that can be performed using obr:* commands:
-  * listUrls()
-  * addUrl(url)
-  * removeUrl(url)
-  * refreshUrl(url)
-  * list()
-  * deploy(bundle)
-  * deploy(bundle, start)
-
-h1. See also
-
-  * Monitoring and Administration using JMX - section of the Karaf User Guide

http://git-wip-us.apache.org/repos/asf/karaf/blob/b0a20b83/obr/pom.xml
----------------------------------------------------------------------
diff --git a/obr/pom.xml b/obr/pom.xml
index 28fbcdd..e0498c7 100644
--- a/obr/pom.xml
+++ b/obr/pom.xml
@@ -29,13 +29,67 @@
     </parent>
 
     <groupId>org.apache.karaf.obr</groupId>
-    <artifactId>obr</artifactId>
-    <packaging>pom</packaging>
-    <name>Apache Karaf :: OBR</name>
-
-    <modules>
-        <module>core</module>
-        <module>command</module>
-    </modules>
+    <artifactId>org.apache.karaf.obr.core</artifactId>
+    <packaging>bundle</packaging>
+    <name>Apache Karaf :: OBR :: Core</name>
+    <description>OBR core services and MBeans</description>
+
+    <properties>
+        <appendedResourcesDirectory>${basedir}/../../../etc/appended-resources/</appendedResourcesDirectory>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>org.osgi.core</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.felix</groupId>
+            <artifactId>org.apache.felix.bundlerepository</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.karaf.shell</groupId>
+            <artifactId>org.apache.karaf.shell.core</artifactId>
+            <optional>true</optional>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <resources>
+            <resource>
+                <directory>src/main/resources</directory>
+                <includes>
+                    <include>**/*</include>
+                </includes>
+            </resource>
+            <resource>
+                <directory>src/main/resources</directory>
+                <filtering>true</filtering>
+                <includes>
+                    <include>**/*.info</include>
+                </includes>
+            </resource>
+        </resources>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+                <configuration>
+                    <instructions>
+                        <Export-Package>
+                            org.apache.karaf.obr.core
+                        </Export-Package>
+                        <Private-Package>
+                            org.apache.karaf.obr.command,
+                            org.apache.karaf.obr.core.internal,
+                        </Private-Package>
+                        <Karaf-Commands>*</Karaf-Commands>
+                    </instructions>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
 
 </project>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/karaf/blob/b0a20b83/obr/src/main/java/org/apache/karaf/obr/command/AddUrlCommand.java
----------------------------------------------------------------------
diff --git a/obr/src/main/java/org/apache/karaf/obr/command/AddUrlCommand.java b/obr/src/main/java/org/apache/karaf/obr/command/AddUrlCommand.java
new file mode 100644
index 0000000..5aaf13a
--- /dev/null
+++ b/obr/src/main/java/org/apache/karaf/obr/command/AddUrlCommand.java
@@ -0,0 +1,39 @@
+/*
+ * 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.karaf.obr.command;
+
+import java.util.List;
+
+import org.apache.felix.bundlerepository.RepositoryAdmin;
+import org.apache.karaf.shell.api.action.Argument;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+
+@Command(scope = "obr", name = "url-add", description = "Adds a list of repository URLs to the OBR service.")
+@Service
+public class AddUrlCommand extends ObrCommandSupport {
+
+    @Argument(index = 0, name = "urls", description = "Repository URLs to add to the OBR service separated by whitespaces", required = true, multiValued = true)
+    List<String> urls;
+
+    protected void doExecute(RepositoryAdmin admin) throws Exception {
+        for (String url : urls) {
+            admin.addRepository(url);
+        }
+        persistRepositoryList(admin);
+    }
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/b0a20b83/obr/src/main/java/org/apache/karaf/obr/command/DeployCommand.java
----------------------------------------------------------------------
diff --git a/obr/src/main/java/org/apache/karaf/obr/command/DeployCommand.java b/obr/src/main/java/org/apache/karaf/obr/command/DeployCommand.java
new file mode 100644
index 0000000..a852c70
--- /dev/null
+++ b/obr/src/main/java/org/apache/karaf/obr/command/DeployCommand.java
@@ -0,0 +1,44 @@
+/*
+ * 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.karaf.obr.command;
+
+import java.util.List;
+
+import org.apache.felix.bundlerepository.RepositoryAdmin;
+import org.apache.karaf.shell.api.action.Argument;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.Option;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+
+@Command(scope = "obr", name = "deploy", description = "Deploys a list of bundles using OBR service.")
+@Service
+public class DeployCommand extends ObrCommandSupport {
+
+    @Argument(index = 0, name = "bundles", description = "List of bundle names to deploy (separated by whitespaces)", required = true, multiValued = true)
+    protected List<String> bundles;
+
+    @Option(name = "-s", aliases = { "--start" }, description = "Start the deployed bundles", required = false, multiValued = false)
+    protected boolean start = false;
+
+    @Option(name = "-d", aliases = { "--deployOptional" }, description = "Deploy optional bundles", required = false, multiValued = false)
+    protected boolean deployOptional = false;
+
+    protected void doExecute(RepositoryAdmin admin) throws Exception {
+        doDeploy(admin, bundles, start, deployOptional);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/b0a20b83/obr/src/main/java/org/apache/karaf/obr/command/FindCommand.java
----------------------------------------------------------------------
diff --git a/obr/src/main/java/org/apache/karaf/obr/command/FindCommand.java b/obr/src/main/java/org/apache/karaf/obr/command/FindCommand.java
new file mode 100644
index 0000000..fad967b
--- /dev/null
+++ b/obr/src/main/java/org/apache/karaf/obr/command/FindCommand.java
@@ -0,0 +1,130 @@
+/*
+ * 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.karaf.obr.command;
+
+import org.apache.felix.bundlerepository.Capability;
+import org.apache.felix.bundlerepository.RepositoryAdmin;
+import org.apache.felix.bundlerepository.Requirement;
+import org.apache.felix.bundlerepository.Resource;
+import org.apache.karaf.shell.api.action.Argument;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+
+import java.io.PrintStream;
+import java.lang.reflect.Array;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+@Command(scope = "obr", name = "find", description = "Find OBR bundles for a given filter.")
+@Service
+public class FindCommand extends ObrCommandSupport {
+
+    @Argument(index = 0, name = "requirements", description = "Requirement", required = true, multiValued = true)
+    List<String> requirements;
+
+    protected void doExecute(RepositoryAdmin admin) throws Exception {
+        Resource[] resources = admin.discoverResources(parseRequirements(admin, requirements));
+        if (resources == null)
+        {
+            System.err.println("No matching resources.");
+        }
+        else
+        {
+            for (int resIdx = 0; resIdx < resources.length; resIdx++)
+            {
+                if (resIdx > 0)
+                {
+                    System.out.println("");
+                }
+                printResource(System.out, resources[resIdx]);
+            }
+        }
+    }
+
+    private void printResource(PrintStream out, Resource resource)
+    {
+        String name = resource.getPresentationName();
+        if (name == null) {
+            name = resource.getSymbolicName();
+        }
+
+        printUnderline(out, name.length());
+        out.println(name);
+        printUnderline(out, name    .length());
+
+        Map map = resource.getProperties();
+        for (Iterator iter = map.entrySet().iterator(); iter.hasNext(); )
+        {
+            Map.Entry entry = (Map.Entry) iter.next();
+            if (entry.getValue().getClass().isArray())
+            {
+                out.println(entry.getKey() + ":");
+                for (int j = 0; j < Array.getLength(entry.getValue()); j++)
+                {
+                    out.println("   " + Array.get(entry.getValue(), j));
+                }
+            }
+            else
+            {
+                out.println(entry.getKey() + ": " + entry.getValue());
+            }
+        }
+
+        Requirement[] reqs = resource.getRequirements();
+        if ((reqs != null) && (reqs.length > 0))
+        {
+            boolean hdr = false;
+            for (int i = 0; i < reqs.length; i++)
+            {
+                if (!reqs[i].isOptional())
+                {
+                    if (!hdr)
+                    {
+                        hdr = true;
+                        out.println("Requirements:");
+                    }
+                    out.println("   " + reqs[i].getName() + ":" + reqs[i].getFilter());
+                }
+            }
+            hdr = false;
+            for (int i = 0; i < reqs.length; i++)
+            {
+                if (reqs[i].isOptional())
+                {
+                    if (!hdr)
+                    {
+                        hdr = true;
+                        out.println("Optional Requirements:");
+                    }
+                    out.println("   " + reqs[i].getName() + ":" + reqs[i].getFilter());
+                }
+            }
+        }
+
+        Capability[] caps = resource.getCapabilities();
+        if ((caps != null) && (caps.length > 0))
+        {
+            out.println("Capabilities:");
+            for (int i = 0; i < caps.length; i++)
+            {
+                out.println("   " + caps[i].getName() + ":" + caps[i].getPropertiesAsMap());
+            }
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/b0a20b83/obr/src/main/java/org/apache/karaf/obr/command/InfoCommand.java
----------------------------------------------------------------------
diff --git a/obr/src/main/java/org/apache/karaf/obr/command/InfoCommand.java b/obr/src/main/java/org/apache/karaf/obr/command/InfoCommand.java
new file mode 100644
index 0000000..bacc61b
--- /dev/null
+++ b/obr/src/main/java/org/apache/karaf/obr/command/InfoCommand.java
@@ -0,0 +1,108 @@
+/*
+ * 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.karaf.obr.command;
+
+import java.io.PrintStream;
+import java.lang.reflect.Array;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.felix.bundlerepository.Capability;
+import org.apache.felix.bundlerepository.RepositoryAdmin;
+import org.apache.felix.bundlerepository.Requirement;
+import org.apache.felix.bundlerepository.Resource;
+import org.apache.karaf.shell.api.action.Argument;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+
+@Command(scope = "obr", name = "info", description = "Prints information about OBR bundles.")
+@Service
+public class InfoCommand extends ObrCommandSupport {
+
+    @Argument(index = 0, name = "bundles", description = "Specify bundles to query for information (separated by whitespaces)", required = true, multiValued = true)
+    List<String> bundles;
+
+    protected void doExecute(RepositoryAdmin admin) throws Exception {
+        for (String bundle : bundles) {
+            String[] target = getTarget(bundle);
+            Resource[] resources = searchRepository(admin, target[0], target[1]);
+            if (resources == null)
+            {
+                System.err.println("Unknown bundle and/or version: "
+                    + target[0]);
+            }
+            else
+            {
+                for (int resIdx = 0; resIdx < resources.length; resIdx++)
+                {
+                    if (resIdx > 0)
+                    {
+                        System.out.println("");
+                    }
+                    printResource(System.out, resources[resIdx]);
+                }
+            }
+        }
+    }
+
+    private void printResource(PrintStream out, Resource resource)
+    {
+        printUnderline(out, resource.getPresentationName().length());
+        out.println(resource.getPresentationName());
+        printUnderline(out, resource.getPresentationName().length());
+
+        Map map = resource.getProperties();
+        for (Iterator iter = map.entrySet().iterator(); iter.hasNext(); )
+        {
+            Map.Entry entry = (Map.Entry) iter.next();
+            if (entry.getValue().getClass().isArray())
+            {
+                out.println(entry.getKey() + ":");
+                for (int j = 0; j < Array.getLength(entry.getValue()); j++)
+                {
+                    out.println("   " + Array.get(entry.getValue(), j));
+                }
+            }
+            else
+            {
+                out.println(entry.getKey() + ": " + entry.getValue());
+            }
+        }
+
+        Requirement[] reqs = resource.getRequirements();
+        if ((reqs != null) && (reqs.length > 0))
+        {
+            out.println("Requires:");
+            for (int i = 0; i < reqs.length; i++)
+            {
+                out.println("   " + reqs[i].getName() + ":" + reqs[i].getFilter());
+            }
+        }
+
+        Capability[] caps = resource.getCapabilities();
+        if ((caps != null) && (caps.length > 0))
+        {
+            out.println("Capabilities:");
+            for (int i = 0; i < caps.length; i++)
+            {
+                out.println("   " + caps[i].getName() + ":" + caps[i].getPropertiesAsMap());
+            }
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/b0a20b83/obr/src/main/java/org/apache/karaf/obr/command/ListCommand.java
----------------------------------------------------------------------
diff --git a/obr/src/main/java/org/apache/karaf/obr/command/ListCommand.java b/obr/src/main/java/org/apache/karaf/obr/command/ListCommand.java
new file mode 100644
index 0000000..45db82f
--- /dev/null
+++ b/obr/src/main/java/org/apache/karaf/obr/command/ListCommand.java
@@ -0,0 +1,85 @@
+/*
+ * 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.karaf.obr.command;
+
+import java.util.List;
+
+import org.apache.felix.bundlerepository.RepositoryAdmin;
+import org.apache.felix.bundlerepository.Resource;
+import org.apache.karaf.shell.api.action.Argument;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.Option;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.apache.karaf.shell.support.table.ShellTable;
+
+@Command(scope = "obr", name = "list", description = "Lists OBR bundles, optionally providing the given packages.")
+@Service
+public class ListCommand extends ObrCommandSupport {
+
+    @Argument(index = 0, name = "packages", description = "A list of packages separated by whitespaces.", required = false, multiValued = true)
+    List<String> packages;
+
+    @Option(name = "--no-format", description = "Disable table rendered output", required = false, multiValued = false)
+    boolean noFormat;
+
+    @Override
+    void doExecute(RepositoryAdmin admin) throws Exception {
+        StringBuilder substr = new StringBuilder();
+
+        if (packages != null) {
+            for (String packageName : packages) {
+                substr.append(" ");
+                substr.append(packageName);
+            }
+        }
+
+        String query;
+        if ((substr == null) || (substr.length() == 0)) {
+            query = "(|(presentationname=*)(symbolicname=*))";
+        } else {
+            query = "(|(presentationname=*" + substr + "*)(symbolicname=*" + substr + "*))";
+        }
+        Resource[] resources = admin.discoverResources(query);
+        int maxPName = 4;
+        int maxSName = 13;
+        int maxVersion = 7;
+        for (Resource resource : resources) {
+            maxPName = Math.max(maxPName, emptyIfNull(resource.getPresentationName()).length());
+            maxSName = Math.max(maxSName, emptyIfNull(resource.getSymbolicName()).length());
+            maxVersion = Math.max(maxVersion, emptyIfNull(resource.getVersion()).length());
+        }
+
+        ShellTable table = new ShellTable();
+        table.column("Name");
+        table.column("Symbolic Name");
+        table.column("Version");
+        table.emptyTableText("No matching bundles");
+
+        for (Resource resource : resources) {
+            table.addRow().addContent(emptyIfNull(resource.getPresentationName()),
+                    emptyIfNull(resource.getSymbolicName()),
+                    emptyIfNull(resource.getVersion()));
+        }
+
+        table.print(System.out, !noFormat);
+    }
+
+    private String emptyIfNull(Object st) {
+        return st == null ? "" : st.toString();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/b0a20b83/obr/src/main/java/org/apache/karaf/obr/command/ListUrlCommand.java
----------------------------------------------------------------------
diff --git a/obr/src/main/java/org/apache/karaf/obr/command/ListUrlCommand.java b/obr/src/main/java/org/apache/karaf/obr/command/ListUrlCommand.java
new file mode 100644
index 0000000..1c07236
--- /dev/null
+++ b/obr/src/main/java/org/apache/karaf/obr/command/ListUrlCommand.java
@@ -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.karaf.obr.command;
+
+import org.apache.felix.bundlerepository.Repository;
+import org.apache.felix.bundlerepository.RepositoryAdmin;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.Option;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.apache.karaf.shell.support.table.ShellTable;
+
+@Command(scope = "obr", name = "url-list", description = "Displays the repository URLs currently associated with the OBR service.")
+@Service
+public class ListUrlCommand extends ObrCommandSupport {
+
+    @Option(name = "--no-format", description = "Disable table rendered output", required = false, multiValued = false)
+    boolean noFormat;
+
+    protected void doExecute(RepositoryAdmin admin) {
+
+        ShellTable table = new ShellTable();
+        table.column("Index");
+        table.column("OBR URL");
+        table.emptyTableText("No OBR repository URL");
+
+        Repository[] repos = admin.listRepositories();
+        if (repos != null) {
+            for (int i = 0; i < repos.length; i++) {
+                table.addRow().addContent(i, repos[i].getURI());
+            }
+        }
+
+        table.print(System.out, !noFormat);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/b0a20b83/obr/src/main/java/org/apache/karaf/obr/command/ObrCommandSupport.java
----------------------------------------------------------------------
diff --git a/obr/src/main/java/org/apache/karaf/obr/command/ObrCommandSupport.java b/obr/src/main/java/org/apache/karaf/obr/command/ObrCommandSupport.java
new file mode 100644
index 0000000..5f038b4
--- /dev/null
+++ b/obr/src/main/java/org/apache/karaf/obr/command/ObrCommandSupport.java
@@ -0,0 +1,281 @@
+/*
+ * 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.karaf.obr.command;
+
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
+import java.io.PrintStream;
+import java.util.List;
+
+import org.apache.felix.bundlerepository.Reason;
+import org.apache.felix.bundlerepository.Repository;
+import org.apache.felix.bundlerepository.RepositoryAdmin;
+import org.apache.felix.bundlerepository.Requirement;
+import org.apache.felix.bundlerepository.Resolver;
+import org.apache.felix.bundlerepository.Resource;
+import org.apache.karaf.shell.api.action.Action;
+import org.apache.karaf.shell.api.action.lifecycle.Reference;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.Version;
+
+public abstract class ObrCommandSupport implements Action {
+
+    protected static final char VERSION_DELIM = ',';
+
+    @Reference
+    private RepositoryAdmin repositoryAdmin;
+
+    @Reference
+    BundleContext bundleContext;
+
+    public void setRepositoryAdmin(RepositoryAdmin repositoryAdmin) {
+        this.repositoryAdmin = repositoryAdmin;
+    }
+
+    @Override
+    public Object execute() throws Exception {
+        doExecute(repositoryAdmin);
+        return null;
+    }
+
+    abstract void doExecute(RepositoryAdmin admin) throws Exception;
+
+    protected Resource[] searchRepository(RepositoryAdmin admin, String targetId, String targetVersion) throws InvalidSyntaxException {
+        // Try to see if the targetId is a bundle ID.
+        try {
+            Bundle bundle = bundleContext.getBundle(Long.parseLong(targetId));
+            targetId = bundle.getSymbolicName();
+        } catch (NumberFormatException ex) {
+            // It was not a number, so ignore.
+        }
+
+        // The targetId may be a bundle name or a bundle symbolic name,
+        // so create the appropriate LDAP query.
+        StringBuffer sb = new StringBuffer("(|(presentationname=");
+        sb.append(targetId);
+        sb.append(")(symbolicname=");
+        sb.append(targetId);
+        sb.append("))");
+        if (targetVersion != null) {
+            sb.insert(0, "(&");
+            sb.append("(version=");
+            sb.append(targetVersion);
+            sb.append("))");
+        }
+        return admin.discoverResources(sb.toString());
+    }
+
+    public Resource selectNewestVersion(Resource[] resources) {
+        int idx = -1;
+        Version v = null;
+        for (int i = 0; (resources != null) && (i < resources.length); i++) {
+            if (i == 0) {
+                idx = 0;
+                v = resources[i].getVersion();
+            } else {
+                Version vtmp = resources[i].getVersion();
+                if (vtmp.compareTo(v) > 0) {
+                    idx = i;
+                    v = vtmp;
+                }
+            }
+        }
+        return (idx < 0) ? null : resources[idx];
+    }
+
+    protected String[] getTarget(String bundle) {
+        String[] target;
+        int idx = bundle.indexOf(VERSION_DELIM);
+        if (idx > 0) {
+            target = new String[]{bundle.substring(0, idx), bundle.substring(idx + 1)};
+        } else {
+            target = new String[]{bundle, null};
+        }
+        return target;
+    }
+
+    protected void printUnderline(PrintStream out, int length) {
+        for (int i = 0; i < length; i++) {
+            out.print('-');
+        }
+        out.println("");
+    }
+
+    protected void doDeploy(RepositoryAdmin admin, List<String> bundles, boolean start, boolean deployOptional) throws Exception {
+        Resolver resolver = admin.resolver();
+        for (String bundle : bundles) {
+            String[] target = getTarget(bundle);
+            Resource resource = selectNewestVersion(searchRepository(admin, target[0], target[1]));
+            if (resource != null) {
+                resolver.add(resource);
+            } else {
+                System.err.println("Unknown bundle - " + target[0]);
+            }
+        }
+        if ((resolver.getAddedResources() != null) &&
+                (resolver.getAddedResources().length > 0)) {
+            if (resolver.resolve(deployOptional ? 0 : Resolver.NO_OPTIONAL_RESOURCES)) {
+                System.out.println("Target resource(s):");
+                printUnderline(System.out, 19);
+                Resource[] resources = resolver.getAddedResources();
+                for (int resIdx = 0; (resources != null) && (resIdx < resources.length); resIdx++) {
+                    System.out.println("   " + resources[resIdx].getPresentationName()
+                            + " (" + resources[resIdx].getVersion() + ")");
+                }
+                resources = resolver.getRequiredResources();
+                if ((resources != null) && (resources.length > 0)) {
+                    System.out.println("\nRequired resource(s):");
+                    printUnderline(System.out, 21);
+                    for (int resIdx = 0; resIdx < resources.length; resIdx++) {
+                        System.out.println("   " + resources[resIdx].getPresentationName()
+                                + " (" + resources[resIdx].getVersion() + ")");
+                    }
+                }
+                if (deployOptional) {
+                    resources = resolver.getOptionalResources();
+                    if ((resources != null) && (resources.length > 0)) {
+                        System.out.println("\nOptional resource(s):");
+                        printUnderline(System.out, 21);
+                        for (int resIdx = 0; resIdx < resources.length; resIdx++) {
+                            System.out.println("   " + resources[resIdx].getPresentationName() + " (" + resources[resIdx].getVersion() + ")");
+                        }
+                    }
+                }
+
+                try {
+                    System.out.print("\nDeploying...");
+                    resolver.deploy(start ? Resolver.START : 0);
+                    System.out.println("done.");
+                } catch (IllegalStateException ex) {
+                    System.err.println(ex);
+                }
+            } else {
+                Reason[] reqs = resolver.getUnsatisfiedRequirements();
+                if ((reqs != null) && (reqs.length > 0)) {
+                    System.out.println("Unsatisfied requirement(s):");
+                    printUnderline(System.out, 27);
+                    for (int reqIdx = 0; reqIdx < reqs.length; reqIdx++) {
+                        System.out.println("   " + reqs[reqIdx].getRequirement().getFilter());
+                        System.out.println("      " + reqs[reqIdx].getResource().getPresentationName());
+                    }
+                } else {
+                    System.out.println("Could not resolve targets.");
+                }
+            }
+        }
+
+    }
+
+
+    protected Requirement parseRequirement(RepositoryAdmin admin, String req) throws InvalidSyntaxException {
+        int p = req.indexOf(':');
+        String name;
+        String filter;
+        if (p > 0) {
+            name = req.substring(0, p);
+            filter = req.substring(p + 1);
+        } else {
+            if (req.contains("package")) {
+                name = "package";
+            } else if (req.contains("service")) {
+                name = "service";
+            } else {
+                name = "bundle";
+            }
+            filter = req;
+        }
+        if (!filter.startsWith("(")) {
+            filter = "(" + filter + ")";
+        }
+        return admin.getHelper().requirement(name, filter);
+    }
+
+    protected Requirement[] parseRequirements(RepositoryAdmin admin, List<String> requirements) throws InvalidSyntaxException {
+        Requirement[] reqs = new Requirement[requirements.size()];
+        for (int i = 0; i < reqs.length; i++) {
+            reqs[i] = parseRequirement(admin, requirements.get(i));
+        }
+        return reqs;
+    }
+
+    public static final String REPOSITORY_URL_PROP = "obr.repository.url";
+
+    protected void persistRepositoryList(RepositoryAdmin admin) {
+        try {
+            StringBuilder sb = new StringBuilder();
+            for (Repository repo : admin.listRepositories()) {
+                if (sb.length() > 0) {
+                    sb.append(" ");
+                }
+                sb.append(repo.getURI());
+            }
+            File etc = new File(System.getProperty("karaf.etc"));
+            File sys = new File(etc, "config.properties");
+            File sysTmp = new File(etc, "config.properties.tmp");
+
+            BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(sysTmp)));
+            boolean modified = false;
+            try {
+                if (sys.exists()) {
+                    BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(sys)));
+                    try {
+                        String line = reader.readLine();
+                        while (line != null) {
+                            if (line.matches("obr\\.repository\\.url[:= ].*")) {
+                                modified = true;
+                                line = "obr.repository.url = " + sb.toString();
+                            }
+                            writer.write(line);
+                            writer.newLine();
+                            line = reader.readLine();
+                        }
+                    } finally {
+                        reader.close();
+                    }
+                }
+                if (!modified) {
+                    writer.newLine();
+                    writer.write("# ");
+                    writer.newLine();
+                    writer.write("# OBR Repository list");
+                    writer.newLine();
+                    writer.write("# ");
+                    writer.newLine();
+                    writer.write("obr.repository.url = " + sb.toString());
+                    writer.newLine();
+                    writer.newLine();
+                }
+            } finally {
+                writer.close();
+            }
+
+            sys.delete();
+            sysTmp.renameTo(sys);
+
+        } catch (Exception e) {
+            System.err.println("Error while persisting repository list");
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/b0a20b83/obr/src/main/java/org/apache/karaf/obr/command/RefreshUrlCommand.java
----------------------------------------------------------------------
diff --git a/obr/src/main/java/org/apache/karaf/obr/command/RefreshUrlCommand.java b/obr/src/main/java/org/apache/karaf/obr/command/RefreshUrlCommand.java
new file mode 100644
index 0000000..20a65ed
--- /dev/null
+++ b/obr/src/main/java/org/apache/karaf/obr/command/RefreshUrlCommand.java
@@ -0,0 +1,63 @@
+/*
+ * 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.karaf.obr.command;
+
+import java.util.List;
+
+import org.apache.felix.bundlerepository.Repository;
+import org.apache.felix.bundlerepository.RepositoryAdmin;
+import org.apache.karaf.shell.api.action.Argument;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.Option;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+
+@Command(scope = "obr", name = "url-refresh", description = "Reloads the repositories to obtain a fresh list of bundles.")
+@Service
+public class RefreshUrlCommand extends ObrCommandSupport {
+
+    @Option(name = "-i", aliases = { "--index" }, description = "Use index to identify URL", required = false, multiValued = false)
+    boolean useIndex;
+
+    @Argument(index = 0, name = "ids", description = "Repository URLs (or indexes if you use -i) to refresh (leave empty for all)", required = false, multiValued = true)
+    List<String> ids;
+
+    protected void doExecute(RepositoryAdmin admin) throws Exception {
+		if (ids != null && !ids.isEmpty()) {
+			for (String id : ids) {
+                if (useIndex) {
+                    Repository[] repos = admin.listRepositories();
+                    int index = Integer.parseInt(id);
+                    if (index >= 0 && index < repos.length) {
+                        admin.addRepository(repos[index].getURI());
+                    } else {
+                        System.err.println("Invalid index");
+                    }
+                } else {
+				    admin.addRepository(id);
+                }
+			}
+		} else {
+			Repository[] repos = admin.listRepositories();
+			if ((repos != null) && (repos.length > 0)) {
+				for (int i = 0; i < repos.length; i++) {
+					admin.addRepository(repos[i].getURI());
+				}
+			}
+		}
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/b0a20b83/obr/src/main/java/org/apache/karaf/obr/command/RemoveUrlCommand.java
----------------------------------------------------------------------
diff --git a/obr/src/main/java/org/apache/karaf/obr/command/RemoveUrlCommand.java b/obr/src/main/java/org/apache/karaf/obr/command/RemoveUrlCommand.java
new file mode 100644
index 0000000..2d41519
--- /dev/null
+++ b/obr/src/main/java/org/apache/karaf/obr/command/RemoveUrlCommand.java
@@ -0,0 +1,54 @@
+/*
+ * 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.karaf.obr.command;
+
+import java.util.List;
+
+import org.apache.felix.bundlerepository.Repository;
+import org.apache.felix.bundlerepository.RepositoryAdmin;
+import org.apache.karaf.shell.api.action.Argument;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.Option;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+
+@Command(scope = "obr", name = "url-remove", description = "Removes a list of repository URLs from the OBR service.")
+@Service
+public class RemoveUrlCommand extends ObrCommandSupport {
+
+    @Option(name = "-i", aliases = { "--index" }, description = "Use index to identify URL", required = false, multiValued = false)
+    boolean useIndex;
+
+    @Argument(index = 0, name = "ids", description = "Repository URLs (or indexes if you use -i) to remove from OBR service", required = true, multiValued = true)
+    List<String> ids;
+
+    protected void doExecute(RepositoryAdmin admin) throws Exception {
+        for (String id : ids) {
+            if (useIndex) {
+                Repository[] repos = admin.listRepositories();
+                int index = Integer.parseInt(id);
+                if (index >= 0 && index < repos.length) {
+                    admin.removeRepository(repos[index].getURI());
+                } else {
+                    System.err.println("Invalid index");
+                }
+            } else {
+                admin.removeRepository(id);
+            }
+        }
+        persistRepositoryList(admin);
+    }
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/b0a20b83/obr/src/main/java/org/apache/karaf/obr/command/ResolveCommand.java
----------------------------------------------------------------------
diff --git a/obr/src/main/java/org/apache/karaf/obr/command/ResolveCommand.java b/obr/src/main/java/org/apache/karaf/obr/command/ResolveCommand.java
new file mode 100644
index 0000000..ab1bd04
--- /dev/null
+++ b/obr/src/main/java/org/apache/karaf/obr/command/ResolveCommand.java
@@ -0,0 +1,145 @@
+/*
+ * 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.karaf.obr.command;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.apache.felix.bundlerepository.Reason;
+import org.apache.felix.bundlerepository.Repository;
+import org.apache.felix.bundlerepository.RepositoryAdmin;
+import org.apache.felix.bundlerepository.Requirement;
+import org.apache.felix.bundlerepository.Resolver;
+import org.apache.felix.bundlerepository.Resource;
+import org.apache.karaf.shell.api.action.Argument;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.Option;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+
+@Command(scope = "obr", name = "resolve", description = "Shows the resolution output for a given set of requirements.")
+@Service
+public class ResolveCommand extends ObrCommandSupport {
+
+    @Option(name = "-w", aliases = "--why", description = "Display the reason of the inclusion of the resource")
+    boolean why;
+
+    @Option(name = "-l", aliases = "--no-local", description = "Ignore local resources during resolution")
+    boolean noLocal;
+
+    @Option(name = "--no-remote", description = "Ignore remote resources during resolution")
+    boolean noRemote;
+
+    @Option(name = "--deploy", description = "Deploy the selected bundles")
+    boolean deploy;
+
+    @Option(name = "--start", description = "Deploy and start the selected bundles")
+    boolean start;
+
+    @Option(name = "--optional", description = "Resolve optional dependencies")
+    boolean optional;
+
+    @Argument(index = 0, name = "requirements", description = "Requirements", required = true, multiValued = true)
+    List<String> requirements;
+
+    protected void doExecute(RepositoryAdmin admin) throws Exception {
+        List<Repository> repositories = new ArrayList<Repository>();
+        repositories.add(admin.getSystemRepository());
+        if (!noLocal) {
+            repositories.add(admin.getLocalRepository());
+        }
+        if (!noRemote) {
+            repositories.addAll(Arrays.asList(admin.listRepositories()));
+        }
+        Resolver resolver = admin.resolver(repositories.toArray(new Repository[repositories.size()]));
+        for (Requirement requirement : parseRequirements(admin, requirements)) {
+            resolver.add(requirement);
+        }
+        if (resolver.resolve(optional ? 0 : Resolver.NO_OPTIONAL_RESOURCES)) {
+            Resource[] resources;
+            resources = resolver.getRequiredResources();
+            if ((resources != null) && (resources.length > 0)) {
+                System.out.println("Required resource(s):");
+                printUnderline(System.out, 21);
+                for (int resIdx = 0; resIdx < resources.length; resIdx++) {
+                    System.out.println("   " + resources[resIdx].getPresentationName() + " (" + resources[resIdx].getVersion() + ")");
+                    if (why) {
+                        Reason[] req = resolver.getReason(resources[resIdx]);
+                        for (int reqIdx = 0; req != null && reqIdx < req.length; reqIdx++) {
+                            if (!req[reqIdx].getRequirement().isOptional()) {
+                                Resource r = req[reqIdx].getResource();
+                                if (r != null) {
+                                    System.out.println("      - " + r.getPresentationName() + " / " + req[reqIdx].getRequirement().getName() + ":" + req[reqIdx].getRequirement().getFilter());
+                                } else {
+                                    System.out.println("      - " + req[reqIdx].getRequirement().getName() + ":" + req[reqIdx].getRequirement().getFilter());
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+            resources = resolver.getOptionalResources();
+            if ((resources != null) && (resources.length > 0)) {
+                System.out.println();
+                System.out.println("Optional resource(s):");
+                printUnderline(System.out, 21);
+                for (int resIdx = 0; resIdx < resources.length; resIdx++) {
+                    System.out.println("   " + resources[resIdx].getPresentationName()
+                        + " (" + resources[resIdx].getVersion() + ")");
+                    if (why) {
+                        Reason[] req = resolver.getReason(resources[resIdx]);
+                        for (int reqIdx = 0; req != null && reqIdx < req.length; reqIdx++) {
+                            if (!req[reqIdx].getRequirement().isOptional()) {
+                                Resource r = req[reqIdx].getResource();
+                                if (r != null) {
+                                    System.out.println("      - " + r.getPresentationName() + " / " + req[reqIdx].getRequirement().getName() + ":" + req[reqIdx].getRequirement().getFilter());
+                                } else {
+                                    System.out.println("      - " + req[reqIdx].getRequirement().getName() + ":" + req[reqIdx].getRequirement().getFilter());
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+            if (deploy || start) {
+                try
+                {
+                    System.out.print("\nDeploying...");
+                    resolver.deploy(start ? Resolver.START : 0);
+                    System.out.println("done.");
+                }
+                catch (IllegalStateException ex)
+                {
+                    System.err.println(ex);
+                }
+            }
+        } else {
+            Reason[] reqs = resolver.getUnsatisfiedRequirements();
+            if ((reqs != null) && (reqs.length > 0)) {
+                System.out.println("Unsatisfied requirement(s):");
+                printUnderline(System.out, 27);
+                for (int reqIdx = 0; reqIdx < reqs.length; reqIdx++) {
+                    System.out.println("   " + reqs[reqIdx].getRequirement().getName() + ":" + reqs[reqIdx].getRequirement().getFilter());
+                    System.out.println("      " +reqs[reqIdx].getResource().getPresentationName());
+                }
+            } else {
+                System.out.println("Could not resolve targets.");
+            }
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/b0a20b83/obr/src/main/java/org/apache/karaf/obr/command/SourceCommand.java
----------------------------------------------------------------------
diff --git a/obr/src/main/java/org/apache/karaf/obr/command/SourceCommand.java b/obr/src/main/java/org/apache/karaf/obr/command/SourceCommand.java
new file mode 100644
index 0000000..161ba82
--- /dev/null
+++ b/obr/src/main/java/org/apache/karaf/obr/command/SourceCommand.java
@@ -0,0 +1,66 @@
+/*
+ * 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.karaf.obr.command;
+
+import java.net.URI;
+import java.util.List;
+
+import org.apache.felix.bundlerepository.RepositoryAdmin;
+import org.apache.felix.bundlerepository.Resource;
+import org.apache.karaf.obr.command.util.FileUtil;
+import org.apache.karaf.shell.api.action.Argument;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.Option;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+
+@Command(scope = "obr", name = "source", description = "Downloads the sources for an OBR bundle.")
+@Service
+public class SourceCommand extends ObrCommandSupport {
+
+    @Option(name = "-x", aliases = {}, description = "Extract the archive", required = false, multiValued = false)
+    boolean extract;
+
+    @Argument(index = 0, name = "folder", description = "Local folder for storing sources", required = true, multiValued = false)
+    String localDir;
+
+    @Argument(index = 1, name = "bundles", description = "List of bundles to download the sources for", required = true, multiValued = true)
+    List<String> bundles;
+
+    protected void doExecute(RepositoryAdmin admin) throws Exception {
+        for (String bundle : bundles) {
+            String[] target = getTarget(bundle);
+            Resource resource = selectNewestVersion(searchRepository(admin, target[0], target[1]));
+            if (resource == null)
+            {
+                System.err.println("Unknown bundle and/or version: " + target[0]);
+            }
+            else
+            {
+                URI srcURL = (URI) resource.getProperties().get(Resource.SOURCE_URI);
+                if (srcURL != null)
+                {
+                    FileUtil.downloadSource(System.out, System.err, srcURL.toURL(), localDir, extract);
+                }
+                else
+                {
+                    System.err.println("Missing source URL: " + target[0]);
+                }
+            }
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/b0a20b83/obr/src/main/java/org/apache/karaf/obr/command/StartCommand.java
----------------------------------------------------------------------
diff --git a/obr/src/main/java/org/apache/karaf/obr/command/StartCommand.java b/obr/src/main/java/org/apache/karaf/obr/command/StartCommand.java
new file mode 100644
index 0000000..0465bae
--- /dev/null
+++ b/obr/src/main/java/org/apache/karaf/obr/command/StartCommand.java
@@ -0,0 +1,41 @@
+/*
+ * 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.karaf.obr.command;
+
+import org.apache.felix.bundlerepository.RepositoryAdmin;
+import org.apache.karaf.shell.api.action.Argument;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.Option;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+
+import java.util.List;
+
+@Command(scope = "obr", name = "start", description = "Deploys and starts a list of bundles using OBR.")
+@Service
+public class StartCommand extends ObrCommandSupport {
+
+    @Argument(index = 0, name = "bundles", description = "List of bundles to deploy (separated by whitespaces)", required = true, multiValued = true)
+    protected List<String> bundles;
+
+    @Option(name = "-d", aliases = { "--deployOptional" }, description = "Deploy optional bundles", required = false, multiValued = false)
+    protected boolean deployOptional = false;
+
+    protected void doExecute(RepositoryAdmin admin) throws Exception {
+        doDeploy(admin, bundles, true, deployOptional);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/b0a20b83/obr/src/main/java/org/apache/karaf/obr/command/util/FileUtil.java
----------------------------------------------------------------------
diff --git a/obr/src/main/java/org/apache/karaf/obr/command/util/FileUtil.java b/obr/src/main/java/org/apache/karaf/obr/command/util/FileUtil.java
new file mode 100644
index 0000000..26aa0bd
--- /dev/null
+++ b/obr/src/main/java/org/apache/karaf/obr/command/util/FileUtil.java
@@ -0,0 +1,177 @@
+/*
+ * 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.karaf.obr.command.util;
+
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.PrintStream;
+import java.net.URL;
+import java.net.URLConnection;
+import java.util.jar.JarEntry;
+import java.util.jar.JarInputStream;
+
+public class FileUtil
+{
+    public static void downloadSource(
+        PrintStream out, PrintStream err,
+        URL srcURL, String dirStr, boolean extract)
+    {
+        // Get the file name from the URL.
+        String fileName = (srcURL.getFile().lastIndexOf('/') > 0)
+            ? srcURL.getFile().substring(srcURL.getFile().lastIndexOf('/') + 1)
+            : srcURL.getFile();
+
+        try
+        {
+            out.println("Connecting...");
+
+            File dir = new File(dirStr);
+            if (!dir.exists())
+            {
+                err.println("Destination directory does not exist.");
+            }
+            File file = new File(dir, fileName);
+
+            OutputStream os = new FileOutputStream(file);
+            URLConnection conn = srcURL.openConnection();
+            int total = conn.getContentLength();
+            InputStream is = conn.getInputStream();
+
+            if (total > 0)
+            {
+                out.println("Downloading " + fileName
+                    + " ( " + total + " bytes ).");
+            }
+            else
+            {
+                out.println("Downloading " + fileName + ".");
+            }
+            byte[] buffer = new byte[4096];
+            int count = 0;
+            for (int len = is.read(buffer); len > 0; len = is.read(buffer))
+            {
+                count += len;
+                os.write(buffer, 0, len);
+            }
+
+            os.close();
+            is.close();
+
+            if (extract)
+            {
+                is = new FileInputStream(file);
+                JarInputStream jis = new JarInputStream(is);
+                out.println("Extracting...");
+                unjar(jis, dir);
+                jis.close();
+                file.delete();
+            }
+        }
+        catch (Exception ex)
+        {
+            err.println(ex);
+        }
+    }
+
+    public static void unjar(JarInputStream jis, File dir)
+        throws IOException
+    {
+        // Reusable buffer.
+        byte[] buffer = new byte[4096];
+
+        // Loop through JAR entries.
+        for (JarEntry je = jis.getNextJarEntry();
+             je != null;
+             je = jis.getNextJarEntry())
+        {
+            if (je.getName().startsWith("/"))
+            {
+                throw new IOException("JAR resource cannot contain absolute paths.");
+            }
+
+            File target = new File(dir, je.getName());
+
+            // Check to see if the JAR entry is a directory.
+            if (je.isDirectory())
+            {
+                if (!target.exists())
+                {
+                    if (!target.mkdirs())
+                    {
+                        throw new IOException("Unable to create target directory: "
+                            + target);
+                    }
+                }
+                // Just continue since directories do not have content to copy.
+                continue;
+            }
+
+            int lastIndex = je.getName().lastIndexOf('/');
+            String name = (lastIndex >= 0) ?
+                je.getName().substring(lastIndex + 1) : je.getName();
+            String destination = (lastIndex >= 0) ?
+                je.getName().substring(0, lastIndex) : "";
+
+            // JAR files use '/', so convert it to platform separator.
+            destination = destination.replace('/', File.separatorChar);
+            copy(jis, dir, name, destination, buffer);
+        }
+    }
+
+    public static void copy(
+        InputStream is, File dir, String destName, String destDir, byte[] buffer)
+        throws IOException
+    {
+        if (destDir == null)
+        {
+            destDir = "";
+        }
+
+        // Make sure the target directory exists and
+        // that is actually a directory.
+        File targetDir = new File(dir, destDir);
+        if (!targetDir.exists())
+        {
+            if (!targetDir.mkdirs())
+            {
+                throw new IOException("Unable to create target directory: "
+                    + targetDir);
+            }
+        }
+        else if (!targetDir.isDirectory())
+        {
+            throw new IOException("Target is not a directory: "
+                + targetDir);
+        }
+
+        BufferedOutputStream bos = new BufferedOutputStream(
+            new FileOutputStream(new File(targetDir, destName)));
+        int count = 0;
+        while ((count = is.read(buffer)) > 0)
+        {
+            bos.write(buffer, 0, count);
+        }
+        bos.close();
+    }
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/b0a20b83/obr/src/main/java/org/apache/karaf/obr/core/ObrMBean.java
----------------------------------------------------------------------
diff --git a/obr/src/main/java/org/apache/karaf/obr/core/ObrMBean.java b/obr/src/main/java/org/apache/karaf/obr/core/ObrMBean.java
new file mode 100644
index 0000000..bf5ebcb
--- /dev/null
+++ b/obr/src/main/java/org/apache/karaf/obr/core/ObrMBean.java
@@ -0,0 +1,37 @@
+/*
+ * 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.karaf.obr.core;
+
+import javax.management.MBeanException;
+import javax.management.openmbean.TabularData;
+import java.util.List;
+
+/**
+ * OBR MBean.
+ */
+public interface ObrMBean {
+
+    List<String> getUrls();
+    TabularData getBundles() throws MBeanException;
+
+    void addUrl(String url) throws MBeanException;
+    void removeUrl(String url);
+    void refreshUrl(String url) throws MBeanException;
+
+    void deployBundle(String bundle) throws MBeanException;
+    void deployBundle(String bundle, boolean start, boolean deployOptional) throws MBeanException;
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/b0a20b83/obr/src/main/java/org/apache/karaf/obr/core/internal/ObrMBeanImpl.java
----------------------------------------------------------------------
diff --git a/obr/src/main/java/org/apache/karaf/obr/core/internal/ObrMBeanImpl.java b/obr/src/main/java/org/apache/karaf/obr/core/internal/ObrMBeanImpl.java
new file mode 100644
index 0000000..c182165
--- /dev/null
+++ b/obr/src/main/java/org/apache/karaf/obr/core/internal/ObrMBeanImpl.java
@@ -0,0 +1,203 @@
+/*
+ * 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.karaf.obr.core.internal;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.management.MBeanException;
+import javax.management.NotCompliantMBeanException;
+import javax.management.StandardMBean;
+import javax.management.openmbean.CompositeData;
+import javax.management.openmbean.CompositeDataSupport;
+import javax.management.openmbean.CompositeType;
+import javax.management.openmbean.OpenType;
+import javax.management.openmbean.SimpleType;
+import javax.management.openmbean.TabularData;
+import javax.management.openmbean.TabularDataSupport;
+import javax.management.openmbean.TabularType;
+
+import org.apache.felix.bundlerepository.Repository;
+import org.apache.felix.bundlerepository.RepositoryAdmin;
+import org.apache.felix.bundlerepository.Resolver;
+import org.apache.felix.bundlerepository.Resource;
+import org.apache.karaf.obr.core.ObrMBean;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.Version;
+
+/**
+ * Implementation of the OBR MBean.
+ */
+public class ObrMBeanImpl extends StandardMBean implements ObrMBean {
+
+    private static final char VERSION_DELIM = ',';
+
+    private BundleContext bundleContext;
+    private RepositoryAdmin repositoryAdmin;
+
+    public ObrMBeanImpl(BundleContext bundleContext, RepositoryAdmin repositoryAdmin) throws NotCompliantMBeanException {
+        super(ObrMBean.class);
+        this.bundleContext = bundleContext;
+        this.repositoryAdmin = repositoryAdmin;
+    }
+
+    public List<String> getUrls() {
+        Repository[] repositories = repositoryAdmin.listRepositories();
+        List<String> urls = new ArrayList<String>();
+        for (int i = 0; i < repositories.length; i++) {
+            urls.add(repositories[i].getURI());
+        }
+        return urls;
+    }
+
+    public TabularData getBundles() throws MBeanException {
+        try {
+            CompositeType bundleType = new CompositeType("OBR Resource", "Bundle available in the OBR",
+                    new String[]{"presentationname", "symbolicname", "version"},
+                    new String[]{"Presentation Name", "Symbolic Name", "Version"},
+                    new OpenType[]{SimpleType.STRING, SimpleType.STRING, SimpleType.STRING});
+            TabularType tableType = new TabularType("OBR Resources", "Table of all resources/bundles available in the OBR",
+                    bundleType, new String[]{"symbolicname", "version"});
+            TabularData table = new TabularDataSupport(tableType);
+
+            Resource[] resources = repositoryAdmin.discoverResources("(|(presentationname=*)(symbolicname=*))");
+            for (int i = 0; i < resources.length; i++) {
+                try {
+                    CompositeData data = new CompositeDataSupport(bundleType,
+                            new String[]{"presentationname", "symbolicname", "version"},
+                            new Object[]{resources[i].getPresentationName(), resources[i].getSymbolicName(), resources[i].getVersion().toString()});
+                    table.put(data);
+                } catch (Exception e) {
+                    e.printStackTrace();
+                }
+            }
+
+            return table;
+        } catch (Exception e) {
+            throw new MBeanException(null, e.getMessage());
+        }
+    }
+
+    public void addUrl(String url) throws MBeanException {
+        try {
+            repositoryAdmin.addRepository(url);
+        } catch (Exception e) {
+            throw new MBeanException(null, e.getMessage());
+        }
+    }
+
+    public void removeUrl(String url) {
+        repositoryAdmin.removeRepository(url);
+    }
+
+    public void refreshUrl(String url) throws MBeanException {
+        try {
+            repositoryAdmin.addRepository(url);
+        } catch (Exception e) {
+            throw new MBeanException(null, e.getMessage());
+        }
+    }
+
+    public void deployBundle(String bundle) throws MBeanException {
+        try {
+            deployBundle(bundle, false, false);
+        } catch (Exception e) {
+            throw new MBeanException(null, e.getMessage());
+        }
+    }
+
+    public void deployBundle(String bundle, boolean start, boolean deployOptional) throws MBeanException {
+        try {
+            Resolver resolver = repositoryAdmin.resolver();
+            String[] target = getTarget(bundle);
+            Resource resource = selectNewestVersion(searchRepository(repositoryAdmin, target[0], target[1]));
+            if (resource == null) {
+                throw new IllegalArgumentException("Unknown bundle " + target[0]);
+            }
+            resolver.add(resource);
+            if ((resolver.getAddedResources() != null) &&
+                    (resolver.getAddedResources().length > 0)) {
+                if (resolver.resolve(deployOptional ? 0 : Resolver.NO_OPTIONAL_RESOURCES)) {
+                    try {
+                        resolver.deploy(start ? Resolver.START : 0);
+                    } catch (IllegalStateException ex) {
+                        throw new IllegalStateException("Can't deploy using OBR", ex);
+                    }
+                }
+            }
+        } catch (Exception e) {
+            throw new MBeanException(null, e.getMessage());
+        }
+    }
+
+    private Resource[] searchRepository(RepositoryAdmin admin, String targetId, String targetVersion) throws InvalidSyntaxException {
+        // Try to see if the targetId is a bundle ID.
+        try {
+            Bundle bundle = bundleContext.getBundle(Long.parseLong(targetId));
+            targetId = bundle.getSymbolicName();
+        } catch (NumberFormatException ex) {
+            // It was not a number, so ignore.
+        }
+
+        // The targetId may be a bundle name or a bundle symbolic name,
+        // so create the appropriate LDAP query.
+        StringBuffer sb = new StringBuffer("(|(presentationname=");
+        sb.append(targetId);
+        sb.append(")(symbolicname=");
+        sb.append(targetId);
+        sb.append("))");
+        if (targetVersion != null) {
+            sb.insert(0, "(&");
+            sb.append("(version=");
+            sb.append(targetVersion);
+            sb.append("))");
+        }
+        return admin.discoverResources(sb.toString());
+    }
+
+    private Resource selectNewestVersion(Resource[] resources) {
+        int idx = -1;
+        Version v = null;
+        for (int i = 0; (resources != null) && (i < resources.length); i++) {
+            if (i == 0) {
+                idx = 0;
+                v = resources[i].getVersion();
+            } else {
+                Version vtmp = resources[i].getVersion();
+                if (vtmp.compareTo(v) > 0) {
+                    idx = i;
+                    v = vtmp;
+                }
+            }
+        }
+        return (idx < 0) ? null : resources[idx];
+    }
+
+    private String[] getTarget(String bundle) {
+        String[] target;
+        int idx = bundle.indexOf(VERSION_DELIM);
+        if (idx > 0) {
+            target = new String[]{bundle.substring(0, idx), bundle.substring(idx + 1)};
+        } else {
+            target = new String[]{bundle, null};
+        }
+        return target;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/b0a20b83/obr/src/main/resources/OSGI-INF/blueprint/blueprint.xml
----------------------------------------------------------------------
diff --git a/obr/src/main/resources/OSGI-INF/blueprint/blueprint.xml b/obr/src/main/resources/OSGI-INF/blueprint/blueprint.xml
new file mode 100644
index 0000000..4fbe9fb
--- /dev/null
+++ b/obr/src/main/resources/OSGI-INF/blueprint/blueprint.xml
@@ -0,0 +1,34 @@
+<?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"
+    xmlns:cm="http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.1.0"
+    xmlns:ext="http://aries.apache.org/blueprint/xmlns/blueprint-ext/v1.0.0">
+
+    <ext:property-placeholder />
+
+    <reference id="repositoryAdmin" interface="org.apache.felix.bundlerepository.RepositoryAdmin"/>
+
+    <bean id="obrMBean" class="org.apache.karaf.obr.core.internal.ObrMBeanImpl">
+        <argument ref="blueprintBundleContext"/>
+        <argument ref="repositoryAdmin"/>
+    </bean>
+
+    <service ref="obrMBean" auto-export="interfaces">
+        <service-properties>
+            <entry key="jmx.objectname" value="org.apache.karaf:type=obr,name=${karaf.name}"/>
+        </service-properties>
+    </service>
+
+</blueprint>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/karaf/blob/b0a20b83/obr/src/main/resources/OSGI-INF/bundle.info
----------------------------------------------------------------------
diff --git a/obr/src/main/resources/OSGI-INF/bundle.info b/obr/src/main/resources/OSGI-INF/bundle.info
new file mode 100644
index 0000000..e14433c
--- /dev/null
+++ b/obr/src/main/resources/OSGI-INF/bundle.info
@@ -0,0 +1,25 @@
+h1. Synopsis
+
+${project.name}
+
+${project.description}
+
+Maven URL:
+[mvn:${project.groupId}/${project.artifactId}/${project.version}]
+
+h1. Description
+
+The obr mbean management bundle exposes an OBR MBean that can be used with any JMX client (for instance JConsole).
+
+The OBR MBean allows quite the same actions that can be performed using obr:* commands:
+  * listUrls()
+  * addUrl(url)
+  * removeUrl(url)
+  * refreshUrl(url)
+  * list()
+  * deploy(bundle)
+  * deploy(bundle, start)
+
+h1. See also
+
+  * Monitoring and Administration using JMX - section of the Karaf User Guide


[28/59] [abbrv] [KARAF-2852] Merge instance/core and instance/command

Posted by gn...@apache.org.
http://git-wip-us.apache.org/repos/asf/karaf/blob/7c2db062/instance/core/src/main/java/org/apache/karaf/instance/core/internal/InstancesMBeanImpl.java
----------------------------------------------------------------------
diff --git a/instance/core/src/main/java/org/apache/karaf/instance/core/internal/InstancesMBeanImpl.java b/instance/core/src/main/java/org/apache/karaf/instance/core/internal/InstancesMBeanImpl.java
deleted file mode 100644
index b95e4dc..0000000
--- a/instance/core/src/main/java/org/apache/karaf/instance/core/internal/InstancesMBeanImpl.java
+++ /dev/null
@@ -1,224 +0,0 @@
-/*
- * 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.karaf.instance.core.internal;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-
-import javax.management.MBeanException;
-import javax.management.NotCompliantMBeanException;
-import javax.management.StandardMBean;
-import javax.management.openmbean.TabularData;
-
-import org.apache.karaf.instance.core.Instance;
-import org.apache.karaf.instance.core.InstanceSettings;
-import org.apache.karaf.instance.core.InstancesMBean;
-
-public class InstancesMBeanImpl extends StandardMBean implements InstancesMBean {
-
-    static final String DEBUG_OPTS = " -Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005";
-    static final String DEFAULT_OPTS = "-server -Xmx512M -Dcom.sun.management.jmxremote";
-
-    private org.apache.karaf.instance.core.InstanceService instanceService;
-
-    public InstancesMBeanImpl(org.apache.karaf.instance.core.InstanceService instanceService) throws NotCompliantMBeanException {
-        super(InstancesMBean.class);
-        this.instanceService = instanceService;
-    }
-
-    public int createInstance(String name, int sshPort, int rmiRegistryPort, int rmiServerPort, String location, String javaOpts, String features, String featureURLs)
-            throws MBeanException {
-        try {
-            if ("".equals(location)) {
-                location = null;
-            }
-            if ("".equals(javaOpts)) {
-                javaOpts = null;
-            }
-
-            InstanceSettings settings = new InstanceSettings(sshPort, rmiRegistryPort, rmiServerPort, location, javaOpts,
-                    parseStringList(featureURLs), parseStringList(features));
-
-            Instance inst = instanceService.createInstance(name, settings, false);
-            if (inst != null) {
-                return inst.getPid();
-            } else {
-                return -1;
-            }
-        } catch (Exception e) {
-            throw new MBeanException(null, e.getMessage());
-        }
-    }
-
-    public void changeSshPort(String name, int port) throws MBeanException {
-        try {
-            getExistingInstance(name).changeSshPort(port);
-        } catch (Exception e) {
-            throw new MBeanException(null, e.getMessage());
-        }
-    }
-
-    public void changeRmiRegistryPort(String name, int port) throws MBeanException {
-        try {
-            getExistingInstance(name).changeRmiRegistryPort(port);
-        } catch (Exception e) {
-            throw new MBeanException(null, e.getMessage());
-        }
-    }
-
-    public void changeRmiServerPort(String name, int port) throws MBeanException {
-        try {
-            getExistingInstance(name).changeRmiServerPort(port);
-        } catch (Exception e) {
-            throw new MBeanException(null, e.getMessage());
-        }
-    }
-
-    public void changeJavaOpts(String name, String javaOpts) throws MBeanException {
-        try {
-            getExistingInstance(name).changeJavaOpts(javaOpts);
-        } catch (Exception e) {
-            throw new MBeanException(null, e.getMessage());
-        }
-    }
-
-    public void destroyInstance(String name) throws MBeanException {
-        try {
-            getExistingInstance(name).destroy();
-        } catch (Exception e) {
-            throw new MBeanException(null, e.getMessage());
-        }
-    }
-
-    public void startInstance(String name) throws MBeanException {
-        try {
-            getExistingInstance(name).start(null);
-        } catch (Exception e) {
-            throw new MBeanException(null, e.getMessage());
-        }
-    }
-
-    public void startInstance(String name, String opts) throws MBeanException {
-        try {
-            getExistingInstance(name).start(opts);
-        } catch (Exception e) {
-            throw new MBeanException(null, e.getMessage());
-        }
-    }
-
-    public void startInstance(String name, String opts, boolean wait, boolean debug) throws MBeanException {
-        try {
-            Instance child = getExistingInstance(name);
-            String options = opts;
-            if (options == null) {
-                options = child.getJavaOpts();
-            }
-            if (options == null) {
-                options = DEFAULT_OPTS;
-            }
-            if (debug) {
-                options += DEBUG_OPTS;
-            }
-            if (wait) {
-                String state = child.getState();
-                if (Instance.STOPPED.equals(state)) {
-                    child.start(opts);
-                }
-                if (!Instance.STARTED.equals(state)) {
-                    do {
-                        Thread.sleep(500);
-                        state = child.getState();
-                    } while (Instance.STARTING.equals(state));
-                }
-            } else {
-                child.start(opts);
-            }
-        } catch (Exception e) {
-            throw new MBeanException(null, e.getMessage());
-        }
-    }
-
-    public void stopInstance(String name) throws MBeanException {
-        try {
-            getExistingInstance(name).stop();
-        } catch (Exception e) {
-            throw new MBeanException(null, e.getMessage());
-        }
-    }
-
-    public void renameInstance(String originalName, String newName) throws MBeanException {
-        try {
-            instanceService.renameInstance(originalName, newName, false);
-        } catch (Exception e) {
-            throw new MBeanException(null, e.getMessage());
-        }
-    }
-
-    public void renameInstance(String originalName, String newName, boolean verbose) throws MBeanException {
-        try {
-            instanceService.renameInstance(originalName, newName, verbose);
-        } catch (Exception e) {
-            throw new MBeanException(null, e.getMessage());
-        }
-    }
-
-    public void cloneInstance(String name, String cloneName, int sshPort, int rmiRegistryPort, int rmiServerPort, String location, String javaOpts) throws MBeanException {
-        try {
-            if ("".equals(location)) {
-                location = null;
-            }
-            if ("".equals(javaOpts)) {
-                javaOpts = null;
-            }
-
-            InstanceSettings settings = new InstanceSettings(sshPort, rmiRegistryPort, rmiServerPort, location, javaOpts, null, null);
-
-            instanceService.cloneInstance(name, cloneName, settings, false);
-        } catch (Exception e) {
-            throw new MBeanException(null, e.getMessage());
-        }
-    }
-
-    public TabularData getInstances() throws MBeanException {
-        List<Instance> instances = Arrays.asList(instanceService.getInstances());
-        TabularData table = InstanceToTableMapper.tableFrom(instances);
-        return table;
-    }
-
-    private Instance getExistingInstance(String name) {
-        Instance i = instanceService.getInstance(name);
-        if (i == null) {
-            throw new IllegalArgumentException("Instance '" + name + "' does not exist");
-        }
-        return i;
-    }
-
-    private List<String> parseStringList(String value) {
-        List<String> list = new ArrayList<String>();
-        if (value != null) {
-            for (String el : value.split(",")) {
-                String trimmed = el.trim();
-                if (trimmed.length() == 0) {
-                    continue;
-                }
-                list.add(trimmed);
-            }
-        }
-        return list;
-    }
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/7c2db062/instance/core/src/main/java/org/apache/karaf/instance/core/internal/osgi/Activator.java
----------------------------------------------------------------------
diff --git a/instance/core/src/main/java/org/apache/karaf/instance/core/internal/osgi/Activator.java b/instance/core/src/main/java/org/apache/karaf/instance/core/internal/osgi/Activator.java
deleted file mode 100644
index a50db46..0000000
--- a/instance/core/src/main/java/org/apache/karaf/instance/core/internal/osgi/Activator.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * 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.karaf.instance.core.internal.osgi;
-
-import org.apache.karaf.instance.core.InstanceService;
-import org.apache.karaf.instance.core.internal.InstanceServiceImpl;
-import org.apache.karaf.instance.core.internal.InstancesMBeanImpl;
-import org.apache.karaf.util.tracker.BaseActivator;
-
-public class Activator extends BaseActivator {
-
-    @Override
-    protected void doStart() throws Exception {
-        InstanceService instanceService = new InstanceServiceImpl();
-        register(InstanceService.class, instanceService);
-
-        InstancesMBeanImpl mbean = new InstancesMBeanImpl(instanceService);
-        registerMBean(mbean, "type=instance");
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/7c2db062/instance/core/src/main/java/org/apache/karaf/jpm/Process.java
----------------------------------------------------------------------
diff --git a/instance/core/src/main/java/org/apache/karaf/jpm/Process.java b/instance/core/src/main/java/org/apache/karaf/jpm/Process.java
deleted file mode 100644
index 2bd3b36..0000000
--- a/instance/core/src/main/java/org/apache/karaf/jpm/Process.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * 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.karaf.jpm;
-
-import java.io.IOException;
-import java.io.Serializable;
-
-/**
- * Interface representing a process
- */
-public interface Process extends Serializable {
-
-    /**
-     * Retrieves the PID of the process
-     * @return the pid
-     */
-    int getPid();
-
-    /**
-     * Check if this process is still running
-     * @return <code>true</code> if the process is running
-     * @throws IOException if an error occurs
-     */
-    boolean isRunning() throws IOException;
-
-    /**
-     * Destroy the process.
-     *
-     * @throws IOException
-     */
-    void destroy() throws IOException;
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/7c2db062/instance/core/src/main/java/org/apache/karaf/jpm/ProcessBuilder.java
----------------------------------------------------------------------
diff --git a/instance/core/src/main/java/org/apache/karaf/jpm/ProcessBuilder.java b/instance/core/src/main/java/org/apache/karaf/jpm/ProcessBuilder.java
deleted file mode 100644
index 2b6c612..0000000
--- a/instance/core/src/main/java/org/apache/karaf/jpm/ProcessBuilder.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * 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.karaf.jpm;
-
-import java.io.File;
-import java.io.IOException;
-
-/**
- * Interface used to create new processes.
- */
-public interface ProcessBuilder {
-
-    /**
-     * Specified the current directory to run the command from
-     *
-     * @param dir the directory to run the command from
-     * @return the ProcessBuilder instance
-     */
-    ProcessBuilder directory(File dir);
-
-    /**
-     * Set the command to execute
-     *
-     * @param command the command to execute
-     * @return the ProcessBuilder instance
-     */
-    ProcessBuilder command(String command);
-
-    /**
-     * Create and start the process
-     *
-     * @return the process that has been started
-     * @throws IOException if the process can not be created
-     */
-    org.apache.karaf.jpm.Process start() throws IOException;
-
-    /**
-     * Attach to an existing process
-     *
-     * @return the process that has been attached
-     * @throws IOException if the process can not be attached to
-     */
-    org.apache.karaf.jpm.Process attach(int pid) throws IOException;
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/7c2db062/instance/core/src/main/java/org/apache/karaf/jpm/ProcessBuilderFactory.java
----------------------------------------------------------------------
diff --git a/instance/core/src/main/java/org/apache/karaf/jpm/ProcessBuilderFactory.java b/instance/core/src/main/java/org/apache/karaf/jpm/ProcessBuilderFactory.java
deleted file mode 100644
index baa563b..0000000
--- a/instance/core/src/main/java/org/apache/karaf/jpm/ProcessBuilderFactory.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * 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.karaf.jpm;
-
-
-/**
- * Factory for process builders.
- */
-public interface ProcessBuilderFactory {
-    ProcessBuilder newBuilder();
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/7c2db062/instance/core/src/main/java/org/apache/karaf/jpm/impl/ProcessBuilderFactoryImpl.java
----------------------------------------------------------------------
diff --git a/instance/core/src/main/java/org/apache/karaf/jpm/impl/ProcessBuilderFactoryImpl.java b/instance/core/src/main/java/org/apache/karaf/jpm/impl/ProcessBuilderFactoryImpl.java
deleted file mode 100644
index 12a6905..0000000
--- a/instance/core/src/main/java/org/apache/karaf/jpm/impl/ProcessBuilderFactoryImpl.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * 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.karaf.jpm.impl;
-
-import org.apache.karaf.jpm.ProcessBuilder;
-import org.apache.karaf.jpm.ProcessBuilderFactory;
-
-public class ProcessBuilderFactoryImpl implements ProcessBuilderFactory {
-
-    public ProcessBuilder newBuilder() {
-        return new ProcessBuilderImpl();
-    }
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/7c2db062/instance/core/src/main/java/org/apache/karaf/jpm/impl/ProcessBuilderImpl.java
----------------------------------------------------------------------
diff --git a/instance/core/src/main/java/org/apache/karaf/jpm/impl/ProcessBuilderImpl.java b/instance/core/src/main/java/org/apache/karaf/jpm/impl/ProcessBuilderImpl.java
deleted file mode 100644
index 08f4407..0000000
--- a/instance/core/src/main/java/org/apache/karaf/jpm/impl/ProcessBuilderImpl.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * 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.karaf.jpm.impl;
-
-import java.io.File;
-import java.io.IOException;
-
-import org.apache.karaf.jpm.Process;
-import org.apache.karaf.jpm.ProcessBuilder;
-
-
-public class ProcessBuilderImpl implements ProcessBuilder {
-
-    private File dir;
-    private String command;
-
-    public ProcessBuilder directory(File dir) {
-        this.dir = dir;
-        return this;
-    }
-
-    public ProcessBuilder command(String command) {
-        this.command = command;
-        return this;
-    }
-
-    public Process start() throws IOException {
-        return ProcessImpl.create(dir, command);
-    }
-
-    public Process attach(int pid) throws IOException {
-        return ProcessImpl.attach(pid);
-    }
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/7c2db062/instance/core/src/main/java/org/apache/karaf/jpm/impl/ProcessImpl.java
----------------------------------------------------------------------
diff --git a/instance/core/src/main/java/org/apache/karaf/jpm/impl/ProcessImpl.java b/instance/core/src/main/java/org/apache/karaf/jpm/impl/ProcessImpl.java
deleted file mode 100644
index d831fb7..0000000
--- a/instance/core/src/main/java/org/apache/karaf/jpm/impl/ProcessImpl.java
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * 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.karaf.jpm.impl;
-
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.InterruptedIOException;
-import java.util.HashMap;
-import java.util.Map;
-
-import org.apache.karaf.jpm.Process;
-
-public class ProcessImpl implements Process {
-
-    /**
-     * 
-     */
-    private static final long serialVersionUID = -8140632422386086507L;
-
-    private int pid;
-    //private File input;
-    //private File output;
-    //private File error;
-
-    public ProcessImpl(int pid/*, File input, File output, File error*/) {
-        this.pid = pid;
-        //this.input = input;
-        //this.output = output;
-        //this.error = error;
-    }
-
-    public int getPid() {
-        return pid;
-    }
-
-    public boolean isRunning() throws IOException {
-        if (ScriptUtils.isWindows()) {
-            Map<String, String> props = new HashMap<String, String>();
-            props.put("${pid}", Integer.toString(pid));
-            int ret = ScriptUtils.execute("running", props);
-            return ret == 0;
-        } else {
-            try {
-                java.lang.Process process = new java.lang.ProcessBuilder("ps", "-p", Integer.toString(pid)).start();
-                BufferedReader r = new BufferedReader(new InputStreamReader(process.getInputStream()));
-                r.readLine(); // skip headers
-                String s = r.readLine();
-                boolean running = s != null && s.length() > 0;
-                process.waitFor();
-                return running;
-            } catch (InterruptedException e) {
-                throw new InterruptedIOException();
-            }
-        }
-    }
-
-    public void destroy() throws IOException {
-        int ret;
-        if (ScriptUtils.isWindows()) {
-            Map<String, String> props = new HashMap<String, String>();
-            props.put("${pid}", Integer.toString(pid));
-            ret = ScriptUtils.execute("destroy", props);
-        } else {
-            ret = ScriptUtils.executeProcess(new java.lang.ProcessBuilder("kill", "-9", Integer.toString(pid)));
-        }
-        if (ret != 0) {
-            throw new IOException("Unable to destroy process, it may already be terminated");
-        }
-    }
-
-    /*
-    public OutputStream getInputStream() throws FileNotFoundException {
-        return new FileOutputStream(input);
-    }
-
-    public InputStream getOutputStream() throws FileNotFoundException {
-        return new FileInputStream(output);
-    }
-
-    public InputStream getErrorStream() throws FileNotFoundException {
-        return new FileInputStream(error);
-    }
-    */
-
-    public int waitFor() throws InterruptedException {
-        return 0;
-    }
-
-    public int exitValue() {
-        return 0;
-    }
-
-    public static Process create(File dir, String command) throws IOException {
-        //File input = File.createTempFile("jpm.", ".input");
-        //File output = File.createTempFile("jpm.", ".output");
-        //File error = File.createTempFile("jpm.", ".error");
-        File pidFile = File.createTempFile("jpm.", ".pid");
-        try {
-            Map<String, String> props = new HashMap<String, String>();
-            //props.put("${in.file}", input.getCanonicalPath());
-            //props.put("${out.file}", output.getCanonicalPath());
-            //props.put("${err.file}", error.getCanonicalPath());
-            props.put("${pid.file}", pidFile.getCanonicalPath());
-            props.put("${dir}", dir != null ? dir.getCanonicalPath() : "");
-            if (ScriptUtils.isWindows()) {
-                command = command.replaceAll("\"", "\"\"");
-            }
-            props.put("${command}", command);
-            int ret = ScriptUtils.execute("start", props);
-            if (ret != 0) {
-                throw new IOException("Unable to create process (error code: " + ret + ")");
-            }
-            int pid = readPid(pidFile);
-            return new ProcessImpl(pid/*, input, output, error*/);
-        } finally {
-            pidFile.delete();
-        }
-    }
-
-    public static Process attach(int pid) throws IOException {
-        return new ProcessImpl(pid);
-    }
-
-    private static int readPid(File pidFile) throws IOException {
-        InputStream is = new FileInputStream(pidFile);
-        try {
-            BufferedReader r = new BufferedReader(new InputStreamReader(is));
-            String pidString = r.readLine();
-            return Integer.valueOf(pidString);
-        } finally {
-            try {
-                is.close();
-            } catch (IOException e) {}
-        }
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/7c2db062/instance/core/src/main/java/org/apache/karaf/jpm/impl/ScriptUtils.java
----------------------------------------------------------------------
diff --git a/instance/core/src/main/java/org/apache/karaf/jpm/impl/ScriptUtils.java b/instance/core/src/main/java/org/apache/karaf/jpm/impl/ScriptUtils.java
deleted file mode 100644
index a96e28e..0000000
--- a/instance/core/src/main/java/org/apache/karaf/jpm/impl/ScriptUtils.java
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * 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.karaf.jpm.impl;
-
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InterruptedIOException;
-import java.io.OutputStream;
-import java.io.PrintStream;
-import java.util.Map;
-import java.util.Scanner;
-
-public class ScriptUtils {
-
-    public static int execute(String name, Map<String, String> props) throws IOException {
-        File script = File.createTempFile("jpm.", ".script");
-        try {
-            if (isWindows()) {
-                String res = "windows/" + name + ".vbs";
-                ScriptUtils.copyFilteredResource(res, script, props);
-                return executeProcess(new java.lang.ProcessBuilder("cscript",
-                                                                   "/NOLOGO",
-                                                                   "//E:vbs",
-                                                                   script.getCanonicalPath()));
-            } else {
-                String res = "unix/" + name + ".sh";
-                ScriptUtils.copyFilteredResource(res, script, props);
-                return executeProcess(new java.lang.ProcessBuilder("/bin/sh",
-                                                                   script.getCanonicalPath()));
-            }
-        } finally {
-            script.delete();
-        }
-    }
-
-    public static int executeProcess(java.lang.ProcessBuilder builder) throws IOException {
-        try {
-            java.lang.Process process = builder.start();
-            return process.waitFor();
-        } catch (InterruptedException e) {
-            throw new InterruptedIOException();
-        }
-    }
-
-    public static void copyFilteredResource(String resource, File outFile, Map<String, String> props) throws IOException {
-        InputStream is = null;
-        try {
-            is = ScriptUtils.class.getResourceAsStream(resource);
-            // Read it line at a time so that we can use the platform line ending when we write it out.
-            PrintStream out = new PrintStream(new FileOutputStream(outFile));
-            try {
-                Scanner scanner = new Scanner(is);
-                while (scanner.hasNextLine() ) {
-                    String line = scanner.nextLine();
-                    line = filter(line, props);
-                    out.println(line);
-                }
-            } finally {
-                safeClose(out);
-            }
-        } finally {
-            safeClose(is);
-        }
-    }
-
-    private static void safeClose(InputStream is) throws IOException {
-        if (is == null) {
-            return;
-        }
-        try {
-            is.close();
-        } catch (Throwable ignore) {
-        }
-    }
-
-    private static void safeClose(OutputStream is) throws IOException {
-        if (is == null) {
-            return;
-        }
-        try {
-            is.close();
-        } catch (Throwable ignore) {
-        }
-    }
-
-    private static String filter(String line, Map<String, String> props) {
-        for (Map.Entry<String, String> i : props.entrySet()) {
-            int p1 = line.indexOf(i.getKey());
-            if( p1 >= 0 ) {
-                String l1 = line.substring(0, p1);
-                String l2 = line.substring(p1+i.getKey().length());
-                line = l1+i.getValue()+l2;
-            }
-        }
-        return line;
-    }
-
-    private static final boolean windows;
-
-    static {
-        windows = System.getProperty("os.name").toLowerCase().indexOf("windows") != -1;
-    }
-
-    public static boolean isWindows() {
-        return windows;
-    }
-
-    public static String getJavaCommandPath() throws IOException {
-        return new File(System.getProperty("java.home"), isWindows() ? "bin\\java.exe" : "bin/java").getCanonicalPath();
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/7c2db062/instance/core/src/main/resources/OSGI-INF/bundle.info
----------------------------------------------------------------------
diff --git a/instance/core/src/main/resources/OSGI-INF/bundle.info b/instance/core/src/main/resources/OSGI-INF/bundle.info
deleted file mode 100644
index 9d305c3..0000000
--- a/instance/core/src/main/resources/OSGI-INF/bundle.info
+++ /dev/null
@@ -1,36 +0,0 @@
-h1. Synopsis
-
-${project.name}
-
-${project.description}
-
-Maven URL:
-[mvn:${project.groupId}/${project.artifactId}/${project.version}]
-
-h1. Description
-
-This bundle is the core implementation of the Karaf instance feature.
-
-Karaf instance allows you to manage Karaf child instances.
-
-You can create new Karaf instances, configure attributes, rename instances, stop instances, etc.
-
-It also provides JMX MBeans related to the Karaf instance feature.
-
-In particular, an InstanceServiceMBean is provided that can be remotely administered using a JMX client (for instance
-JConsole).
-
-With this InstanceServiceMBean, you have the following operations available:
-* createInstance(name, sshPort, rmiPort, location, javaOpts, features, featureURLs) - Creates a new Karaf instance.
-* changeSshPort(name, port) - Changes the SSH port number of an existing Karaf instance.
-* changeRmiRegistryPort(name, port) - Changes the RMI registry port number of an existing Karaf instance.
-* changeRmiServerPort(name, port) - Changes the RMI server port number of an existing Karaf instance.
-* changeJavaOpts(name, javaopts) - Changes the Java options of an existing Karaf instance.
-* destroyInstance(name) - Destroys an existing Karaf instance.
-* startInstance(name) - Starts an existing Karaf instance.
-* stopInstance(name) - Stops an existing Karaf instance.
-* renameInstance(originalName, newName) - Renames an existing Karaf instance.
-
-h1. See also
-
-Managing child instances - of the Karaf User Guide.

http://git-wip-us.apache.org/repos/asf/karaf/blob/7c2db062/instance/core/src/main/resources/org/apache/karaf/instance/resources/bin/karaf
----------------------------------------------------------------------
diff --git a/instance/core/src/main/resources/org/apache/karaf/instance/resources/bin/karaf b/instance/core/src/main/resources/org/apache/karaf/instance/resources/bin/karaf
deleted file mode 100644
index 8967cea..0000000
--- a/instance/core/src/main/resources/org/apache/karaf/instance/resources/bin/karaf
+++ /dev/null
@@ -1,25 +0,0 @@
-#!/bin/sh
-################################################################################
-#
-#    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.
-#
-################################################################################
-
-KARAF_HOME=${SUBST-KARAF-HOME}
-KARAF_BASE=${SUBST-KARAF-BASE}
-
-export KARAF_BASE
-exec ${KARAF_HOME}/bin/karaf "$*"

http://git-wip-us.apache.org/repos/asf/karaf/blob/7c2db062/instance/core/src/main/resources/org/apache/karaf/instance/resources/bin/karaf.bat
----------------------------------------------------------------------
diff --git a/instance/core/src/main/resources/org/apache/karaf/instance/resources/bin/karaf.bat b/instance/core/src/main/resources/org/apache/karaf/instance/resources/bin/karaf.bat
deleted file mode 100644
index e054d83..0000000
--- a/instance/core/src/main/resources/org/apache/karaf/instance/resources/bin/karaf.bat
+++ /dev/null
@@ -1,25 +0,0 @@
-@ECHO OFF
-REM =========================================================================
-REM
-REM Licensed to the Apache Software Foundation (ASF) under one or more
-REM contributor license agreements.  See the NOTICE file distributed with
-REM this work for additional information regarding copyright ownership.
-REM The ASF licenses this file to You under the Apache License, Version 2.0
-REM (the "License"); you may not use this file except in compliance with
-REM the License.  You may obtain a copy of the License at
-REM
-REM    http://www.apache.org/licenses/LICENSE-2.0
-REM
-REM Unless required by applicable law or agreed to in writing, software
-REM distributed under the License is distributed on an "AS IS" BASIS,
-REM WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-REM See the License for the specific language governing permissions and
-REM limitations under the License.
-REM
-REM =========================================================================
-
-SETLOCAL
-SET KARAF_HOME=${SUBST-KARAF-HOME}
-SET KARAF_BASE=${SUBST-KARAF-BASE}
-
-"%KARAF_HOME%\bin\karaf.bat" %*

http://git-wip-us.apache.org/repos/asf/karaf/blob/7c2db062/instance/core/src/main/resources/org/apache/karaf/instance/resources/bin/start
----------------------------------------------------------------------
diff --git a/instance/core/src/main/resources/org/apache/karaf/instance/resources/bin/start b/instance/core/src/main/resources/org/apache/karaf/instance/resources/bin/start
deleted file mode 100644
index d45d749..0000000
--- a/instance/core/src/main/resources/org/apache/karaf/instance/resources/bin/start
+++ /dev/null
@@ -1,25 +0,0 @@
-#!/bin/sh
-################################################################################
-#
-#    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.
-#
-################################################################################
-
-KARAF_HOME=${SUBST-KARAF-HOME}
-KARAF_NAME=${SUBST-KARAF-NAME}
-
-exec ${KARAF_HOME}/bin/instance start ${KARAF_NAME} "$@"
-

http://git-wip-us.apache.org/repos/asf/karaf/blob/7c2db062/instance/core/src/main/resources/org/apache/karaf/instance/resources/bin/start.bat
----------------------------------------------------------------------
diff --git a/instance/core/src/main/resources/org/apache/karaf/instance/resources/bin/start.bat b/instance/core/src/main/resources/org/apache/karaf/instance/resources/bin/start.bat
deleted file mode 100644
index 0c530c8..0000000
--- a/instance/core/src/main/resources/org/apache/karaf/instance/resources/bin/start.bat
+++ /dev/null
@@ -1,24 +0,0 @@
-@ECHO OFF
-REM =========================================================================
-REM 
-REM Licensed to the Apache Software Foundation (ASF) under one or more
-REM contributor license agreements.  See the NOTICE file distributed with
-REM this work for additional information regarding copyright ownership.
-REM The ASF licenses this file to You under the Apache License, Version 2.0
-REM (the "License"); you may not use this file except in compliance with
-REM the License.  You may obtain a copy of the License at
-REM 
-REM    http://www.apache.org/licenses/LICENSE-2.0
-REM 
-REM Unless required by applicable law or agreed to in writing, software
-REM distributed under the License is distributed on an "AS IS" BASIS,
-REM WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-REM See the License for the specific language governing permissions and
-REM limitations under the License.
-REM 
-REM =========================================================================
-
-SET KARAF_HOME=${SUBST-KARAF-HOME}
-SET KARAF_NAME=${SUBST-KARAF-NAME}
-
-"%KARAF_HOME%\bin\instance.bat" start %KARAF_NAME%

http://git-wip-us.apache.org/repos/asf/karaf/blob/7c2db062/instance/core/src/main/resources/org/apache/karaf/instance/resources/bin/stop
----------------------------------------------------------------------
diff --git a/instance/core/src/main/resources/org/apache/karaf/instance/resources/bin/stop b/instance/core/src/main/resources/org/apache/karaf/instance/resources/bin/stop
deleted file mode 100644
index fb91985..0000000
--- a/instance/core/src/main/resources/org/apache/karaf/instance/resources/bin/stop
+++ /dev/null
@@ -1,25 +0,0 @@
-#!/bin/sh
-################################################################################
-#
-#    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.
-#
-################################################################################
-
-KARAF_HOME=${SUBST-KARAF-HOME}
-KARAF_NAME=${SUBST-KARAF-NAME}
-
-exec ${KARAF_HOME}/bin/instance stop ${KARAF_NAME} "$@"
-

http://git-wip-us.apache.org/repos/asf/karaf/blob/7c2db062/instance/core/src/main/resources/org/apache/karaf/instance/resources/bin/stop.bat
----------------------------------------------------------------------
diff --git a/instance/core/src/main/resources/org/apache/karaf/instance/resources/bin/stop.bat b/instance/core/src/main/resources/org/apache/karaf/instance/resources/bin/stop.bat
deleted file mode 100644
index 8520acb..0000000
--- a/instance/core/src/main/resources/org/apache/karaf/instance/resources/bin/stop.bat
+++ /dev/null
@@ -1,24 +0,0 @@
-@ECHO OFF
-REM =========================================================================
-REM 
-REM Licensed to the Apache Software Foundation (ASF) under one or more
-REM contributor license agreements.  See the NOTICE file distributed with
-REM this work for additional information regarding copyright ownership.
-REM The ASF licenses this file to You under the Apache License, Version 2.0
-REM (the "License"); you may not use this file except in compliance with
-REM the License.  You may obtain a copy of the License at
-REM 
-REM    http://www.apache.org/licenses/LICENSE-2.0
-REM 
-REM Unless required by applicable law or agreed to in writing, software
-REM distributed under the License is distributed on an "AS IS" BASIS,
-REM WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-REM See the License for the specific language governing permissions and
-REM limitations under the License.
-REM 
-REM =========================================================================
-
-SET KARAF_HOME=${SUBST-KARAF-HOME}
-SET KARAF_NAME=${SUBST-KARAF-NAME}
-
-"%KARAF_HOME%\bin\instance.bat" stop %KARAF_NAME%

http://git-wip-us.apache.org/repos/asf/karaf/blob/7c2db062/instance/core/src/main/resources/org/apache/karaf/instance/resources/etc/org.apache.karaf.management.cfg
----------------------------------------------------------------------
diff --git a/instance/core/src/main/resources/org/apache/karaf/instance/resources/etc/org.apache.karaf.management.cfg b/instance/core/src/main/resources/org/apache/karaf/instance/resources/etc/org.apache.karaf.management.cfg
deleted file mode 100644
index 57b2957..0000000
--- a/instance/core/src/main/resources/org/apache/karaf/instance/resources/etc/org.apache.karaf.management.cfg
+++ /dev/null
@@ -1,63 +0,0 @@
-################################################################################
-#
-#    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.
-#
-################################################################################
-
-#
-# The properties in this file define the configuration of Apache Karaf's JMX Management
-#
-
-#
-# Port number for RMI registry connection
-#
-rmiRegistryPort = ${SUBST-RMI-REGISTRY-PORT}
-
-#
-# Port number for RMI server connection
-#
-rmiServerPort = ${SUBST-RMI-SERVER-PORT}
-
-#
-# Name of the JAAS realm used for authentication
-#
-jmxRealm = karaf
-
-#
-# The service URL for the JMXConnectorServer
-#
-serviceUrl = service:jmx:rmi://0.0.0.0:${rmiServerPort}/jndi/rmi://0.0.0.0:${rmiRegistryPort}/karaf-${karaf.name}
-
-#
-# Whether any threads started for the JMXConnectorServer should be started as daemon threads
-#
-daemon = true
-
-#
-# Whether the JMXConnectorServer should be started in a separate thread
-#
-threaded = true
-
-#
-# The ObjectName used to register the JMXConnectorServer
-#
-objectName = connector:name=rmi
-
-#
-# Role name used for JMX access authorization
-# If not set, this defaults to the ${karaf.admin.role} configured in etc/system.properties
-#
-# jmxRole=admin

http://git-wip-us.apache.org/repos/asf/karaf/blob/7c2db062/instance/core/src/main/resources/org/apache/karaf/instance/resources/etc/org.apache.karaf.shell.cfg
----------------------------------------------------------------------
diff --git a/instance/core/src/main/resources/org/apache/karaf/instance/resources/etc/org.apache.karaf.shell.cfg b/instance/core/src/main/resources/org/apache/karaf/instance/resources/etc/org.apache.karaf.shell.cfg
deleted file mode 100644
index 077f5da..0000000
--- a/instance/core/src/main/resources/org/apache/karaf/instance/resources/etc/org.apache.karaf.shell.cfg
+++ /dev/null
@@ -1,75 +0,0 @@
-################################################################################
-#
-#    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.
-#
-################################################################################
-
-#
-# These properties are used to configure Karaf's ssh shell.
-#
-
-#
-# Via sshPort and sshHost you define the address you can login into Karaf.
-#
-sshPort = ${SUBST-SSH-PORT}
-sshHost = 0.0.0.0
-
-#
-# The sshIdleTimeout defines the inactivity timeout to logout the SSH session.
-# The sshIdleTimeout is in milliseconds, and the default is set to 30 minutes.
-#
-sshIdleTimeout = 1800000
-
-#
-# sshRealm defines which JAAS domain to use for password authentication.
-#
-sshRealm = karaf
-
-#
-# The location of the hostKey file defines where the private/public key of the server
-# is located. If no file is at the defined location it will be ignored.
-#
-hostKey = ${karaf.etc}/host.key
-
-#
-# Role name used for SSH access authorization
-# If not set, this defaults to the ${karaf.admin.role} configured in etc/system.properties
-#
-# sshRole = admin
-
-#
-# Self defined key size in 1024, 2048, 3072, or 4096
-# If not set, this defaults to 1024.
-#
-# keySize = 1024
-
-#
-# Specify host key algorithm, defaults to DSA
-#
-# algorithm = DSA
-
-#
-# Defines the completion mode on the Karaf shell console. The possible values are:
-# - GLOBAL: it's the same behavior as in previous Karaf releases. The completion displays all commands and all aliases
-#           ignoring if you are in a subshell or not.
-# - FIRST: the completion displays all commands and all aliases only when you are not in a subshell. When you are
-#          in a subshell, the completion displays only the commands local to the subshell.
-# - SUBSHELL: the completion displays only the subshells on the root level. When you are in a subshell, the completion
-#             displays only the commands local to the subshell.
-# This property define the default value when you use the Karaf shell console.
-# You can change the completion mode directly in the shell console, using shell:completion command.
-#
-completionMode = GLOBAL
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/karaf/blob/7c2db062/instance/core/src/main/resources/org/apache/karaf/instance/resources/etc/system.properties
----------------------------------------------------------------------
diff --git a/instance/core/src/main/resources/org/apache/karaf/instance/resources/etc/system.properties b/instance/core/src/main/resources/org/apache/karaf/instance/resources/etc/system.properties
deleted file mode 100644
index a683a34..0000000
--- a/instance/core/src/main/resources/org/apache/karaf/instance/resources/etc/system.properties
+++ /dev/null
@@ -1,120 +0,0 @@
-################################################################################
-#
-#    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.
-#
-################################################################################
-
-#
-# The properties defined in this file will be made available through system
-# properties at the very beginning of the Karaf's boot process.
-#
-
-
-# Log level when the pax-logging service is not available
-# This level will only be used while the pax-logging service bundle
-# is not fully available.
-# To change log levels, please refer to the org.ops4j.pax.logging.cfg file
-# instead.
-org.ops4j.pax.logging.DefaultServiceLog.level = ERROR
-
-#
-# Name of this Karaf instance.
-#
-karaf.name = ${SUBST-KARAF-NAME}
-
-#
-# Default repository where bundles will be loaded from before using
-# other Maven repositories.  For the full Maven configuration, see
-# the org.ops4j.pax.url.mvn.cfg file.
-#
-karaf.default.repository = system
-
-#
-# Location of a shell script that will be run when starting a shell
-# session.  This script can be used to create aliases and define
-# additional commands.
-#
-karaf.shell.init.script = ${karaf.etc}/shell.init.script
-
-#
-# Sets the maximum size of the shell command history. If not set,
-# defaults to 500 entries. Setting to 0 will disable history.
-#
-# karaf.shell.history.maxSize = 0
-
-#
-# Deletes the entire karaf.data directory at every start
-#
-karaf.clean.all = false
-
-#
-# Deletes the karaf.data/cache directory at every start
-#
-karaf.clean.cache = false
-
-#
-# Roles to use when logging into a local Karaf console.
-#
-# The syntax is the following:
-#   [classname:]principal
-# where classname is the class name of the principal object
-# (defaults to org.apache.karaf.jaas.modules.RolePrincipal)
-# and principal is the name of the principal of that class
-# (defaults to instance).
-#
-karaf.local.roles = admin,manager,viewer
-
-#
-# Set this empty property to avoid errors when validating xml documents.
-#
-xml.catalog.files =
-
-#
-# Suppress the bell in the console when hitting backspace too many times
-# for example
-#
-jline.nobell = true
-
-#
-# ServiceMix specs options
-#
-org.apache.servicemix.specs.debug = false
-org.apache.servicemix.specs.timeout = 100
-
-#
-# Settings for the OSGi 4.3 Weaving
-# By default, we will not weave any classes. Change this setting to include classes
-# that you application needs to have woven.
-#
-org.apache.aries.proxy.weaving.enabled = none
-# Classes not to weave - Aries default + Xerces which is known to have issues.
-org.apache.aries.proxy.weaving.disabled = org.objectweb.asm.*,org.slf4j.*,org.apache.log4j.*,javax.*,org.apache.xerces.*
-
-#
-# By default, only Karaf shell commands are secured, but additional services can be
-# secured by expanding this filter
-#
-karaf.secured.services = (&(osgi.command.scope=*)(osgi.command.function=*))
-
-#
-# Security properties
-#
-# To enable OSGi security, uncomment the properties below,
-# install the framework-security feature and restart.
-#
-#java.security.policy=${karaf.etc}/all.policy
-#org.osgi.framework.security=osgi
-#org.osgi.framework.trust.repositories=${karaf.etc}/trustStore.ks

http://git-wip-us.apache.org/repos/asf/karaf/blob/7c2db062/instance/core/src/main/resources/org/apache/karaf/jpm/impl/unix/start.sh
----------------------------------------------------------------------
diff --git a/instance/core/src/main/resources/org/apache/karaf/jpm/impl/unix/start.sh b/instance/core/src/main/resources/org/apache/karaf/jpm/impl/unix/start.sh
deleted file mode 100644
index 1d1d720..0000000
--- a/instance/core/src/main/resources/org/apache/karaf/jpm/impl/unix/start.sh
+++ /dev/null
@@ -1,29 +0,0 @@
-#!/bin/sh
-################################################################################
-#
-#    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.
-#
-################################################################################
-
-#exec 1>${out.file}
-#exec 2>${err.file}
-exec 1>/dev/null
-exec 2>/dev/null
-if [ "x${dir}" != "x" ]; then
-    cd ${dir}
-fi
-nohup ${command} &
-echo $! > ${pid.file}

http://git-wip-us.apache.org/repos/asf/karaf/blob/7c2db062/instance/core/src/main/resources/org/apache/karaf/jpm/impl/windows/destroy.vbs
----------------------------------------------------------------------
diff --git a/instance/core/src/main/resources/org/apache/karaf/jpm/impl/windows/destroy.vbs b/instance/core/src/main/resources/org/apache/karaf/jpm/impl/windows/destroy.vbs
deleted file mode 100644
index abd60eb..0000000
--- a/instance/core/src/main/resources/org/apache/karaf/jpm/impl/windows/destroy.vbs
+++ /dev/null
@@ -1,27 +0,0 @@
-'===============================================================================
-'
-'    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.
-'
-'===============================================================================
-
-Set objWMIService = GetObject("winmgmts:\\.\root\cimv2")
-Set colProcessList = objWMIService.ExecQuery("Select * from Win32_Process Where ProcessId = ${pid}")
-intRetVal = 1
-For Each objProcess in colProcessList
-    objProcess.Terminate()
-    intRetVal = 0
-Next
-WScript.Quit(intRetVal)

http://git-wip-us.apache.org/repos/asf/karaf/blob/7c2db062/instance/core/src/main/resources/org/apache/karaf/jpm/impl/windows/running.vbs
----------------------------------------------------------------------
diff --git a/instance/core/src/main/resources/org/apache/karaf/jpm/impl/windows/running.vbs b/instance/core/src/main/resources/org/apache/karaf/jpm/impl/windows/running.vbs
deleted file mode 100644
index 32c65c5..0000000
--- a/instance/core/src/main/resources/org/apache/karaf/jpm/impl/windows/running.vbs
+++ /dev/null
@@ -1,26 +0,0 @@
-'===============================================================================
-'
-'    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.
-'
-'===============================================================================
-
-Set objWMIService = GetObject("winmgmts:\\.\root\cimv2")
-Set colProcessList = objWMIService.ExecQuery("Select * from Win32_Process Where ProcessId = ${pid}")
-intRetVal = 1
-For Each objProcess in colProcessList
-    intRetVal = 0
-Next
-WScript.Quit(intRetVal)

http://git-wip-us.apache.org/repos/asf/karaf/blob/7c2db062/instance/core/src/main/resources/org/apache/karaf/jpm/impl/windows/start.vbs
----------------------------------------------------------------------
diff --git a/instance/core/src/main/resources/org/apache/karaf/jpm/impl/windows/start.vbs b/instance/core/src/main/resources/org/apache/karaf/jpm/impl/windows/start.vbs
deleted file mode 100644
index 6004c86..0000000
--- a/instance/core/src/main/resources/org/apache/karaf/jpm/impl/windows/start.vbs
+++ /dev/null
@@ -1,34 +0,0 @@
-'===============================================================================
-'
-'    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.
-'
-'===============================================================================
-
-Set objWMIService = GetObject("winmgmts:\\.\root\cimv2")
-Set objConfig = objWMIService.Get("Win32_ProcessStartup").SpawnInstance_
-objConfig.ShowWindow = SW_HIDE
-objConfig.CreateFlags = 8
-If Len("${dir}") > 0 Then
-    intReturn = objWMIService.Get("Win32_Process").Create("${command}", "${dir}", objConfig, intProcessID)
-Else
-    intReturn = objWMIService.Get("Win32_Process").Create("${command}", Null, objConfig, intProcessID)
-End If
-If intReturn = 0 Then
-    Set objOutputFile = CreateObject("Scripting.fileSystemObject").CreateTextFile("${pid.file}", TRUE)
-    objOutputFile.WriteLine(intProcessID)
-    objOutputFile.Close
-End If
-WScript.Quit(intReturn)

http://git-wip-us.apache.org/repos/asf/karaf/blob/7c2db062/instance/core/src/test/java/org/apache/karaf/instance/core/InstanceSettingsTest.java
----------------------------------------------------------------------
diff --git a/instance/core/src/test/java/org/apache/karaf/instance/core/InstanceSettingsTest.java b/instance/core/src/test/java/org/apache/karaf/instance/core/InstanceSettingsTest.java
deleted file mode 100644
index 264176b..0000000
--- a/instance/core/src/test/java/org/apache/karaf/instance/core/InstanceSettingsTest.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * 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.karaf.instance.core;
-
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-
-import junit.framework.TestCase;
-
-import org.apache.karaf.instance.core.InstanceSettings;
-import org.junit.Assert;
-
-public class InstanceSettingsTest extends TestCase {
-    public void testInstanceSettings() {
-        InstanceSettings is =
-            new InstanceSettings(1, 1, 1, null, null, Collections.<String>emptyList(), Arrays.asList("hi"));
-        assertEquals(1, is.getSshPort());
-        assertEquals(1, is.getRmiRegistryPort());
-        assertEquals(1, is.getRmiServerPort());
-        Assert.assertNull(is.getLocation());
-        assertEquals(Arrays.asList("hi"), is.getFeatures());
-        assertEquals(0, is.getFeatureURLs().size());
-    }
-    
-    public void testEqualsHashCode() {
-        testEqualsHashCode(1, 1, 1, "top", "foo", Collections.<String>emptyList(), Arrays.asList("hi"));
-        testEqualsHashCode(0, 0, 0, null, null, null, null);
-    }
-
-    private void testEqualsHashCode(int sshPort, int rmiRegistryPort, int rmiServerPort, String location, String javaOpts, List<String> featureURLs, List<String> features) {
-        InstanceSettings is = new InstanceSettings(sshPort, rmiRegistryPort, rmiServerPort, location, javaOpts, featureURLs, features);
-        InstanceSettings is2 = new InstanceSettings(sshPort, rmiRegistryPort, rmiServerPort, location, javaOpts, featureURLs, features);
-        assertEquals(is, is2);
-        assertEquals(is.hashCode(), is2.hashCode());
-    }
-    
-    public void testEqualsHashCode2() {
-        InstanceSettings is = new InstanceSettings(1, 1, 1, "top", "foo", Collections.<String>emptyList(), Arrays.asList("hi"));
-        Assert.assertFalse(is.equals(null));
-        Assert.assertFalse(is.equals(new Object()));
-        assertEquals(is, is);
-    }
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/7c2db062/instance/core/src/test/java/org/apache/karaf/instance/core/internal/InstanceServiceImplTest.java
----------------------------------------------------------------------
diff --git a/instance/core/src/test/java/org/apache/karaf/instance/core/internal/InstanceServiceImplTest.java b/instance/core/src/test/java/org/apache/karaf/instance/core/internal/InstanceServiceImplTest.java
deleted file mode 100644
index 9c77934..0000000
--- a/instance/core/src/test/java/org/apache/karaf/instance/core/internal/InstanceServiceImplTest.java
+++ /dev/null
@@ -1,187 +0,0 @@
-/*
- * 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.karaf.instance.core.internal;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.util.Arrays;
-import java.util.Properties;
-
-import org.apache.karaf.instance.core.Instance;
-import org.apache.karaf.instance.core.InstanceSettings;
-import org.junit.BeforeClass;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.TemporaryFolder;
-import org.junit.rules.TestName;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-
-public class InstanceServiceImplTest {
-
-    @Rule
-    public TestName name = new TestName();
-
-    @Rule
-    public TemporaryFolder tempFolder = new TemporaryFolder();
-
-    @BeforeClass
-    public static void setUpClass() throws Exception {
-        String buildDirectory = ClassLoader.getSystemResource("etc/startup.properties").getFile()
-                .replace("startup.properties", "");
-        System.setProperty("karaf.etc", buildDirectory);
-    }
-
-    @Test
-    public void testHandleFeatures() throws Exception {
-        InstanceServiceImpl as = new InstanceServiceImpl();
-
-        File f = tempFolder.newFile(getName() + ".test");
-        Properties p = new Properties();
-        p.put("featuresBoot", "abc,def ");
-        p.put("featuresRepositories", "somescheme://xyz");
-        OutputStream os = new FileOutputStream(f);
-        try {
-            p.store(os, "Test comment");
-        } finally {
-            os.close();
-        }
-
-        InstanceSettings s = new InstanceSettings(8122, 1122, 44444, null, null, null, Arrays.asList("test"));
-        as.addFeaturesFromSettings(f, s);
-
-        Properties p2 = new Properties();
-        InputStream is = new FileInputStream(f);
-        try {
-            p2.load(is);
-        } finally {
-            is.close();
-        }
-        assertEquals(2, p2.size());
-        assertEquals("abc,def,test", p2.get("featuresBoot"));
-        assertEquals("somescheme://xyz", p2.get("featuresRepositories"));
-    }
-
-    @Test
-    public void testConfigurationFiles() throws Exception {
-        InstanceServiceImpl service = new InstanceServiceImpl();
-        service.setStorageLocation(tempFolder.newFolder("instances"));
-
-        InstanceSettings settings = new InstanceSettings(8122, 1122, 44444, getName(), null, null, null);
-        Instance instance = service.createInstance(getName(), settings, true);
-
-        assertFileExists(instance.getLocation(), "etc/config.properties");
-        assertFileExists(instance.getLocation(), "etc/users.properties");
-        assertFileExists(instance.getLocation(), "etc/startup.properties");
-
-        assertFileExists(instance.getLocation(), "etc/java.util.logging.properties");
-        assertFileExists(instance.getLocation(), "etc/org.apache.karaf.features.cfg");
-        assertFileExists(instance.getLocation(), "etc/org.apache.felix.fileinstall-deploy.cfg");
-        assertFileExists(instance.getLocation(), "etc/org.apache.karaf.log.cfg");
-        assertFileExists(instance.getLocation(), "etc/org.apache.karaf.management.cfg");
-        assertFileExists(instance.getLocation(), "etc/org.ops4j.pax.logging.cfg");
-        assertFileExists(instance.getLocation(), "etc/org.ops4j.pax.url.mvn.cfg");
-    }
-
-    /**
-     * <p>
-     * Test the renaming of an existing instance.
-     * </p>
-     */
-    @Test
-    public void testRenameInstance() throws Exception {
-        InstanceServiceImpl service = new InstanceServiceImpl();
-        service.setStorageLocation(tempFolder.newFolder("instances"));
-
-        InstanceSettings settings = new InstanceSettings(8122, 1122, 44444, getName(), null, null, null);
-        service.createInstance(getName(), settings, true);
-
-        service.renameInstance(getName(), getName() + "b", true);
-        assertNotNull(service.getInstance(getName() + "b"));
-    }
-
-    /**
-     * <p>
-     * Test the renaming of an existing instance.
-     * </p>
-     */
-    @Test
-    public void testToSimulateRenameInstanceByExternalProcess() throws Exception {
-        InstanceServiceImpl service = new InstanceServiceImpl();
-        File storageLocation = tempFolder.newFolder("instances");
-        service.setStorageLocation(storageLocation);
-
-        InstanceSettings settings = new InstanceSettings(8122, 1122, 44444, getName(), null, null, null);
-        service.createInstance(getName(), settings, true);
-        
-        //to simulate the scenario that the instance name get changed by 
-        //external process, likely the admin command CLI tool, which cause
-        //the instance storage file get updated, the AdminService should be 
-        //able to reload the storage file before check any status for the 
-        //instance
-        
-        File storageFile = new File(storageLocation, InstanceServiceImpl.STORAGE_FILE);
-        assertTrue(storageFile.isFile());
-        Properties storage = loadStorage(storageFile);
-        storage.setProperty("item.0.name", getName() + "b");
-        saveStorage(storage, storageFile, "testToSimulateRenameInstanceByExternalProcess");
-        
-        assertNotNull(service.getInstance(getName() + "b"));
-    }
-
-    private String getName() {
-        return name.getMethodName();
-    }
-
-    private void saveStorage(Properties props, File location, String comment) throws IOException {
-        OutputStream os = null;
-        try {
-            os = new FileOutputStream(location);
-            props.store(os, comment);
-        } finally {
-            if (os != null) {
-                os.close();
-            }
-        }
-    }
-    
-    private Properties loadStorage(File location) throws IOException {
-        InputStream is = null;
-        try {
-            is = new FileInputStream(location);
-            Properties props = new Properties();
-            props.load(is);
-            return props;
-        } finally {
-            if (is != null) {
-                is.close();
-            }
-        }
-    }
-
-    private void assertFileExists(String path, String name) throws IOException {
-        File file = new File(path, name);
-        assertTrue("Expected " + file.getCanonicalPath() + " to exist",
-                   file.exists());
-    }   
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/7c2db062/instance/core/src/test/java/org/apache/karaf/instance/core/management/internal/InstanceServiceMBeanImplTest.java
----------------------------------------------------------------------
diff --git a/instance/core/src/test/java/org/apache/karaf/instance/core/management/internal/InstanceServiceMBeanImplTest.java b/instance/core/src/test/java/org/apache/karaf/instance/core/management/internal/InstanceServiceMBeanImplTest.java
deleted file mode 100644
index bb67041..0000000
--- a/instance/core/src/test/java/org/apache/karaf/instance/core/management/internal/InstanceServiceMBeanImplTest.java
+++ /dev/null
@@ -1,239 +0,0 @@
-/*
- * 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.karaf.instance.core.management.internal;
-
-import java.util.Arrays;
-import java.util.Collections;
-
-import javax.management.openmbean.CompositeData;
-import javax.management.openmbean.TabularData;
-
-import junit.framework.TestCase;
-
-import org.apache.karaf.instance.core.Instance;
-import org.apache.karaf.instance.core.InstanceService;
-import org.apache.karaf.instance.core.InstanceSettings;
-import org.apache.karaf.instance.core.InstancesMBean;
-import org.apache.karaf.instance.core.internal.InstancesMBeanImpl;
-import org.easymock.EasyMock;
-import org.junit.Assert;
-
-public class InstanceServiceMBeanImplTest extends TestCase {
-
-    public void testCreateInstance() throws Exception {
-        final InstanceSettings instanceSettings = new InstanceSettings(123, 456,789, "somewhere", "someopts",
-                Collections.<String>emptyList(), Arrays.asList("webconsole", "funfeat"));
-        
-        final Instance inst = EasyMock.createMock(Instance.class);
-        EasyMock.expect(inst.getPid()).andReturn(42);
-        EasyMock.replay(inst);
-
-        org.apache.karaf.instance.core.InstanceService instanceService = EasyMock.createMock(org.apache.karaf.instance.core.InstanceService.class);
-        EasyMock.expect(instanceService.createInstance("t1", instanceSettings, false)).andReturn(inst);
-        EasyMock.replay(instanceService);
-        
-        InstancesMBeanImpl ab = new InstancesMBeanImpl(instanceService);
-        assertEquals(42, ab.createInstance("t1", 123, 456, 789, "somewhere", "someopts", " webconsole,  funfeat", ""));
-    }
-    
-    public void testCreateInstance2() throws Exception {
-        final InstanceSettings instanceSettings = new InstanceSettings(0, 0, 0, null, null,
-                Collections.<String>emptyList(), Collections.<String>emptyList());
-        
-        InstanceService instanceService = EasyMock.createMock(InstanceService.class);
-        EasyMock.expect(instanceService.createInstance("t1", instanceSettings, false)).andReturn(null);
-        EasyMock.replay(instanceService);
-        
-        InstancesMBean ab = new InstancesMBeanImpl(instanceService);
-        assertEquals(-1, ab.createInstance("t1", 0, 0, 0, "", "", "", ""));
-    }
-    
-    public void testGetInstances() throws Exception {       
-        Instance i1 = EasyMock.createMock(Instance.class);
-        EasyMock.expect(i1.getPid()).andReturn(1234);
-        EasyMock.expect(i1.getSshPort()).andReturn(8818);
-        EasyMock.expect(i1.getRmiRegistryPort()).andReturn(1122);
-        EasyMock.expect(i1.getRmiServerPort()).andReturn(44444);
-        EasyMock.expect(i1.getName()).andReturn("i1");
-        EasyMock.expect(i1.isRoot()).andReturn(true);
-        EasyMock.expect(i1.getLocation()).andReturn("somewhere");
-        EasyMock.expect(i1.getJavaOpts()).andReturn("someopts");
-        EasyMock.expect(i1.getState()).andReturn("Stopped");
-        EasyMock.replay(i1);
-        Instance i2 = EasyMock.createNiceMock(Instance.class);
-        EasyMock.expect(i2.getName()).andReturn("i2");
-        EasyMock.replay(i2);
-        
-        InstanceService instanceService = EasyMock.createMock(InstanceService.class);
-        EasyMock.expect(instanceService.getInstances()).andReturn(new Instance[]{i1, i2});
-        EasyMock.replay(instanceService);
-
-        InstancesMBeanImpl instanceServiceMBean = new InstancesMBeanImpl(instanceService);
-        TabularData tabularData = instanceServiceMBean.getInstances();
-        Assert.assertEquals(2, tabularData.size());
-        CompositeData cd1 = tabularData.get(new Object[]{"i1"});
-        Assert.assertTrue(cd1.containsValue("i1"));
-        Assert.assertTrue(cd1.containsValue(true));
-        Assert.assertTrue(cd1.containsValue(1234));
-        Assert.assertTrue(cd1.containsValue(8818));
-        Assert.assertTrue(cd1.containsValue(1122));
-        Assert.assertTrue(cd1.containsValue(44444));
-        Assert.assertTrue(cd1.containsValue("somewhere"));
-        Assert.assertTrue(cd1.containsValue("someopts"));
-        Assert.assertTrue(cd1.containsValue("Stopped"));
-
-        CompositeData cd2 = tabularData.get(new Object [] {"i2"});
-        Assert.assertTrue(cd2.containsValue("i2"));
-    }
-    
-    public void testStartInstanceWithJavaOpts() throws Exception {
-        Instance inst = EasyMock.createMock(Instance.class);
-        inst.start("-x -y -z");
-        EasyMock.expectLastCall();
-        EasyMock.replay(inst);
-
-        InstanceService instanceService = EasyMock.createMock(InstanceService.class);
-        EasyMock.expect(instanceService.getInstance("test instance")).andReturn(inst);
-        EasyMock.replay(instanceService);
-
-        InstancesMBean instanceServiceMBean = new InstancesMBeanImpl(instanceService);
-
-        instanceServiceMBean.startInstance("test instance", "-x -y -z");
-        EasyMock.verify(instanceService);
-        EasyMock.verify(inst);
-    }
-
-    public void testStartInstanceWithNoJavaOpts() throws Exception {
-        Instance inst = EasyMock.createMock(Instance.class);
-        inst.start(null);
-        EasyMock.expectLastCall();
-        EasyMock.replay(inst);
-
-        InstanceService instanceService = EasyMock.createMock(InstanceService.class);
-        EasyMock.expect(instanceService.getInstance("test instance")).andReturn(inst);
-        EasyMock.replay(instanceService);
-
-        InstancesMBean instanceServiceMBean = new InstancesMBeanImpl(instanceService);
-
-        instanceServiceMBean.startInstance("test instance", null);
-        EasyMock.verify(instanceService);
-        EasyMock.verify(inst);
-    }
-
-    public void testStopInstance() throws Exception {
-        Instance inst = EasyMock.createMock(Instance.class);
-        inst.stop();
-        EasyMock.expectLastCall();
-        EasyMock.replay(inst);
-
-        InstanceService instanceService = EasyMock.createMock(InstanceService.class);
-        EasyMock.expect(instanceService.getInstance("test instance")).andReturn(inst);
-        EasyMock.replay(instanceService);
-        
-        InstancesMBean instanceServiceMBean = new InstancesMBeanImpl(instanceService);
-
-        instanceServiceMBean.stopInstance("test instance");
-        EasyMock.verify(instanceService);
-        EasyMock.verify(inst);
-    }
-
-    public void testDestroyInstance() throws Exception {
-        Instance inst = EasyMock.createMock(Instance.class);
-        inst.destroy();
-        EasyMock.expectLastCall();
-        EasyMock.replay(inst);
-
-        InstanceService instanceService = EasyMock.createMock(InstanceService.class);
-        EasyMock.expect(instanceService.getInstance("test instance")).andReturn(inst);
-        EasyMock.replay(instanceService);
-        
-        InstancesMBean instanceServiceMBean = new InstancesMBeanImpl(instanceService);
-
-        instanceServiceMBean.destroyInstance("test instance");
-        EasyMock.verify(instanceService);
-        EasyMock.verify(inst);
-    }
-
-    public void testSshChangePort() throws Exception {
-        Instance inst = EasyMock.createMock(Instance.class);
-        inst.changeSshPort(7788);
-        EasyMock.expectLastCall();
-        EasyMock.replay(inst);
-
-        InstanceService instanceService = EasyMock.createMock(InstanceService.class);
-        EasyMock.expect(instanceService.getInstance("test instance")).andReturn(inst);
-        EasyMock.replay(instanceService);
-        
-        InstancesMBean instanceServiceMBean = new InstancesMBeanImpl(instanceService);
-
-        instanceServiceMBean.changeSshPort("test instance", 7788);
-        EasyMock.verify(instanceService);
-        EasyMock.verify(inst);
-    }
-    
-    public void testRmiRegistryChangePort() throws Exception {
-        Instance inst = EasyMock.createMock(Instance.class);
-        inst.changeRmiRegistryPort(1123);
-        EasyMock.expectLastCall();
-        EasyMock.replay(inst);
-        
-        InstanceService instanceService = EasyMock.createMock(InstanceService.class);
-        EasyMock.expect(instanceService.getInstance("test instance")).andReturn(inst);
-        EasyMock.replay(instanceService);
-        
-        InstancesMBean instanceServiceMBean = new InstancesMBeanImpl(instanceService);
-        
-        instanceServiceMBean.changeRmiRegistryPort("test instance", 1123);
-        EasyMock.verify(instanceService);
-        EasyMock.verify(inst);
-    }
-
-    public void testRmiServerChangePort() throws Exception {
-        Instance inst = EasyMock.createMock(Instance.class);
-        inst.changeRmiServerPort(44444);
-        EasyMock.expectLastCall();
-        EasyMock.replay(inst);
-
-        InstanceService instanceService = EasyMock.createMock(InstanceService.class);
-        EasyMock.expect(instanceService.getInstance("test instance")).andReturn(inst);
-        EasyMock.replay(instanceService);
-
-        InstancesMBean instanceServiceMBean = new InstancesMBeanImpl(instanceService);
-
-        instanceServiceMBean.changeRmiServerPort("test instance", 44444);
-        EasyMock.verify(instanceService);
-        EasyMock.verify(inst);
-    }
-
-    public void testChangeOptions() throws Exception {
-        Instance inst = EasyMock.createMock(Instance.class);
-        inst.changeJavaOpts("new opts");
-        EasyMock.expectLastCall();
-        EasyMock.replay(inst);
-
-        InstanceService instanceService = EasyMock.createMock(InstanceService.class);
-        EasyMock.expect(instanceService.getInstance("test instance")).andReturn(inst);
-        EasyMock.replay(instanceService);
-
-        InstancesMBean instanceServiceMBean = new InstancesMBeanImpl(instanceService);
-
-        instanceServiceMBean.changeJavaOpts("test instance", "new opts");
-        EasyMock.verify(instanceService);
-        EasyMock.verify(inst);
-    }
-
-}


[49/59] [abbrv] git commit: [KARAF-2852] Merge wrapper/core and wrapper/command

Posted by gn...@apache.org.
[KARAF-2852] Merge wrapper/core and wrapper/command


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

Branch: refs/heads/master
Commit: 4182735c7979c461b5be733cbe9db06b0d83239b
Parents: b0a20b8
Author: Guillaume Nodet <gn...@gmail.com>
Authored: Thu Apr 10 09:31:03 2014 +0200
Committer: Guillaume Nodet <gn...@gmail.com>
Committed: Thu Apr 10 16:02:49 2014 +0200

----------------------------------------------------------------------
 .../standard/src/main/feature/feature.xml       |   1 -
 wrapper/NOTICE                                  |  71 +++
 wrapper/command/NOTICE                          |  71 ---
 wrapper/command/pom.xml                         | 100 ----
 .../apache/karaf/wrapper/commands/Install.java  | 199 -------
 .../services/org/apache/karaf/shell/commands    |  18 -
 .../src/main/resources/OSGI-INF/bundle.info     |  19 -
 wrapper/core/NOTICE                             |  71 ---
 wrapper/core/pom.xml                            | 128 -----
 .../apache/karaf/wrapper/WrapperService.java    |  42 --
 .../org/apache/karaf/wrapper/internal/Main.java | 146 -----
 .../wrapper/internal/PumpStreamHandler.java     | 246 --------
 .../karaf/wrapper/internal/StreamPumper.java    | 195 -------
 .../wrapper/internal/WrapperServiceImpl.java    | 450 ---------------
 .../karaf/wrapper/internal/osgi/Activator.java  |  36 --
 .../karaf/wrapper/management/WrapperMBean.java  |  46 --
 .../management/internal/WrapperMBeanImpl.java   |  62 ---
 .../src/main/resources/OSGI-INF/bundle.info     |  16 -
 .../wrapper/internal/aix/ppc32/karaf-wrapper    | Bin 281540 -> 0 bytes
 .../wrapper/internal/aix/ppc32/libwrapper.a     | Bin 22948 -> 0 bytes
 .../wrapper/internal/aix/ppc64/karaf-wrapper    | Bin 319397 -> 0 bytes
 .../wrapper/internal/aix/ppc64/libwrapper.a     | Bin 24499 -> 0 bytes
 .../wrapper/internal/all/karaf-wrapper.jar      | Bin 83820 -> 0 bytes
 .../internal/hpux/parisc64/karaf-wrapper        | Bin 253808 -> 0 bytes
 .../internal/hpux/parisc64/libwrapper.sl        | Bin 74520 -> 0 bytes
 .../karaf/wrapper/internal/linux/karaf-wrapper  | Bin 99401 -> 0 bytes
 .../karaf/wrapper/internal/linux/libwrapper.so  | Bin 11887 -> 0 bytes
 .../wrapper/internal/linux64/karaf-wrapper      | Bin 111027 -> 0 bytes
 .../wrapper/internal/linux64/libwrapper.so      | Bin 15248 -> 0 bytes
 .../karaf/wrapper/internal/macosx/karaf-wrapper | Bin 378976 -> 0 bytes
 .../wrapper/internal/macosx/libwrapper.jnilib   | Bin 43840 -> 0 bytes
 .../macosx/org.apache.karaf.KARAF.plist         |  36 --
 .../internal/solaris/sparc32/karaf-wrapper      | Bin 112536 -> 0 bytes
 .../internal/solaris/sparc32/libwrapper.so      | Bin 13760 -> 0 bytes
 .../internal/solaris/sparc64/karaf-wrapper      | Bin 148512 -> 0 bytes
 .../internal/solaris/sparc64/libwrapper.so      | Bin 21032 -> 0 bytes
 .../wrapper/internal/solaris/x86/karaf-wrapper  | Bin 110992 -> 0 bytes
 .../wrapper/internal/solaris/x86/libwrapper.so  | Bin 12572 -> 0 bytes
 .../internal/solaris/x86_64/karaf-wrapper       | Bin 160000 -> 0 bytes
 .../internal/solaris/x86_64/libwrapper.so       | Bin 19072 -> 0 bytes
 .../karaf/wrapper/internal/unix/karaf-service   | 557 -------------------
 .../wrapper/internal/unix/karaf-wrapper.conf    | 135 -----
 .../wrapper/internal/windows/karaf-service.bat  |  51 --
 .../wrapper/internal/windows/karaf-wrapper.conf | 135 -----
 .../wrapper/internal/windows/karaf-wrapper.exe  | Bin 204800 -> 0 bytes
 .../karaf/wrapper/internal/windows/wrapper.dll  | Bin 81920 -> 0 bytes
 .../internal/windows64/karaf-service.bat        |  51 --
 .../internal/windows64/karaf-wrapper.conf       | 135 -----
 .../internal/windows64/karaf-wrapper.exe        | Bin 220672 -> 0 bytes
 .../wrapper/internal/windows64/wrapper.dll      | Bin 76800 -> 0 bytes
 wrapper/pom.xml                                 | 110 +++-
 .../apache/karaf/wrapper/WrapperService.java    |  42 ++
 .../apache/karaf/wrapper/commands/Install.java  | 199 +++++++
 .../org/apache/karaf/wrapper/internal/Main.java | 146 +++++
 .../wrapper/internal/PumpStreamHandler.java     | 246 ++++++++
 .../karaf/wrapper/internal/StreamPumper.java    | 195 +++++++
 .../wrapper/internal/WrapperServiceImpl.java    | 450 +++++++++++++++
 .../karaf/wrapper/internal/osgi/Activator.java  |  36 ++
 .../karaf/wrapper/management/WrapperMBean.java  |  46 ++
 .../management/internal/WrapperMBeanImpl.java   |  62 +++
 .../services/org/apache/karaf/shell/commands    |  18 +
 wrapper/src/main/resources/OSGI-INF/bundle.info |  16 +
 .../wrapper/internal/aix/ppc32/karaf-wrapper    | Bin 0 -> 281540 bytes
 .../wrapper/internal/aix/ppc32/libwrapper.a     | Bin 0 -> 22948 bytes
 .../wrapper/internal/aix/ppc64/karaf-wrapper    | Bin 0 -> 319397 bytes
 .../wrapper/internal/aix/ppc64/libwrapper.a     | Bin 0 -> 24499 bytes
 .../wrapper/internal/all/karaf-wrapper.jar      | Bin 0 -> 83820 bytes
 .../internal/hpux/parisc64/karaf-wrapper        | Bin 0 -> 253808 bytes
 .../internal/hpux/parisc64/libwrapper.sl        | Bin 0 -> 74520 bytes
 .../karaf/wrapper/internal/linux/karaf-wrapper  | Bin 0 -> 99401 bytes
 .../karaf/wrapper/internal/linux/libwrapper.so  | Bin 0 -> 11887 bytes
 .../wrapper/internal/linux64/karaf-wrapper      | Bin 0 -> 111027 bytes
 .../wrapper/internal/linux64/libwrapper.so      | Bin 0 -> 15248 bytes
 .../karaf/wrapper/internal/macosx/karaf-wrapper | Bin 0 -> 378976 bytes
 .../wrapper/internal/macosx/libwrapper.jnilib   | Bin 0 -> 43840 bytes
 .../macosx/org.apache.karaf.KARAF.plist         |  36 ++
 .../internal/solaris/sparc32/karaf-wrapper      | Bin 0 -> 112536 bytes
 .../internal/solaris/sparc32/libwrapper.so      | Bin 0 -> 13760 bytes
 .../internal/solaris/sparc64/karaf-wrapper      | Bin 0 -> 148512 bytes
 .../internal/solaris/sparc64/libwrapper.so      | Bin 0 -> 21032 bytes
 .../wrapper/internal/solaris/x86/karaf-wrapper  | Bin 0 -> 110992 bytes
 .../wrapper/internal/solaris/x86/libwrapper.so  | Bin 0 -> 12572 bytes
 .../internal/solaris/x86_64/karaf-wrapper       | Bin 0 -> 160000 bytes
 .../internal/solaris/x86_64/libwrapper.so       | Bin 0 -> 19072 bytes
 .../karaf/wrapper/internal/unix/karaf-service   | 557 +++++++++++++++++++
 .../wrapper/internal/unix/karaf-wrapper.conf    | 135 +++++
 .../wrapper/internal/windows/karaf-service.bat  |  51 ++
 .../wrapper/internal/windows/karaf-wrapper.conf | 135 +++++
 .../wrapper/internal/windows/karaf-wrapper.exe  | Bin 0 -> 204800 bytes
 .../karaf/wrapper/internal/windows/wrapper.dll  | Bin 0 -> 81920 bytes
 .../internal/windows64/karaf-service.bat        |  51 ++
 .../internal/windows64/karaf-wrapper.conf       | 135 +++++
 .../internal/windows64/karaf-wrapper.exe        | Bin 0 -> 220672 bytes
 .../wrapper/internal/windows64/wrapper.dll      | Bin 0 -> 76800 bytes
 94 files changed, 2728 insertions(+), 2955 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/karaf/blob/4182735c/assemblies/features/standard/src/main/feature/feature.xml
----------------------------------------------------------------------
diff --git a/assemblies/features/standard/src/main/feature/feature.xml b/assemblies/features/standard/src/main/feature/feature.xml
index e596a84..6813d27 100644
--- a/assemblies/features/standard/src/main/feature/feature.xml
+++ b/assemblies/features/standard/src/main/feature/feature.xml
@@ -103,7 +103,6 @@
 
     <feature name="wrapper" description="Provide OS integration" version="${project.version}">
         <bundle start-level="30">mvn:org.apache.karaf.wrapper/org.apache.karaf.wrapper.core/${project.version}</bundle>
-        <bundle start-level="30">mvn:org.apache.karaf.wrapper/org.apache.karaf.wrapper.command/${project.version}</bundle>
     </feature>
     <feature name="service-wrapper" description="Provide OS integration (alias to wrapper feature)" version="${project.version}">
         <feature>wrapper</feature>

http://git-wip-us.apache.org/repos/asf/karaf/blob/4182735c/wrapper/NOTICE
----------------------------------------------------------------------
diff --git a/wrapper/NOTICE b/wrapper/NOTICE
new file mode 100644
index 0000000..b70f1f9
--- /dev/null
+++ b/wrapper/NOTICE
@@ -0,0 +1,71 @@
+Apache Karaf
+Copyright 2010-2014 The Apache Software Foundation
+
+
+I. Included Software
+
+This product includes software developed at
+The Apache Software Foundation (http://www.apache.org/).
+Licensed under the Apache License 2.0.
+
+This product uses software developed at
+The OSGi Alliance (http://www.osgi.org/).
+Copyright (c) OSGi Alliance (2000, 2010).
+Licensed under the Apache License 2.0.
+
+This product includes software developed at
+OW2 (http://www.ow2.org/).
+Licensed under the BSD License.
+
+This product includes software developed at
+OPS4J (http://www.ops4j.org/).
+Licensed under the Apache License 2.0.
+
+This product includes software developed at
+Eclipse Foundation (http://www.eclipse.org/).
+Licensed under the EPL.
+
+This product includes software written by
+Antony Lesuisse.
+Licensed under Public Domain.
+
+
+II. Used Software
+
+This product uses software developed at
+FUSE Source (http://www.fusesource.org/).
+Licensed under the Apache License 2.0.
+
+This product uses software developed at
+AOP Alliance (http://aopalliance.sourceforge.net/).
+Licensed under the Public Domain.
+
+This product uses software developed at
+Tanuki Software (http://www.tanukisoftware.com/).
+Licensed under the Apache License 2.0.
+
+This product uses software developed at
+Jasypt (http://jasypt.sourceforge.net/).
+Licensed under the Apache License 2.0.
+
+This product uses software developed at
+JLine (http://jline.sourceforge.net).
+Licensed under the BSD License.
+
+This product uses software developed at
+SLF4J (http://www.slf4j.org/).
+Licensed under the MIT License.
+
+This product uses software developed at
+SpringSource (http://www.springsource.org/).
+Licensed under the Apache License 2.0.
+
+This product includes software from http://www.json.org.
+Copyright (c) 2002 JSON.org
+
+
+III. License Summary
+- Apache License 2.0
+- BSD License
+- EPL License
+- MIT License

http://git-wip-us.apache.org/repos/asf/karaf/blob/4182735c/wrapper/command/NOTICE
----------------------------------------------------------------------
diff --git a/wrapper/command/NOTICE b/wrapper/command/NOTICE
deleted file mode 100644
index b70f1f9..0000000
--- a/wrapper/command/NOTICE
+++ /dev/null
@@ -1,71 +0,0 @@
-Apache Karaf
-Copyright 2010-2014 The Apache Software Foundation
-
-
-I. Included Software
-
-This product includes software developed at
-The Apache Software Foundation (http://www.apache.org/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-The OSGi Alliance (http://www.osgi.org/).
-Copyright (c) OSGi Alliance (2000, 2010).
-Licensed under the Apache License 2.0.
-
-This product includes software developed at
-OW2 (http://www.ow2.org/).
-Licensed under the BSD License.
-
-This product includes software developed at
-OPS4J (http://www.ops4j.org/).
-Licensed under the Apache License 2.0.
-
-This product includes software developed at
-Eclipse Foundation (http://www.eclipse.org/).
-Licensed under the EPL.
-
-This product includes software written by
-Antony Lesuisse.
-Licensed under Public Domain.
-
-
-II. Used Software
-
-This product uses software developed at
-FUSE Source (http://www.fusesource.org/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-AOP Alliance (http://aopalliance.sourceforge.net/).
-Licensed under the Public Domain.
-
-This product uses software developed at
-Tanuki Software (http://www.tanukisoftware.com/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-Jasypt (http://jasypt.sourceforge.net/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-JLine (http://jline.sourceforge.net).
-Licensed under the BSD License.
-
-This product uses software developed at
-SLF4J (http://www.slf4j.org/).
-Licensed under the MIT License.
-
-This product uses software developed at
-SpringSource (http://www.springsource.org/).
-Licensed under the Apache License 2.0.
-
-This product includes software from http://www.json.org.
-Copyright (c) 2002 JSON.org
-
-
-III. License Summary
-- Apache License 2.0
-- BSD License
-- EPL License
-- MIT License

http://git-wip-us.apache.org/repos/asf/karaf/blob/4182735c/wrapper/command/pom.xml
----------------------------------------------------------------------
diff --git a/wrapper/command/pom.xml b/wrapper/command/pom.xml
deleted file mode 100644
index 5e29b84..0000000
--- a/wrapper/command/pom.xml
+++ /dev/null
@@ -1,100 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-
-    <!--
-
-        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.
-    -->
-
-    <modelVersion>4.0.0</modelVersion>
-
-    <parent>
-        <groupId>org.apache.karaf.wrapper</groupId>
-        <artifactId>wrapper</artifactId>
-        <version>4.0.0-SNAPSHOT</version>
-        <relativePath>../pom.xml</relativePath>
-    </parent>
-
-    <artifactId>org.apache.karaf.wrapper.command</artifactId>
-    <packaging>bundle</packaging>
-    <name>Apache Karaf :: Wrapper :: Shell Commands</name>
-    <description>
-        This bundle provides Karaf shell commands to manipulate the OS service wrapper.
-    </description>
-
-    <properties>
-        <appendedResourcesDirectory>${basedir}/../../etc/appended-resources</appendedResourcesDirectory>
-    </properties>
-
-    <dependencies>
-        <dependency>
-            <groupId>org.apache.karaf.wrapper</groupId>
-            <artifactId>org.apache.karaf.wrapper.core</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.karaf.shell</groupId>
-            <artifactId>org.apache.karaf.shell.console</artifactId>
-            <scope>provided</scope>
-        </dependency>
-
-        <dependency>
-            <groupId>org.apache.felix</groupId>
-            <artifactId>org.apache.felix.gogo.runtime</artifactId>
-            <scope>provided</scope>
-        </dependency>
-    </dependencies>
-
-    <build>
-        <resources>
-            <resource>
-                <directory>${project.basedir}/src/main/resources</directory>
-                <includes>
-                    <include>**/*</include>
-                </includes>
-            </resource>
-            <resource>
-                <directory>${project.basedir}/src/main/resources</directory>
-                <filtering>true</filtering>
-                <includes>
-                    <include>**/*.info</include>
-                </includes>
-            </resource>
-        </resources>
-        <plugins>
-            <plugin>
-                <groupId>org.apache.felix</groupId>
-                <artifactId>maven-bundle-plugin</artifactId>
-                <configuration>
-                    <instructions>
-                        <Import-Package>
-                            !org.apache.karaf.main,
-                            !org.tanukisoftware*,
-                            org.apache.karaf.wrapper,
-                            javax.management,
-                            javax.management.loading,
-                            *
-                        </Import-Package>
-                        <Karaf-Commands>
-                            org.apache.karaf.wrapper.commands
-                        </Karaf-Commands>
-                    </instructions>
-                </configuration>
-            </plugin>
-        </plugins>
-    </build>
-
-</project>

http://git-wip-us.apache.org/repos/asf/karaf/blob/4182735c/wrapper/command/src/main/java/org/apache/karaf/wrapper/commands/Install.java
----------------------------------------------------------------------
diff --git a/wrapper/command/src/main/java/org/apache/karaf/wrapper/commands/Install.java b/wrapper/command/src/main/java/org/apache/karaf/wrapper/commands/Install.java
deleted file mode 100644
index 346f6f1..0000000
--- a/wrapper/command/src/main/java/org/apache/karaf/wrapper/commands/Install.java
+++ /dev/null
@@ -1,199 +0,0 @@
-/*
- * 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.karaf.wrapper.commands;
-
-import java.io.File;
-
-import org.apache.karaf.shell.api.action.Action;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Option;
-import org.apache.karaf.shell.api.action.lifecycle.Reference;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.apache.karaf.wrapper.WrapperService;
-
-import static org.apache.karaf.shell.support.ansi.SimpleAnsi.INTENSITY_BOLD;
-import static org.apache.karaf.shell.support.ansi.SimpleAnsi.INTENSITY_NORMAL;
-
-/**
- * Installs the Karaf instance as a service in your operating system.
- */
-@Command(scope = "wrapper", name = "install", description = "Install the container as a system service in the OS.")
-@Service
-public class Install implements Action {
-
-	@Option(name = "-n", aliases = { "--name" }, description = "The service name that will be used when installing the service. (Default: karaf)", required = false, multiValued = false)
-	private String name = "karaf";
-
-	@Option(name = "-d", aliases = { "--display" }, description = "The display name of the service.", required = false, multiValued = false)
-	private String displayName = "karaf";
-
-	@Option(name = "-D", aliases = { "--description" }, description = "The description of the service.", required = false, multiValued = false)
-	private String description = "";
-
-	@Option(name = "-s", aliases = { "--start-type" }, description = "Mode in which the service is installed. AUTO_START or DEMAND_START (Default: AUTO_START)", required = false, multiValued = false)
-	private String startType = "AUTO_START";
-
-    @Reference
-	private WrapperService wrapperService;
-
-    @Override
-	public Object execute() throws Exception {
-        File[] wrapperPaths = wrapperService.install(name, displayName, description, startType);
-
-        String os = System.getProperty("os.name", "Unknown");
-        File wrapperConf = wrapperPaths[0];
-        File serviceFile = wrapperPaths[1];
-
-        System.out.println("");
-        System.out.println("Setup complete.  You may wish to tweak the JVM properties in the wrapper configuration file:");
-        System.out.println("\t" + wrapperConf.getPath());
-        System.out.println("before installing and starting the service.");
-        System.out.println("");
-        if (os.startsWith("Win")) {
-            System.out.println("");
-            System.out.println(INTENSITY_BOLD + "MS Windows system detected:" + INTENSITY_NORMAL);
-            System.out.println("To install the service, run: ");
-            System.out.println("  C:> " + serviceFile.getPath() + " install");
-            System.out.println("");
-            System.out.println("Once installed, to start the service run: ");
-            System.out.println("  C:> net start \"" + name + "\"");
-            System.out.println("");
-            System.out.println("Once running, to stop the service run: ");
-            System.out.println("  C:> net stop \"" + name + "\"");
-            System.out.println("");
-            System.out.println("Once stopped, to remove the installed the service run: ");
-            System.out.println("  C:> " + serviceFile.getPath() + " remove");
-            System.out.println("");
-        } else if (os.startsWith("Mac OS X")) {
-            System.out.println("");
-            System.out.println(INTENSITY_BOLD + "Mac OS X system detected:" + INTENSITY_NORMAL);
-            System.out.println("to add bin/org.apache.karaf.KARAF as user service move this file into ~/Library/LaunchAgents/");  
-            System.out.println("> mv bin/org.apache.karaf.KARAF.plist ~/Library/LaunchAgents/");
-            System.out.println("");
-            System.out.println("to add org.apache.karaf.KARAF as system service move this into /Library/LaunchDaemons");  
-            System.out.println("> sudo mv bin/org.apache.karaf.KARAF.plist /Library/LaunchDaemons/");  
-            System.out.println("change owner and rights");  
-            System.out.println("> sudo chown root:wheel /Library/LaunchDaemons/org.apache.karaf.KARAF.plist");  
-            System.out.println("> sudo chmod u=rw,g=r,o=r /Library/LaunchDaemons/org.apache.karaf.KARAF.plist");  
-            System.out.println(""); 
-            System.out.println("test your service");  
-            System.out.println("> launchctl load ~/Library/LaunchAgents/org.apache.karaf.KARAF.plist");  
-            System.out.println("> launchctl start org.apache.karaf.KARAF");  
-            System.out.println("> launchctl stop org.apache.karaf.KARAF");  
-            System.out.println("");  
-            System.out.println("after restart your session or system");  
-            System.out.println("you can use launchctl command to start and stop your service");  
-            System.out.println("");  
-            System.out.println("for removing the service call");  
-            System.out.println("> launchctl remove org.apache.karaf.KARAF");  
-            System.out.println("");
-        } else if (os.startsWith("Linux")) {
-
-            File debianVersion = new File("/etc/debian_version");
-            File redhatRelease = new File("/etc/redhat-release");
-
-            if (redhatRelease.exists()) {
-                System.out.println("");
-                System.out.println(INTENSITY_BOLD + "RedHat/Fedora/CentOS Linux system detected:" + INTENSITY_NORMAL);
-                System.out.println("  To install the service:");
-                System.out.println("    $ ln -s " + serviceFile.getPath() + " /etc/init.d/");
-                System.out.println("    $ chkconfig " + serviceFile.getName() + " --add");
-                System.out.println("");
-                System.out.println("  To start the service when the machine is rebooted:");
-                System.out.println("    $ chkconfig " + serviceFile.getName() + " on");
-                System.out.println("");
-                System.out.println("  To disable starting the service when the machine is rebooted:");
-                System.out.println("    $ chkconfig " + serviceFile.getName() + " off");
-                System.out.println("");
-                System.out.println("  To start the service:");
-                System.out.println("    $ service " + serviceFile.getName() + " start");
-                System.out.println("");
-                System.out.println("  To stop the service:");
-                System.out.println("    $ service " + serviceFile.getName() + " stop");
-                System.out.println("");
-                System.out.println("  To uninstall the service :");
-                System.out.println("    $ chkconfig " + serviceFile.getName() + " --del");
-                System.out.println("    $ rm /etc/init.d/" + serviceFile.getPath());
-            } else if (debianVersion.exists()) {
-                System.out.println("");
-                System.out.println(INTENSITY_BOLD + "Ubuntu/Debian Linux system detected:" + INTENSITY_NORMAL);
-                System.out.println("  To install the service:");
-                System.out.println("    $ ln -s " + serviceFile.getPath() + " /etc/init.d/");
-                System.out.println("");
-                System.out.println("  To start the service when the machine is rebooted:");
-                System.out.println("    $ update-rc.d " + serviceFile.getName() + " defaults");
-                System.out.println("");
-                System.out.println("  To disable starting the service when the machine is rebooted:");
-                System.out.println("    $ update-rc.d -f " + serviceFile.getName() + " remove");
-                System.out.println("");
-                System.out.println("  To start the service:");
-                System.out.println("    $ /etc/init.d/" + serviceFile.getName() + " start");
-                System.out.println("");
-                System.out.println("  To stop the service:");
-                System.out.println("    $ /etc/init.d/" + serviceFile.getName() + " stop");
-                System.out.println("");
-                System.out.println("  To uninstall the service :");
-                System.out.println("    $ rm /etc/init.d/" + serviceFile.getName());
-            } else {
-				System.out.println("");
-                System.out.println(INTENSITY_BOLD + "On Redhat/Fedora/CentOS Systems:" + INTENSITY_NORMAL);
-				System.out.println("  To install the service:");
-				System.out.println("    $ ln -s "+serviceFile.getPath()+" /etc/init.d/");
-				System.out.println("    $ chkconfig "+serviceFile.getName()+" --add");
-				System.out.println("");
-				System.out.println("  To start the service when the machine is rebooted:");
-				System.out.println("    $ chkconfig "+serviceFile.getName()+" on");
-				System.out.println("");
-				System.out.println("  To disable starting the service when the machine is rebooted:");
-				System.out.println("    $ chkconfig "+serviceFile.getName()+" off");
-				System.out.println("");
-				System.out.println("  To start the service:");
-				System.out.println("    $ service "+serviceFile.getName()+" start");
-				System.out.println("");
-				System.out.println("  To stop the service:");
-				System.out.println("    $ service "+serviceFile.getName()+" stop");
-				System.out.println("");
-				System.out.println("  To uninstall the service :");
-				System.out.println("    $ chkconfig "+serviceFile.getName()+" --del");
-				System.out.println("    $ rm /etc/init.d/"+serviceFile.getName());
-
-				System.out.println("");
-                System.out.println(INTENSITY_BOLD + "On Ubuntu/Debian Systems:" + INTENSITY_NORMAL);
-				System.out.println("  To install the service:");
-				System.out.println("    $ ln -s "+serviceFile.getPath()+" /etc/init.d/");
-				System.out.println("");
-				System.out.println("  To start the service when the machine is rebooted:");
-				System.out.println("    $ update-rc.d "+serviceFile.getName()+" defaults");
-				System.out.println("");
-				System.out.println("  To disable starting the service when the machine is rebooted:");
-				System.out.println("    $ update-rc.d -f "+serviceFile.getName()+" remove");
-				System.out.println("");
-				System.out.println("  To start the service:");
-				System.out.println("    $ /etc/init.d/"+serviceFile.getName()+" start");
-				System.out.println("");
-				System.out.println("  To stop the service:");
-				System.out.println("    $ /etc/init.d/"+serviceFile.getName()+" stop");
-				System.out.println("");
-				System.out.println("  To uninstall the service :");
-				System.out.println("    $ rm /etc/init.d/"+serviceFile.getName());
-            }
-
-        }
-
-        return null;
-    }
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/4182735c/wrapper/command/src/main/resources/META-INF/services/org/apache/karaf/shell/commands
----------------------------------------------------------------------
diff --git a/wrapper/command/src/main/resources/META-INF/services/org/apache/karaf/shell/commands b/wrapper/command/src/main/resources/META-INF/services/org/apache/karaf/shell/commands
deleted file mode 100644
index 73b329d..0000000
--- a/wrapper/command/src/main/resources/META-INF/services/org/apache/karaf/shell/commands
+++ /dev/null
@@ -1,18 +0,0 @@
-##---------------------------------------------------------------------------
-##  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.
-##---------------------------------------------------------------------------
-org.apache.karaf.wrapper.internal.WrapperServiceImpl
-org.apache.karaf.wrapper.commands.Install
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/karaf/blob/4182735c/wrapper/command/src/main/resources/OSGI-INF/bundle.info
----------------------------------------------------------------------
diff --git a/wrapper/command/src/main/resources/OSGI-INF/bundle.info b/wrapper/command/src/main/resources/OSGI-INF/bundle.info
deleted file mode 100644
index c5d6ba0..0000000
--- a/wrapper/command/src/main/resources/OSGI-INF/bundle.info
+++ /dev/null
@@ -1,19 +0,0 @@
-h1. Synopsis
-
-${project.name}
-
-${project.description}
-
-Maven URL:
-[mvn:${project.groupId}/${project.artifactId}/${project.version}]
-
-h1. Description
-
-This bundle contains all Karaf shell commands related to the wrapper.
-
-The following commands are available:
-* wrapper:install - Install this Karaf instance as a service in your operating system.
-
-h1. See also
-
-Wrapper - section of the Karaf User Guide.
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/karaf/blob/4182735c/wrapper/core/NOTICE
----------------------------------------------------------------------
diff --git a/wrapper/core/NOTICE b/wrapper/core/NOTICE
deleted file mode 100644
index b70f1f9..0000000
--- a/wrapper/core/NOTICE
+++ /dev/null
@@ -1,71 +0,0 @@
-Apache Karaf
-Copyright 2010-2014 The Apache Software Foundation
-
-
-I. Included Software
-
-This product includes software developed at
-The Apache Software Foundation (http://www.apache.org/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-The OSGi Alliance (http://www.osgi.org/).
-Copyright (c) OSGi Alliance (2000, 2010).
-Licensed under the Apache License 2.0.
-
-This product includes software developed at
-OW2 (http://www.ow2.org/).
-Licensed under the BSD License.
-
-This product includes software developed at
-OPS4J (http://www.ops4j.org/).
-Licensed under the Apache License 2.0.
-
-This product includes software developed at
-Eclipse Foundation (http://www.eclipse.org/).
-Licensed under the EPL.
-
-This product includes software written by
-Antony Lesuisse.
-Licensed under Public Domain.
-
-
-II. Used Software
-
-This product uses software developed at
-FUSE Source (http://www.fusesource.org/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-AOP Alliance (http://aopalliance.sourceforge.net/).
-Licensed under the Public Domain.
-
-This product uses software developed at
-Tanuki Software (http://www.tanukisoftware.com/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-Jasypt (http://jasypt.sourceforge.net/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-JLine (http://jline.sourceforge.net).
-Licensed under the BSD License.
-
-This product uses software developed at
-SLF4J (http://www.slf4j.org/).
-Licensed under the MIT License.
-
-This product uses software developed at
-SpringSource (http://www.springsource.org/).
-Licensed under the Apache License 2.0.
-
-This product includes software from http://www.json.org.
-Copyright (c) 2002 JSON.org
-
-
-III. License Summary
-- Apache License 2.0
-- BSD License
-- EPL License
-- MIT License

http://git-wip-us.apache.org/repos/asf/karaf/blob/4182735c/wrapper/core/pom.xml
----------------------------------------------------------------------
diff --git a/wrapper/core/pom.xml b/wrapper/core/pom.xml
deleted file mode 100644
index a097bfa..0000000
--- a/wrapper/core/pom.xml
+++ /dev/null
@@ -1,128 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-
-    <!--
-
-        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.
-    -->
-
-    <modelVersion>4.0.0</modelVersion>
-
-    <parent>
-        <groupId>org.apache.karaf.wrapper</groupId>
-        <artifactId>wrapper</artifactId>
-        <version>4.0.0-SNAPSHOT</version>
-        <relativePath>../pom.xml</relativePath>
-    </parent>
-
-    <artifactId>org.apache.karaf.wrapper.core</artifactId>
-    <packaging>bundle</packaging>
-    <name>Apache Karaf :: Wrapper :: Core</name>
-    <description>
-        Core implementation and integration of the Java Service Wrapper.
-        It provides a complete integration of Karaf with your Operating System.
-    </description>
-
-    <properties>
-        <appendedResourcesDirectory>${basedir}/../../etc/appended-resources</appendedResourcesDirectory>
-    </properties>
-
-    <dependencies>
-        <dependency>
-            <groupId>org.osgi</groupId>
-            <artifactId>org.osgi.core</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.karaf</groupId>
-            <artifactId>org.apache.karaf.main</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.karaf.shell</groupId>
-            <artifactId>org.apache.karaf.shell.core</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>tanukisoft</groupId>
-            <artifactId>wrapper</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.slf4j</groupId>
-            <artifactId>slf4j-api</artifactId>
-        </dependency>
-
-        <dependency>
-            <groupId>org.slf4j</groupId>
-            <artifactId>slf4j-jdk14</artifactId>
-            <scope>test</scope>
-        </dependency>
-    </dependencies>
-
-    <build>
-        <resources>
-            <resource>
-                <directory>${project.basedir}/src/main/resources</directory>
-                <includes>
-                    <include>**/*</include>
-                </includes>
-            </resource>
-            <resource>
-                <directory>${project.basedir}/src/main/resources</directory>
-                <filtering>true</filtering>
-                <includes>
-                    <include>**/*.info</include>
-                </includes>
-            </resource>
-        </resources>
-        <plugins>
-            <plugin>
-                <groupId>org.codehaus.mojo</groupId>
-                <artifactId>exec-maven-plugin</artifactId>
-                <configuration>
-                    <mainClass>Main</mainClass>
-                </configuration>
-            </plugin>
-            <plugin>
-                <groupId>org.apache.felix</groupId>
-                <artifactId>maven-bundle-plugin</artifactId>
-                <configuration>
-                    <instructions>
-                        <Export-Package>
-                            org.apache.karaf.wrapper,
-                            org.apache.karaf.wrapper.management
-                        </Export-Package>
-                        <Private-Package>
-                            org.apache.karaf.wrapper.internal,
-                            org.apache.karaf.wrapper.internal.osgi,
-                            org.apache.karaf.wrapper.management.internal,
-                            org.tanukisoftware.wrapper*,
-                            org.apache.karaf.main*,
-                            org.apache.karaf.util.tracker
-                        </Private-Package>
-                        <Import-Package>
-                            !org.apache.felix.utils.properties,
-                            !org.apache.karaf.util.locks,
-                            !org.apache.karaf.info,
-                            *
-                        </Import-Package>
-                        <Bundle-Activator>
-                            org.apache.karaf.wrapper.internal.osgi.Activator
-                        </Bundle-Activator>
-                    </instructions>
-                </configuration>
-            </plugin>
-        </plugins>
-    </build>
-
-</project>

http://git-wip-us.apache.org/repos/asf/karaf/blob/4182735c/wrapper/core/src/main/java/org/apache/karaf/wrapper/WrapperService.java
----------------------------------------------------------------------
diff --git a/wrapper/core/src/main/java/org/apache/karaf/wrapper/WrapperService.java b/wrapper/core/src/main/java/org/apache/karaf/wrapper/WrapperService.java
deleted file mode 100644
index fb05a16..0000000
--- a/wrapper/core/src/main/java/org/apache/karaf/wrapper/WrapperService.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * 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.karaf.wrapper;
-
-import java.io.File;
-
-/**
- * Interface describing the Wrapper service.
- */
-public interface WrapperService {
-
-    /**
-     * Install the Karaf container as a system service in the OS.
-     */
-    public void install() throws Exception;
-
-    /**
-     * Install the Karaf container as a system service in the OS.
-     *
-     * @param name The service name that will be used when installing the service.
-     * @param displayName The display name of the service.
-     * @param description The description of the service.
-     * @param startType Mode in which the service is installed. AUTO_START or DEMAND_START.
-     * @return an array containing the wrapper configuration file (index 0) and the service file (index 1)
-     */
-    public File[] install(String name, String displayName, String description, String startType) throws Exception;
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/4182735c/wrapper/core/src/main/java/org/apache/karaf/wrapper/internal/Main.java
----------------------------------------------------------------------
diff --git a/wrapper/core/src/main/java/org/apache/karaf/wrapper/internal/Main.java b/wrapper/core/src/main/java/org/apache/karaf/wrapper/internal/Main.java
deleted file mode 100644
index 8f3060e..0000000
--- a/wrapper/core/src/main/java/org/apache/karaf/wrapper/internal/Main.java
+++ /dev/null
@@ -1,146 +0,0 @@
-/*
- * 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.karaf.wrapper.internal;
-
-import org.apache.karaf.main.ShutdownCallback;
-import org.tanukisoftware.wrapper.WrapperListener;
-import org.tanukisoftware.wrapper.WrapperManager;
-
-/**
- * Java Service Wrapper Main class
- */
-public class Main extends Thread implements WrapperListener, ShutdownCallback {
-
-    private org.apache.karaf.main.Main main;
-    private volatile boolean destroying;
-
-    /*---------------------------------------------------------------
-     * Constructors
-     *-------------------------------------------------------------*/
-    private Main() {
-    }
-
-    /*---------------------------------------------------------------
-     * WrapperListener Methods
-     *-------------------------------------------------------------*/
-
-    /**
-     * The start method is called when the WrapperManager is signaled by the
-     * native Wrapper code that it can start its application.  This
-     * method call is expected to return, so a new thread should be launched
-     * if necessary.
-     *
-     * @param args List of arguments used to initialize the application.
-     * @return Any error code if the application should exit on completion
-     *         of the start method.  If there were no problems then this
-     *         method should return null.
-     */
-    public Integer start(String[] args) {
-        main = new org.apache.karaf.main.Main(args);
-        try {
-            main.launch();
-            main.setShutdownCallback(this);
-            start();
-            return null;
-        } catch (Throwable ex) {
-            System.err.println("Could not create framework: " + ex);
-            ex.printStackTrace();
-            return -1;
-        }
-    }
-
-    public void run() {
-        try {
-            main.awaitShutdown();
-            if (!destroying) {
-                WrapperManager.stop(main.getExitCode());
-            }
-        } catch (Exception e) {
-            // Ignore
-        }
-    }
-
-    /**
-     * Called when the application is shutting down.  The Wrapper assumes that
-     * this method will return fairly quickly.  If the shutdown code code
-     * could potentially take a long time, then WrapperManager.signalStopping()
-     * should be called to extend the timeout period.  If for some reason,
-     * the stop method can not return, then it must call
-     * WrapperManager.stopped() to avoid warning messages from the Wrapper.
-     *
-     * @param exitCode The suggested exit code that will be returned to the OS
-     *                 when the JVM exits.
-     * @return The exit code to actually return to the OS.  In most cases, this
-     *         should just be the value of exitCode, however the user code has
-     *         the option of changing the exit code if there are any problems
-     *         during shutdown.
-     */
-    public int stop(int exitCode) {
-        try {
-            destroying = true;
-            if (!main.destroy()) {
-                System.err.println("Timeout waiting for Karaf to shutdown");
-                return -3;
-            }
-        } catch (Throwable ex) {
-            System.err.println("Error occured shutting down framework: " + ex);
-            ex.printStackTrace();
-            return -2;
-        }
-
-        return main.getExitCode();
-    }
-
-    /**
-     * Call-back method is called by the @{link org.apache.karaf.main.Main} for Signaling
-     * that the stopping process is in progress and the wrapper doesn't kill the JVM.
-     */
-    public void waitingForShutdown(int delay) {
-        WrapperManager.signalStopping(delay);
-    }
-
-    /**
-     * Called whenever the native Wrapper code traps a system control signal
-     * against the Java process.  It is up to the callback to take any actions
-     * necessary.  Possible values are: WrapperManager.WRAPPER_CTRL_C_EVENT,
-     * WRAPPER_CTRL_CLOSE_EVENT, WRAPPER_CTRL_LOGOFF_EVENT, or
-     * WRAPPER_CTRL_SHUTDOWN_EVENT
-     *
-     * @param event The system control signal.
-     */
-    public void controlEvent(int event) {
-        if ((event == WrapperManager.WRAPPER_CTRL_LOGOFF_EVENT)
-                && (WrapperManager.isLaunchedAsService())) {
-            // Ignore
-        } else {
-            WrapperManager.stop(0);
-            // Will not get here.
-        }
-    }
-
-    /*---------------------------------------------------------------
-     * Main Method
-     *-------------------------------------------------------------*/
-    public static void main(String[] args) {
-        // Start the application.  If the JVM was launched from the native
-        //  Wrapper then the application will wait for the native Wrapper to
-        //  call the application's start method.  Otherwise the start method
-        //  will be called immediately.
-        WrapperManager.start(new Main(), args);
-    }
-
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/karaf/blob/4182735c/wrapper/core/src/main/java/org/apache/karaf/wrapper/internal/PumpStreamHandler.java
----------------------------------------------------------------------
diff --git a/wrapper/core/src/main/java/org/apache/karaf/wrapper/internal/PumpStreamHandler.java b/wrapper/core/src/main/java/org/apache/karaf/wrapper/internal/PumpStreamHandler.java
deleted file mode 100644
index 8737547..0000000
--- a/wrapper/core/src/main/java/org/apache/karaf/wrapper/internal/PumpStreamHandler.java
+++ /dev/null
@@ -1,246 +0,0 @@
-/*
- * 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.karaf.wrapper.internal;
-
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.IOException;
-
-//
-// Based on Apache Ant 1.6.5
-//
-
-/**
- * Copies standard output and error of children streams to standard output and error of the parent.
- */
-public class PumpStreamHandler {
-
-    private final InputStream in;
-
-    private final OutputStream out;
-
-    private final OutputStream err;
-
-    private final String name;
-
-    private StreamPumper outputPump;
-
-    private StreamPumper errorPump;
-
-    private StreamPumper inputPump;
-
-    //
-    // NOTE: May want to use a ThreadPool here, 3 threads per/pair seems kinda expensive :-(
-    //
-
-    public PumpStreamHandler(final InputStream in, final OutputStream out, final OutputStream err, String name) {
-        assert in != null;
-        assert out != null;
-        assert err != null;
-        assert name != null;
-
-        this.in = in;
-        this.out = out;
-        this.err = err;
-        this.name = name;
-    }
-
-    public PumpStreamHandler(final InputStream in, final OutputStream out, final OutputStream err) {
-        this(in, out, err, "<unknown>");
-    }
-
-    public PumpStreamHandler(final OutputStream out, final OutputStream err) {
-        this(null, out, err);
-    }
-
-    public PumpStreamHandler(final OutputStream outAndErr) {
-        this(outAndErr, outAndErr);
-    }
-
-    /**
-     * Set the input stream from which to read the standard output of the child.
-     */
-    public void setChildOutputStream(final InputStream in) {
-        assert in != null;
-
-        createChildOutputPump(in, out);
-    }
-
-    /**
-     * Set the input stream from which to read the standard error of the child.
-     */
-    public void setChildErrorStream(final InputStream in) {
-        assert in != null;
-
-        if (err != null) {
-            createChildErrorPump(in, err);
-        }
-    }
-
-    /**
-     * Set the output stream by means of which input can be sent to the child.
-     */
-    public void setChildInputStream(final OutputStream out) {
-        assert out != null;
-
-        if (in != null) {
-            inputPump = createInputPump(in, out, true);
-        } else {
-            try {
-                out.close();
-            } catch (IOException e) {
-            }
-        }
-    }
-
-    /**
-     * Attach to a child streams from the given process.
-     *
-     * @param p The process to attach to.
-     */
-    public void attach(final Process p) {
-        assert p != null;
-
-        setChildInputStream(p.getOutputStream());
-        setChildOutputStream(p.getInputStream());
-        setChildErrorStream(p.getErrorStream());
-    }
-
-    /**
-     * Start pumping the streams.
-     */
-    public void start() {
-        if (outputPump != null) {
-            Thread thread = new Thread(outputPump);
-            thread.setDaemon(true);
-            thread.setName("Output pump for " + this.name);
-            thread.start();
-        }
-
-        if (errorPump != null) {
-            Thread thread = new Thread(errorPump);
-            thread.setDaemon(true);
-            thread.setName("Error pump for " + this.name);
-            thread.start();
-        }
-
-        if (inputPump != null) {
-            Thread thread = new Thread(inputPump);
-            thread.setDaemon(true);
-            thread.setName("Input pump for " + this.name);
-            thread.start();
-        }
-    }
-
-    /**
-     * Stop pumping the streams.
-     */
-    public void stop() {
-        if (outputPump != null) {
-            try {
-                outputPump.stop();
-                outputPump.waitFor();
-            } catch (InterruptedException e) {
-                // ignore
-            }
-        }
-
-        if (errorPump != null) {
-            try {
-                errorPump.stop();
-                errorPump.waitFor();
-            } catch (InterruptedException e) {
-                // ignore
-            }
-        }
-
-        if (inputPump != null) {
-            inputPump.stop();
-        }
-
-        try {
-            err.flush();
-        } catch (IOException e) {
-        }
-        try {
-            out.flush();
-        } catch (IOException e) {
-        }
-    }
-
-    /**
-     * Create the pump to handle child output.
-     */
-    protected void createChildOutputPump(final InputStream in, final OutputStream out) {
-        assert in != null;
-        assert out != null;
-
-        outputPump = createPump(in, out);
-    }
-
-    /**
-     * Create the pump to handle error output.
-     */
-    protected void createChildErrorPump(final InputStream in, final OutputStream out) {
-        assert in != null;
-        assert out != null;
-
-        errorPump = createPump(in, out);
-    }
-
-    /**
-     * Creates a stream pumper to copy the given input stream to the given output stream.
-     */
-    protected StreamPumper createPump(final InputStream in, final OutputStream out) {
-        assert in != null;
-        assert out != null;
-
-        return createPump(in, out, false);
-    }
-
-    /**
-     * Creates a stream pumper to copy the given input stream to the
-     * given output stream.
-     *
-     * @param in                 The input stream to copy from.
-     * @param out                The output stream to copy to.
-     * @param closeWhenExhausted If true close the inputstream.
-     * @return A thread object that does the pumping.
-     */
-    protected StreamPumper createPump(final InputStream in, final OutputStream out, final boolean closeWhenExhausted) {
-        assert in != null;
-        assert out != null;
-
-        StreamPumper pumper = new StreamPumper(in, out, closeWhenExhausted);
-        return pumper;
-    }
-
-    /**
-     * Creates a stream pumper to copy the given input stream to the
-     * given output stream. Used for standard input.
-     */
-    protected StreamPumper createInputPump(final InputStream in, final OutputStream out, final boolean closeWhenExhausted) {
-        assert in != null;
-        assert out != null;
-
-        StreamPumper pumper = new StreamPumper(in, out, closeWhenExhausted);
-        pumper.setAutoflush(true);
-        return pumper;
-    }
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/4182735c/wrapper/core/src/main/java/org/apache/karaf/wrapper/internal/StreamPumper.java
----------------------------------------------------------------------
diff --git a/wrapper/core/src/main/java/org/apache/karaf/wrapper/internal/StreamPumper.java b/wrapper/core/src/main/java/org/apache/karaf/wrapper/internal/StreamPumper.java
deleted file mode 100644
index 330d8fc..0000000
--- a/wrapper/core/src/main/java/org/apache/karaf/wrapper/internal/StreamPumper.java
+++ /dev/null
@@ -1,195 +0,0 @@
-/*
- * 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.karaf.wrapper.internal;
-
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.IOException;
-
-//
-// Based on Apache Ant 1.6.5
-//
-
-/**
- * Copies all data from an input stream to an output stream.
- */
-public class StreamPumper implements Runnable {
-
-    private InputStream in;
-
-    private OutputStream out;
-
-    private volatile boolean finish;
-
-    private volatile boolean finished;
-
-    private boolean closeWhenExhausted;
-
-    private boolean autoflush;
-
-    private Exception exception;
-
-    private int bufferSize = 128;
-
-    private boolean started;
-
-    /**
-     * Create a new stream pumper.
-     *
-     * @param in                 Input stream to read data from
-     * @param out                Output stream to write data to.
-     * @param closeWhenExhausted If true, the output stream will be closed when
-     *                           the input is exhausted.
-     */
-    public StreamPumper(final InputStream in, final OutputStream out, final boolean closeWhenExhausted) {
-        assert in != null;
-        assert out != null;
-
-        this.in = in;
-        this.out = out;
-        this.closeWhenExhausted = closeWhenExhausted;
-    }
-
-    /**
-     * Create a new stream pumper.
-     *
-     * @param in  Input stream to read data from
-     * @param out Output stream to write data to.
-     */
-    public StreamPumper(final InputStream in, final OutputStream out) {
-        this(in, out, false);
-    }
-
-    /**
-     * Set whether data should be flushed through to the output stream.
-     *
-     * @param autoflush If true, push through data; if false, let it be buffered
-     */
-    public void setAutoflush(boolean autoflush) {
-        this.autoflush = autoflush;
-    }
-
-    /**
-     * Copies data from the input stream to the output stream.
-     * <p/>
-     * Terminates as soon as the input stream is closed or an error occurs.
-     */
-    public void run() {
-        synchronized (this) {
-            started = true;
-        }
-        finished = false;
-        finish = false;
-
-        final byte[] buf = new byte[bufferSize];
-
-        int length;
-        try {
-            while ((length = in.read(buf)) > 0 && !finish) {
-                out.write(buf, 0, length);
-                if (autoflush) {
-                    out.flush();
-                }
-            }
-            out.flush();
-        } catch (Exception e) {
-            synchronized (this) {
-                exception = e;
-            }
-        } finally {
-            if (closeWhenExhausted) {
-                try {
-                    out.close();
-                } catch (IOException e) {
-                }
-            }
-            finished = true;
-
-            synchronized (this) {
-                notifyAll();
-            }
-        }
-    }
-
-    /**
-     * Tells whether the end of the stream has been reached.
-     *
-     * @return true     If the stream has been exhausted.
-     */
-    public boolean isFinished() {
-        return finished;
-    }
-
-    /**
-     * This method blocks until the stream pumper finishes.
-     *
-     * @see #isFinished()
-     */
-    public synchronized void waitFor() throws InterruptedException {
-        while (!isFinished()) {
-            wait();
-        }
-    }
-
-    /**
-     * Set the size in bytes of the read buffer.
-     *
-     * @param bufferSize the buffer size to use.
-     * @throws IllegalStateException if the StreamPumper is already running.
-     */
-    public synchronized void setBufferSize(final int bufferSize) {
-        if (started) {
-            throw new IllegalStateException("Cannot set buffer size on a running StreamPumper");
-        }
-
-        this.bufferSize = bufferSize;
-    }
-
-    /**
-     * Get the size in bytes of the read buffer.
-     *
-     * @return The size of the read buffer.
-     */
-    public synchronized int getBufferSize() {
-        return bufferSize;
-    }
-
-    /**
-     * Get the exception encountered, if any.
-     *
-     * @return The Exception encountered; or null if there was none.
-     */
-    public synchronized Exception getException() {
-        return exception;
-    }
-
-    /**
-     * Stop the pumper as soon as possible.
-     * <p/>
-     * Note that it may continue to block on the input stream
-     * but it will really stop the thread as soon as it gets EOF
-     * or any byte, and it will be marked as finished.
-     */
-    public synchronized void stop() {
-        finish = true;
-
-        notifyAll();
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/4182735c/wrapper/core/src/main/java/org/apache/karaf/wrapper/internal/WrapperServiceImpl.java
----------------------------------------------------------------------
diff --git a/wrapper/core/src/main/java/org/apache/karaf/wrapper/internal/WrapperServiceImpl.java b/wrapper/core/src/main/java/org/apache/karaf/wrapper/internal/WrapperServiceImpl.java
deleted file mode 100644
index ad4aa4a..0000000
--- a/wrapper/core/src/main/java/org/apache/karaf/wrapper/internal/WrapperServiceImpl.java
+++ /dev/null
@@ -1,450 +0,0 @@
-/*
- * 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.karaf.wrapper.internal;
-
-import org.apache.karaf.wrapper.WrapperService;
-import org.fusesource.jansi.Ansi;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.io.*;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Scanner;
-import java.util.jar.JarOutputStream;
-import java.util.zip.ZipEntry;
-
-/**
- * Default implementation of the wrapper service.
- */
-public class WrapperServiceImpl implements WrapperService {
-
-    private final static Logger LOGGER = LoggerFactory.getLogger(WrapperServiceImpl.class);
-
-    public void install() throws Exception {
-        install("karaf", "karaf", "", "AUTO_START");
-    }
-
-    public File[] install(String name, String displayName, String description, String startType) throws Exception {
-
-        File base = new File(System.getProperty("karaf.base"));
-        File etc = new File(System.getProperty("karaf.etc"));
-        File bin = new File(base, "bin");
-        File lib = new File(base, "lib");
-
-        if (name == null) {
-            name = base.getName();
-        }
-
-        HashMap<String, String> props = new HashMap<String, String>();
-        props.put("${java.home}", System.getenv("JAVA_HOME"));
-        props.put("${karaf.home}", System.getProperty("karaf.home"));
-        props.put("${karaf.base}", base.getPath());
-        props.put("${karaf.data}", System.getProperty("karaf.data"));
-        props.put("${karaf.etc}", System.getProperty("karaf.etc"));
-        props.put("${name}", name);
-        props.put("${displayName}", displayName);
-        props.put("${description}", description);
-        props.put("${startType}", startType);
-
-        String os = System.getProperty("os.name", "Unknown");
-        File serviceFile = null;
-        File wrapperConf = null;
-        if (os.startsWith("Win")) {
-            String arch = System.getProperty("os.arch");
-            if (arch.equalsIgnoreCase("amd64") || arch.equalsIgnoreCase("x86_64")) {
-                mkdir(bin);
-
-                copyResourceTo(new File(bin, name + "-wrapper.exe"), "windows64/karaf-wrapper.exe", false);
-
-                serviceFile = new File(bin, name + "-service.bat");
-                wrapperConf = new File(etc, name + "-wrapper.conf");
-
-                copyFilteredResourceTo(wrapperConf, "windows64/karaf-wrapper.conf", props);
-                copyFilteredResourceTo(serviceFile, "windows64/karaf-service.bat", props);
-
-                mkdir(lib);
-                copyResourceTo(new File(lib, "wrapper.dll"), "windows64/wrapper.dll", false);
-            } else {
-                mkdir(bin);
-
-                copyResourceTo(new File(bin, name + "-wrapper.exe"), "windows/karaf-wrapper.exe", false);
-
-                serviceFile = new File(bin, name + "-service.bat");
-                wrapperConf = new File(etc, name + "-wrapper.conf");
-
-                copyFilteredResourceTo(wrapperConf, "windows/karaf-wrapper.conf", props);
-                copyFilteredResourceTo(serviceFile, "windows/karaf-service.bat", props);
-
-                mkdir(lib);
-                copyResourceTo(new File(lib, "wrapper.dll"), "windows/wrapper.dll", false);
-            }
-        } else if (os.startsWith("Mac OS X")) {
-            mkdir(bin);
-
-            File file = new File(bin, name + "-wrapper");
-            copyResourceTo(file, "macosx/karaf-wrapper", false);
-            chmod(file, "a+x");
-
-            serviceFile = new File(bin, name + "-service");
-            copyFilteredResourceTo(serviceFile, "unix/karaf-service", props);
-            chmod(serviceFile, "a+x");
-
-            wrapperConf = new File(etc, name + "-wrapper.conf");
-            copyFilteredResourceTo(wrapperConf, "unix/karaf-wrapper.conf", props);
-
-            File plistConf = new File(bin, "org.apache.karaf."+ name + ".plist");
-            copyFilteredResourceTo(plistConf, "macosx/org.apache.karaf.KARAF.plist", props);
-            
-            mkdir(lib);
-
-            copyResourceTo(new File(lib, "libwrapper.jnilib"), "macosx/libwrapper.jnilib", false);
-        } else if (os.startsWith("Linux")) {
-            String arch = System.getProperty("os.arch");
-            if (arch.equalsIgnoreCase("amd64") || arch.equalsIgnoreCase("x86_64")) {
-                mkdir(bin);
-
-                File file = new File(bin, name + "-wrapper");
-                copyResourceTo(file, "linux64/karaf-wrapper", false);
-                chmod(file, "a+x");
-
-                serviceFile = new File(bin, name + "-service");
-                copyFilteredResourceTo(serviceFile, "unix/karaf-service", props);
-                chmod(serviceFile, "a+x");
-
-                wrapperConf = new File(etc, name + "-wrapper.conf");
-                copyFilteredResourceTo(wrapperConf, "unix/karaf-wrapper.conf", props);
-
-                mkdir(lib);
-                copyResourceTo(new File(lib, "libwrapper.so"), "linux64/libwrapper.so", false);
-            } else {
-                mkdir(bin);
-
-                File file = new File(bin, name + "-wrapper");
-                copyResourceTo(file, "linux/karaf-wrapper", false);
-                chmod(file, "a+x");
-
-                serviceFile = new File(bin, name + "-service");
-                copyFilteredResourceTo(serviceFile, "unix/karaf-service", props);
-                chmod(serviceFile, "a+x");
-
-                wrapperConf = new File(etc, name + "-wrapper.conf");
-                copyFilteredResourceTo(wrapperConf, "unix/karaf-wrapper.conf", props);
-
-                mkdir(lib);
-                copyResourceTo(new File(lib, "libwrapper.so"), "linux/libwrapper.so", false);
-            }
-        } else if (os.startsWith("AIX")) {
-            String arch = System.getProperty("os.arch");
-            if (arch.equalsIgnoreCase("ppc64")) {
-                mkdir(bin);
-
-                File file = new File(bin, name + "-wrapper");
-                copyResourceTo(file, "aix/ppc64/karaf-wrapper", false);
-                chmod(file, "a+x");
-
-                serviceFile = new File(bin, name + "-service");
-                copyFilteredResourceTo(serviceFile, "unix/karaf-service", props);
-                chmod(serviceFile, "a+x");
-
-                wrapperConf = new File(etc, name + "-wrapper.conf");
-                copyFilteredResourceTo(wrapperConf, "unix/karaf-wrapper.conf", props);
-
-                mkdir(lib);
-                copyResourceTo(new File(lib, "libwrapper.a"), "aix/ppc64/libwrapper.a", false);
-            } else {
-                mkdir(bin);
-
-                File file = new File(bin, name + "-wrapper");
-                copyResourceTo(file, "aix/ppc32/karaf-wrapper", false);
-                chmod(file, "a+x");
-
-                serviceFile = new File(bin, name + "-service");
-                copyFilteredResourceTo(serviceFile, "unix/karaf-service", props);
-                chmod(serviceFile, "a+x");
-
-                wrapperConf = new File(etc, name + "-wrapper.conf");
-                copyFilteredResourceTo(wrapperConf, "unix/karaf-wrapper.conf", props);
-
-                mkdir(lib);
-                copyResourceTo(new File(lib, "libwrapper.a"), "aix/ppc32/libwrapper.a", false);
-            }
-        } else if (os.startsWith("Solaris") || os.startsWith("SunOS")) {
-            String arch = System.getProperty("os.arch");
-            if (arch.equalsIgnoreCase("sparc")) {
-                mkdir(bin);
-
-                File file = new File(bin, name + "-wrapper");
-                copyResourceTo(file, "solaris/sparc64/karaf-wrapper", false);
-                chmod(file, "a+x");
-
-                serviceFile = new File(bin, name + "-service");
-                copyFilteredResourceTo(serviceFile, "unix/karaf-service", props);
-                chmod(serviceFile, "a+x");
-
-                wrapperConf = new File(etc, name + "-wrapper.conf");
-                copyFilteredResourceTo(wrapperConf, "unix/karaf-wrapper.conf", props);
-
-                mkdir(lib);
-                copyResourceTo(new File(lib, "libwrapper.so"), "solaris/sparc64/libwrapper.so", false);
-            } else if (arch.equalsIgnoreCase("x86")) {
-                mkdir(bin);
-
-                File file = new File(bin, name + "-wrapper");
-                copyResourceTo(file, "solaris/x86/karaf-wrapper", false);
-                chmod(file, "a+x");
-
-                serviceFile = new File(bin, name + "-service");
-                copyFilteredResourceTo(serviceFile, "unix/karaf-service", props);
-                chmod(serviceFile, "a+x");
-
-                wrapperConf = new File(etc, name + "-wrapper.conf");
-                copyFilteredResourceTo(wrapperConf, "unix/karaf-wrapper.conf", props);
-
-                mkdir(lib);
-                copyResourceTo(new File(lib, "libwrapper.so"), "solaris/x86/libwrapper.so", false);
-            } else if (arch.equalsIgnoreCase("x86_64")) {
-                mkdir(bin);
-
-                File file = new File(bin, name + "-wrapper");
-                copyResourceTo(file, "solaris/x86_64/karaf-wrapper", false);
-                chmod(file, "a+x");
-
-                serviceFile = new File(bin, name + "-service");
-                copyFilteredResourceTo(serviceFile, "unix/karaf-service", props);
-                chmod(serviceFile, "a+x");
-
-                wrapperConf = new File(etc, name + "-wrapper.conf");
-                copyFilteredResourceTo(wrapperConf, "unix/karaf-wrapper.conf", props);
-
-                mkdir(lib);
-                copyResourceTo(new File(lib, "libwrapper.so"), "solaris/x86_64/libwrapper.so", false);
-            } else {
-                mkdir(bin);
-
-                File file = new File(bin, name + "-wrapper");
-                copyResourceTo(file, "solaris/sparc32/karaf-wrapper", false);
-                chmod(file, "a+x");
-
-                serviceFile = new File(bin, name + "-service");
-                copyFilteredResourceTo(serviceFile, "unix/karaf-service", props);
-                chmod(serviceFile, "a+x");
-
-                wrapperConf = new File(etc, name + "-wrapper.conf");
-                copyFilteredResourceTo(wrapperConf, "unix/karaf-wrapper.conf", props);
-
-                mkdir(lib);
-                copyResourceTo(new File(lib, "libwrapper.so"), "solaris/sparc32/libwrapper.so", false);
-            }
-        } else if (os.startsWith("HP-UX") || os.startsWith("HPUX")) {
-            mkdir(bin);
-
-            File file = new File(bin, name + "-wrapper");
-            copyResourceTo(file, "hpux/parisc64/karaf-wrapper", false);
-            chmod(file, "a+x");
-
-            serviceFile = new File(bin, name + "-service");
-            copyFilteredResourceTo(serviceFile, "unix/karaf-service", props);
-            chmod(serviceFile, "a+x");
-
-            wrapperConf = new File(etc, name + "-wrapper.conf");
-            copyFilteredResourceTo(wrapperConf, "unix/karaf-wrapper.conf", props);
-
-            mkdir(lib);
-            copyResourceTo(new File(lib, "libwrapper.sl"), "hpux/parisc64/libwrapper.sl", false);
-        } else {
-            throw new IllegalStateException("Your operating system '" + os + "' is not currently supported.");
-        }
-
-        // install the wrapper jar to the lib directory
-        mkdir(lib);
-        copyResourceTo(new File(lib, "karaf-wrapper.jar"), "all/karaf-wrapper.jar", false);
-        mkdir(etc);
-
-        createJar(new File(lib, "karaf-wrapper-main.jar"), "org/apache/karaf/wrapper/internal/Main.class");
-
-        File[] wrapperPaths = new File[2];
-        wrapperPaths[0] = wrapperConf;
-        wrapperPaths[1] = serviceFile;
-
-        return wrapperPaths;
-    }
-
-    private void mkdir(File file) {
-        if (!file.exists()) {
-            LOGGER.info("Creating missing directory: {}", file.getPath());
-            System.out.println(Ansi.ansi().a("Creating missing directory: ")
-                    .a(Ansi.Attribute.INTENSITY_BOLD).a(file.getPath()).a(Ansi.Attribute.RESET).toString());
-            file.mkdirs();
-        }
-    }
-
-    private void copyResourceTo(File outFile, String resource, boolean text) throws Exception {
-        if (!outFile.exists()) {
-            LOGGER.info("Creating file: {}", outFile.getPath());
-            System.out.println(Ansi.ansi().a("Creating file: ")
-                    .a(Ansi.Attribute.INTENSITY_BOLD).a(outFile.getPath()).a(Ansi.Attribute.RESET).toString());
-            InputStream is = WrapperServiceImpl.class.getResourceAsStream(resource);
-            if (is == null) {
-                throw new IllegalArgumentException("Resource " + resource + " doesn't exist");
-            }
-            try {
-                if (text) {
-                    // read it line at a time so what we can use the platform line ending when we write it out
-                    PrintStream out = new PrintStream(new FileOutputStream(outFile));
-                    try {
-                        Scanner scanner = new Scanner(is);
-                        while (scanner.hasNextLine()) {
-                            String line = scanner.nextLine();
-                            LOGGER.info("writing: {}", line);
-                            out.println(line);
-                        }
-                    } finally {
-                        safeClose(out);
-                    }
-                } else {
-                    // binary resource so just write it out the way it came in
-                    FileOutputStream out = new FileOutputStream(outFile);
-                    try {
-                        int c = 0;
-                        while ((c = is.read()) >= 0) {
-                            out.write(c);
-                        }
-                    } finally {
-                        safeClose(out);
-                    }
-                }
-            } finally {
-                safeClose(is);
-            }
-        } else {
-            LOGGER.warn("File already exists. Move it out of the way if you wish to recreate it: {}", outFile.getPath());
-            System.out.println(Ansi.ansi()
-                    .fg(Ansi.Color.RED).a("File already exists").a(Ansi.Attribute.RESET)
-                    .a(". Move it out of the way if you wish to recreate it: ").a(outFile.getPath()).toString());
-        }
-    }
-
-    private void copyFilteredResourceTo(File outFile, String resource, HashMap<String, String> props) throws Exception {
-        if (!outFile.exists()) {
-            LOGGER.info("Creating file: {}", outFile.getPath());
-            System.out.println(Ansi.ansi().a("Creating file: ")
-                    .a(Ansi.Attribute.INTENSITY_BOLD).a(outFile.getPath()).a(Ansi.Attribute.RESET).toString());
-            InputStream is = WrapperServiceImpl.class.getResourceAsStream(resource);
-            if (is == null) {
-                throw new IllegalArgumentException("Resource " + resource + " doesn't exist");
-            }
-            try {
-                // read it line at a time so that we can use the platform line ending when we write it out
-                PrintStream out = new PrintStream(new FileOutputStream(outFile));
-                try {
-                    Scanner scanner = new Scanner(is);
-                    while (scanner.hasNextLine()) {
-                        String line = scanner.nextLine();
-                        line = filter(line, props);
-                        out.println(line);
-                    }
-                } finally {
-                    safeClose(out);
-                }
-            } finally {
-                safeClose(is);
-            }
-        } else {
-            LOGGER.warn("File already exists. Move it out of the way if you wish to recreate it: {}", outFile.getPath());
-            System.out.println(Ansi.ansi()
-                    .fg(Ansi.Color.RED).a("File already exists").a(Ansi.Attribute.RESET)
-                    .a(". Move it out of the way if you wish to recreate it: ").a(outFile.getPath()).toString());
-        }
-    }
-
-    private void safeClose(InputStream is) throws IOException {
-        if (is == null)
-            return;
-        try {
-            is.close();
-        } catch (Throwable ignore) {
-            // nothing to do
-        }
-    }
-
-    private void safeClose(OutputStream is) throws IOException {
-        if (is == null)
-            return;
-        try {
-            is.close();
-        } catch (Throwable ignore) {
-            // nothing to do
-        }
-    }
-
-    private String filter(String line, HashMap<String, String> props) {
-        for (Map.Entry<String, String> i : props.entrySet()) {
-            int p1 = line.indexOf(i.getKey());
-            if (p1 >= 0) {
-                String l1 = line.substring(0, p1);
-                String l2 = line.substring(p1 + i.getKey().length());
-                line = l1 + i.getValue() + l2;
-            }
-        }
-        return line;
-    }
-
-    private int chmod(File serviceFile, String mode) throws Exception {
-        ProcessBuilder builder = new ProcessBuilder();
-        builder.command("chmod", mode, serviceFile.getCanonicalPath());
-        Process p = builder.start();
-
-        PumpStreamHandler handler = new PumpStreamHandler(System.in, System.out, System.err);
-        handler.attach(p);
-        handler.start();
-        int status = p.waitFor();
-        handler.stop();
-        return status;
-    }
-
-    private void createJar(File outFile, String resource) throws Exception {
-        if (!outFile.exists()) {
-            LOGGER.info("Creating file: {}", outFile.getPath());
-            System.out.println(Ansi.ansi().a("Creating file: ")
-                    .a(Ansi.Attribute.INTENSITY_BOLD).a(outFile.getPath()).a(Ansi.Attribute.RESET).toString());
-            InputStream is = getClass().getClassLoader().getResourceAsStream(resource);
-            if (is == null) {
-                throw new IllegalStateException("Resource " + resource + " not found!");
-            }
-            try {
-                JarOutputStream jar = new JarOutputStream(new FileOutputStream(outFile));
-                int idx = resource.indexOf('/');
-                while (idx > 0) {
-                    jar.putNextEntry(new ZipEntry(resource.substring(0, idx)));
-                    jar.closeEntry();
-                    idx = resource.indexOf('/', idx + 1);
-                }
-                jar.putNextEntry(new ZipEntry(resource));
-                int c;
-                while ((c = is.read()) >= 0) {
-                    jar.write(c);
-                }
-                jar.closeEntry();
-                jar.close();
-            } finally {
-                safeClose(is);
-            }
-        }
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/4182735c/wrapper/core/src/main/java/org/apache/karaf/wrapper/internal/osgi/Activator.java
----------------------------------------------------------------------
diff --git a/wrapper/core/src/main/java/org/apache/karaf/wrapper/internal/osgi/Activator.java b/wrapper/core/src/main/java/org/apache/karaf/wrapper/internal/osgi/Activator.java
deleted file mode 100644
index 0cb8242..0000000
--- a/wrapper/core/src/main/java/org/apache/karaf/wrapper/internal/osgi/Activator.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * 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.karaf.wrapper.internal.osgi;
-
-import org.apache.karaf.util.tracker.BaseActivator;
-import org.apache.karaf.wrapper.WrapperService;
-import org.apache.karaf.wrapper.internal.WrapperServiceImpl;
-import org.apache.karaf.wrapper.management.internal.WrapperMBeanImpl;
-
-public class Activator extends BaseActivator {
-
-    @Override
-    protected void doStart() throws Exception {
-        WrapperService wrapperService = new WrapperServiceImpl();
-        register(WrapperService.class, wrapperService);
-
-        WrapperMBeanImpl wrapperMBean = new WrapperMBeanImpl();
-        wrapperMBean.setWrapperService(wrapperService);
-        registerMBean(wrapperMBean, "type=wrapper");
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/4182735c/wrapper/core/src/main/java/org/apache/karaf/wrapper/management/WrapperMBean.java
----------------------------------------------------------------------
diff --git a/wrapper/core/src/main/java/org/apache/karaf/wrapper/management/WrapperMBean.java b/wrapper/core/src/main/java/org/apache/karaf/wrapper/management/WrapperMBean.java
deleted file mode 100644
index 937bfe2..0000000
--- a/wrapper/core/src/main/java/org/apache/karaf/wrapper/management/WrapperMBean.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * 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.karaf.wrapper.management;
-
-import javax.management.MBeanException;
-import java.io.File;
-
-/**
- * Describe the WrapperMBean.
- */
-public interface WrapperMBean {
-
-    /**
-     * Install the service wrapper.
-     *
-     * @throws MBeanException in case of installation failure.
-     */
-    void install() throws MBeanException;
-
-    /**
-     * Install the service wrapper.
-     *
-     * @param name the service name.
-     * @param displayName the service display name.
-     * @param description the service description.
-     * @param startType the start type.
-     * @return the wrapper configuration (index 0) and service files (index 1).
-     * @throws MBeanException in case of installation failure.
-     */
-    File[] install(String name, String displayName, String description, String startType) throws MBeanException;
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/4182735c/wrapper/core/src/main/java/org/apache/karaf/wrapper/management/internal/WrapperMBeanImpl.java
----------------------------------------------------------------------
diff --git a/wrapper/core/src/main/java/org/apache/karaf/wrapper/management/internal/WrapperMBeanImpl.java b/wrapper/core/src/main/java/org/apache/karaf/wrapper/management/internal/WrapperMBeanImpl.java
deleted file mode 100644
index 1523015..0000000
--- a/wrapper/core/src/main/java/org/apache/karaf/wrapper/management/internal/WrapperMBeanImpl.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * 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.karaf.wrapper.management.internal;
-
-import org.apache.karaf.wrapper.WrapperService;
-import org.apache.karaf.wrapper.management.WrapperMBean;
-
-import javax.management.MBeanException;
-import javax.management.NotCompliantMBeanException;
-import javax.management.StandardMBean;
-import java.io.File;
-
-/**
- * Implementation of the wrapper MBean.
- */
-public class WrapperMBeanImpl extends StandardMBean implements WrapperMBean {
-
-    private WrapperService wrapperService;
-
-    public WrapperMBeanImpl() throws NotCompliantMBeanException {
-        super(WrapperMBean.class);
-    }
-
-    public void setWrapperService(WrapperService wrapperService) {
-        this.wrapperService = wrapperService;
-    }
-
-    public WrapperService getWrapperService() {
-        return this.wrapperService;
-    }
-
-    public void install() throws MBeanException {
-        try {
-            wrapperService.install();
-        } catch (Exception e) {
-            throw new MBeanException(null, e.getMessage());
-        }
-    }
-
-    public File[] install(String name, String displayName, String description, String startType) throws MBeanException {
-        try {
-            return wrapperService.install(name, displayName, description, startType);
-        } catch (Exception e) {
-            throw new MBeanException(null, e.getMessage());
-        }
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/4182735c/wrapper/core/src/main/resources/OSGI-INF/bundle.info
----------------------------------------------------------------------
diff --git a/wrapper/core/src/main/resources/OSGI-INF/bundle.info b/wrapper/core/src/main/resources/OSGI-INF/bundle.info
deleted file mode 100644
index 8462cc5..0000000
--- a/wrapper/core/src/main/resources/OSGI-INF/bundle.info
+++ /dev/null
@@ -1,16 +0,0 @@
-h1. Synopsis
-
-${project.name}
-
-${project.description}
-
-Maven URL:
-[mvn:${project.groupId}/${project.artifactId}/${project.version}]
-
-h1. Description
-
-This bundle provides support of the service wrapper, which allows for starting/stopping Karaf as a system service.
-
-h1. See also
-
-Service Wrapper - section of the Karaf User Guide


[53/59] [abbrv] [KARAF-2852] Merge region/core and region/command

Posted by gn...@apache.org.
http://git-wip-us.apache.org/repos/asf/karaf/blob/1bcdb173/region/src/main/java/org/apache/karaf/region/persist/internal/util/ManifestHeaderProcessor.java
----------------------------------------------------------------------
diff --git a/region/src/main/java/org/apache/karaf/region/persist/internal/util/ManifestHeaderProcessor.java b/region/src/main/java/org/apache/karaf/region/persist/internal/util/ManifestHeaderProcessor.java
new file mode 100644
index 0000000..410121c
--- /dev/null
+++ b/region/src/main/java/org/apache/karaf/region/persist/internal/util/ManifestHeaderProcessor.java
@@ -0,0 +1,661 @@
+/*
+ * 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.karaf.region.persist.internal.util;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.osgi.framework.Constants;
+
+public class ManifestHeaderProcessor
+{
+  public static final String NESTED_FILTER_ATTRIBUTE = "org.apache.aries.application.filter.attribute";
+  private static final Pattern FILTER_ATTR = Pattern.compile("(\\(!)?\\((.*?)([<>]?=)(.*?)\\)\\)?");
+  private static final String LESS_EQ_OP = "<=";
+  private static final String GREATER_EQ_OP = ">=";
+
+  /**
+   * A simple class to associate two types.
+   *
+   */
+  public static class NameValuePair {
+    private String name;
+    private Map<String,String> attributes;
+
+    public NameValuePair(String name, Map<String,String> value)
+    {
+      this.name = name;
+      this.attributes = value;
+    }
+    public String getName()
+    {
+      return name;
+    }
+    public void setName(String name)
+    {
+      this.name = name;
+    }
+
+    public Map<String,String> getAttributes()
+    {
+      return attributes;
+    }
+    public void setAttributes(Map<String,String> value)
+    {
+      this.attributes = value;
+    }
+
+    @Override
+    public String toString(){
+      return "{"+name.toString()+"::"+attributes.toString()+"}";
+    }
+    @Override
+    public int hashCode()
+    {
+      final int prime = 31;
+      int result = 1;
+      result = prime * result + ((name == null) ? 0 : name.hashCode());
+      result = prime * result + ((attributes == null) ? 0 : attributes.hashCode());
+      return result;
+    }
+    @Override
+    public boolean equals(Object obj)
+    {
+      if (this == obj) return true;
+      if (obj == null) return false;
+      if (getClass() != obj.getClass()) return false;
+      final NameValuePair other = (NameValuePair) obj;
+      if (name == null) {
+        if (other.name != null) return false;
+      } else if (!name.equals(other.name)) return false;
+      if (attributes == null) {
+    	  if (other.attributes != null) return false;
+      } else if (!attributes.equals(other.attributes)) return false;
+      return true;
+    }
+  }
+
+  /**
+   * Intended to provide a standard way to add Name/Value's to
+   * aggregations of Name/Value's.
+   *
+   */
+  public static interface NameValueCollection {
+    /**
+     * Add this Name & Value to the collection.
+     * @param n
+     * @param v
+     */
+    public void addToCollection(String n, Map<String,String> v);
+  }
+
+  /**
+   * Map of Name -> Value.
+   *
+   */
+  public static class NameValueMap extends HashMap<String, Map<String,String>> implements NameValueCollection, Map<String, Map<String,String>>{
+	private static final long serialVersionUID = -6446338858542599141L;
+
+	public void addToCollection(String n, Map<String,String> v){
+      this.put(n,v);
+    }
+
+	@Override
+	public String toString(){
+      StringBuilder sb = new StringBuilder();
+      sb.append("{");
+      boolean first=true;
+      for(Map.Entry<String, Map<String,String>> entry : this.entrySet()){
+        if(!first)sb.append(",");
+        first=false;
+        sb.append(entry.getKey()+"->"+entry.getValue());
+      }
+      sb.append("}");
+      return sb.toString();
+    }
+  }
+
+  /**
+   * List of Name/Value
+   *
+   */
+  public static class NameValueList extends ArrayList<NameValuePair> implements NameValueCollection, List<NameValuePair> {
+	private static final long serialVersionUID = 1808636823825029983L;
+
+	public void addToCollection(String n, Map<String,String> v){
+      this.add(new NameValuePair(n,v));
+    }
+	@Override
+    public String toString(){
+      StringBuffer sb = new StringBuffer();
+      sb.append("{");
+      boolean first = true;
+      for(NameValuePair nvp : this){
+        if(!first)sb.append(",");
+        first=false;
+        sb.append(nvp.toString());
+      }
+      sb.append("}");
+      return sb.toString();
+    }
+  }
+
+  /**
+   *
+   * Splits a delimiter separated string, tolerating presence of non separator commas
+   * within double quoted segments.
+   *
+   * Eg.
+   * com.ibm.ws.eba.helloWorldService;version="[1.0.0, 1.0.0]" &
+   * com.ibm.ws.eba.helloWorldService;version="1.0.0"
+   * com.ibm.ws.eba.helloWorld;version="2";bundle-version="[2,30)"
+   * com.acme.foo;weirdAttr="one;two;three";weirdDir:="1;2;3"
+   *  @param value          the value to be split
+   *  @param delimiter      the delimiter string such as ',' etc.
+   *  @return List<String>  the components of the split String in a list
+   */
+  public static List<String> split(String value, String delimiter)
+  {
+    return ManifestHeaderUtils.split(value, delimiter);
+  }
+
+
+  /**
+   * Internal method to parse headers with the format<p>
+   *   [Name](;[Name])*(;[attribute-name]=[attribute-value])*<br>
+   * Eg.<br>
+   *   rumplestiltskin;thing=value;other=something<br>
+   *   littleredridinghood
+   *   bundle1;bundle2;other=things
+   *   bundle1;bundle2
+   *
+   * @param s data to parse
+   * @return a list of NameValuePair, with the Name being the name component,
+   *         and the Value being a NameValueMap of key->value mappings.
+   */
+  private static List<NameValuePair> genericNameWithNameValuePairProcess(String s){
+    String name;
+    Map<String,String> params = null;
+    List<NameValuePair> nameValues = new ArrayList<NameValuePair>();
+    List<String> pkgs = new ArrayList<String>();
+    int index = s.indexOf(";");
+    if(index==-1){
+      name = s;
+      params = new HashMap<String, String>();
+      pkgs.add(name);
+    }else{
+      name = s.substring(0,index).trim();
+      String tail = s.substring(index+1).trim();
+
+      pkgs.add(name); // add the first package
+      StringBuilder parameters = new StringBuilder();
+
+
+      // take into consideration of multiple packages separated by ';'
+      // while they share the same attributes or directives
+      List<String> tailParts = split(tail, ";");
+      boolean firstParameter =false;
+
+      for (String part : tailParts) {
+        // if it is not a parameter and no parameter appears in front of it, it must a package
+        if (!!!(part.contains("=")))  {
+          // Need to make sure no parameter appears before the package, otherwise ignore this string
+          // as this syntax is invalid
+          if (!!!(firstParameter))
+            pkgs.add(part);
+        } else {
+          if (!!!(firstParameter))
+            firstParameter = true;
+
+          parameters.append(part + ";");
+        }
+      }
+
+      if (parameters.length() != 0) {
+        //remove the final ';' if there is one
+        if (parameters.toString().endsWith(";")) {
+
+          parameters = parameters.deleteCharAt(parameters.length() -1);
+        }
+
+        params = genericNameValueProcess(parameters.toString());
+      }
+
+    }
+    for (String pkg : pkgs) {
+      nameValues.add(new NameValuePair(pkg,params));
+    }
+
+    return nameValues;
+
+  }
+
+  /**
+   * Internal method to parse headers with the format<p>
+   *   [attribute-name]=[attribute-value](;[attribute-name]=[attribute-value])*<br>
+   * Eg.<br>
+   *   thing=value;other=something<br>
+   * <p>
+   * Note. Directives (name:=value) are represented in the map with name suffixed by ':'
+   *
+   * @param s data to parse
+   * @return a NameValueMap, with attribute-name -> attribute-value.
+   */
+  private static Map<String,String> genericNameValueProcess(String s){
+    Map<String,String> params = new HashMap<String,String>();
+    List<String> parameters = split(s, ";");
+    for(String parameter : parameters) {
+      List<String> parts = split(parameter,"=");
+      // do a check, otherwise we might get NPE
+      if (parts.size() ==2) {
+        String second = parts.get(1).trim();
+        if (second.startsWith("\"") && second.endsWith("\""))
+          second = second.substring(1,second.length()-1);
+
+        String first = parts.get(0).trim();
+
+        // make sure for directives we clear out any space as in "directive  :=value"
+        if (first.endsWith(":")) {
+            first = first.substring(0, first.length()-1).trim()+":";
+        }
+
+        params.put(first, second);
+      }
+    }
+
+    return params;
+  }
+
+  /**
+   * Processes an import/export style header.. <p>
+   *  pkg1;attrib=value;attrib=value,pkg2;attrib=value,pkg3;attrib=value
+   *
+   * @param out The collection to add each package name + attrib map to.
+   * @param s The data to parse
+   */
+  private static void genericImportExportProcess(NameValueCollection out, String s){
+    List<String> packages = split(s, ",");
+    for(String pkg : packages){
+      List<NameValuePair> ps = genericNameWithNameValuePairProcess(pkg);
+      for (NameValuePair p : ps) {
+        out.addToCollection(p.getName(), p.getAttributes());
+      }
+    }
+  }
+
+  /**
+   * Parse an export style header.<p>
+   *   pkg1;attrib=value;attrib=value,pkg2;attrib=value,pkg3;attrib=value2
+   * <p>
+   * Result is returned as a list, as export does allow duplicate package exports.
+   *
+   * @param s The data to parse.
+   * @return List of NameValuePairs, where each Name in the list is an exported package,
+   *         with its associated Value being a NameValueMap of any attributes declared.
+   */
+  public static List<NameValuePair> parseExportString(String s){
+    NameValueList retval = new NameValueList();
+    genericImportExportProcess(retval, s);
+    return retval;
+  }
+
+  /**
+   * Parse an export style header in a list.<p>
+   *   pkg1;attrib=value;attrib=value
+   *   pkg2;attrib=value
+   *   pkg3;attrib=value2
+   * <p>
+   * Result is returned as a list, as export does allow duplicate package exports.
+   *
+   * @param list The data to parse.
+   * @return List of NameValuePairs, where each Name in the list is an exported package,
+   *         with its associated Value being a NameValueMap of any attributes declared.
+   */
+  public static List<NameValuePair> parseExportList(List<String> list){
+    NameValueList retval = new NameValueList();
+    for(String pkg : list){
+      List<NameValuePair> ps = genericNameWithNameValuePairProcess(pkg);
+      for (NameValuePair p : ps) {
+        retval.addToCollection(p.getName(), p.getAttributes());
+      }
+    }
+    return retval;
+  }
+
+  /**
+   * Parse an import style header.<p>
+   *   pkg1;attrib=value;attrib=value,pkg2;attrib=value,pkg3;attrib=value
+   * <p>
+   * Result is returned as a set, as import does not allow duplicate package imports.
+   *
+   * @param s The data to parse.
+   * @return Map of NameValuePairs, where each Key in the Map is an imported package,
+   *         with its associated Value being a NameValueMap of any attributes declared.
+   */
+  public static Map<String, Map<String, String>> parseImportString(String s){
+    NameValueMap retval = new NameValueMap();
+    genericImportExportProcess(retval, s);
+    return retval;
+  }
+
+  /**
+   * Parse a bundle symbolic name.<p>
+   *   bundlesymbolicname;attrib=value;attrib=value
+   * <p>
+   *
+   * @param s The data to parse.
+   * @return NameValuePair with Name being the BundleSymbolicName,
+   *         and Value being any attribs declared for the name.
+   */
+  public static NameValuePair parseBundleSymbolicName(String s){
+    return genericNameWithNameValuePairProcess(s).get(0); // should just return the first one
+  }
+
+  /**
+   * Parse a version range..
+   *
+   * @param s
+   * @return VersionRange object.
+   * @throws IllegalArgumentException if the String could not be parsed as a VersionRange
+   */
+  public static VersionRange parseVersionRange(String s) throws IllegalArgumentException{
+    return new VersionRange(s);
+  }
+
+  /**
+   * Parse a version range and indicate if the version is an exact version
+   *
+   * @param s
+   * @param exactVersion
+   * @return VersionRange object.
+   * @throws IllegalArgumentException if the String could not be parsed as a VersionRange
+   */
+  public static VersionRange parseVersionRange(String s, boolean exactVersion) throws IllegalArgumentException{
+    return new VersionRange(s, exactVersion);
+  }
+
+  /**
+	 * Generate a filter from a set of attributes. This filter will be suitable
+	 * for presentation to OBR This means that, due to the way OBR works, it
+	 * will include a stanza of the form, (mandatory:<*mandatoryAttribute)
+	 * Filter strings generated by this method will therefore tend to break the
+	 * standard OSGi Filter class. The OBR stanza can be stripped out later if
+	 * required.
+	 *
+	 * @param attribs
+	 * @return filter string
+	 */
+	public static String generateFilter(Map<String, Object> attribs) {
+		StringBuilder filter = new StringBuilder("(&");
+		boolean realAttrib = false;
+		StringBuffer realAttribs = new StringBuffer();
+
+		if (attribs == null) {
+			attribs = new HashMap<String, Object>();
+		}
+
+		for (Map.Entry<String, Object> attrib : attribs.entrySet()) {
+			String attribName = attrib.getKey();
+
+			if (attribName.endsWith(":")) {
+				// skip all directives. It is used to affect the attribs on the
+				// filter xml.
+			} else if ((Constants.VERSION_ATTRIBUTE.equals(attribName))
+					|| (Constants.BUNDLE_VERSION_ATTRIBUTE.equals(attribName))) {
+				// version and bundle-version attrib requires special
+				// conversion.
+				realAttrib = true;
+
+				VersionRange vr = ManifestHeaderProcessor
+						.parseVersionRange(attrib.getValue().toString());
+
+				filter.append("(" + attribName + ">=" + vr.getMinimumVersion());
+
+				if (vr.getMaximumVersion() != null) {
+					filter.append(")(" + attribName + "<=");
+					filter.append(vr.getMaximumVersion());
+				}
+
+				if (vr.getMaximumVersion() != null && vr.isMinimumExclusive()) {
+					filter.append(")(!(" + attribName + "=");
+					filter.append(vr.getMinimumVersion());
+					filter.append(")");
+				}
+
+				if (vr.getMaximumVersion() != null && vr.isMaximumExclusive()) {
+					filter.append(")(!(" + attribName + "=");
+					filter.append(vr.getMaximumVersion());
+					filter.append(")");
+				}
+				filter.append(")");
+
+			} else if (NESTED_FILTER_ATTRIBUTE.equals(attribName)) {
+				// Filters go in whole, no formatting needed
+				realAttrib = true;
+				filter.append(attrib.getValue());
+
+			} else if (Constants.OBJECTCLASS.equals(attribName)) {
+				realAttrib = true;
+				// objectClass has a "," separated list of interfaces
+				String[] values = attrib.getValue().toString().split(",");
+				for (String s : values)
+					filter.append("(" + Constants.OBJECTCLASS + "=" + s + ")");
+
+			} else {
+				// attribName was not version..
+				realAttrib = true;
+
+				filter.append("(" + attribName + "=" + attrib.getValue() + ")");
+				// store all attributes in order to build up the mandatory
+				// filter and separate them with ", "
+				// skip bundle-symbolic-name in the mandatory directive query
+				if (!!!Constants.BUNDLE_SYMBOLICNAME_ATTRIBUTE
+						.equals(attribName)) {
+					realAttribs.append(attribName);
+					realAttribs.append(", ");
+				}
+			}
+		}
+//		/*
+//		 * The following is how OBR makes mandatory attributes work, we require
+//		 * that the set of mandatory attributes on the export is a subset of (or
+//		 * equal to) the set of the attributes we supply.
+//		 */
+//
+//		if (realAttribs.length() > 0) {
+//			String attribStr = (realAttribs.toString()).trim();
+//			// remove the final ,
+//			if ((attribStr.length() > 0) && (attribStr.endsWith(","))) {
+//				attribStr = attribStr.substring(0, attribStr.length() - 1);
+//			}
+//			// build the mandatory filter, e.g.(mandatory:&lt;*company, local)
+//			filter.append("(" + Constants.MANDATORY_DIRECTIVE + ":" + "<*"
+//					+ attribStr + ")");
+//		}
+
+		// Prune (& off the front and ) off end
+		String filterString = filter.toString();
+		int openBraces = 0;
+		for (int i = 0; openBraces < 3; i++) {
+			i = filterString.indexOf('(', i);
+			if (i == -1) {
+				break;
+			} else {
+				openBraces++;
+			}
+		}
+		if (openBraces < 3 && filterString.length() > 2) {
+			filter.delete(0, 2);
+		} else {
+			filter.append(")");
+		}
+
+		String result = "";
+		if (realAttrib != false) {
+			result = filter.toString();
+		}
+		return result;
+	}
+
+	/**
+   * Generate a filter from a set of attributes. This filter will be suitable
+   * for presentation to OBR. This means that, due to the way OBR works, it will
+   * include a stanza of the form, (mandatory:<*mandatoryAttribute) Filter
+   * strings generated by this method will therefore tend to break the standard
+   * OSGi Filter class. The OBR stanza can be stripped out later if required.
+   *
+   * We may wish to consider relocating this method since VersionRange has its
+   * own top level class.
+   *
+   * @param type
+   * @param name
+   * @param attribs
+   * @return filter string
+   */
+  public static String generateFilter(String type, String name,
+      Map<String, Object> attribs) {
+    StringBuffer filter = new StringBuffer();
+    String result;
+    // shortcut for the simple case with no attribs.
+
+    if (attribs == null || attribs.isEmpty())
+      filter.append("(" + type + "=" + name + ")");
+    else {
+      // process all the attribs passed.
+      // find out whether there are attributes on the filter
+
+      filter.append("(&(" + type + "=" + name + ")");
+
+      String filterString = generateFilter(attribs);
+
+      int start = 0;
+      int end = filterString.length();
+      if (filterString.startsWith("(&")) {
+        start = 2;
+        end--;
+      }
+
+      if ("".equals(filterString)) {
+        filter.delete(0, 2);
+      } else {
+        filter.append(filterString, start, end);
+        filter.append(")");
+      }
+    }
+
+    result = filter.toString();
+
+    return result;
+  }
+
+  private static Map<String, String> parseFilterList(String filter) {
+
+    Map<String, String> result = new HashMap<String, String>();
+    Set<String> negatedVersions = new HashSet<String>();
+    Set<String> negatedBundleVersions = new HashSet<String>();
+
+    String lowerVersion = null;
+    String upperVersion = null;
+    String lowerBundleVersion = null;
+    String upperBundleVersion = null;
+
+    Matcher m = FILTER_ATTR.matcher(filter);
+    while (m.find()) {
+      boolean negation = m.group(1) != null;
+      String attr = m.group(2);
+      String op = m.group(3);
+      String value = m.group(4);
+
+      if (Constants.VERSION_ATTRIBUTE.equals(attr)) {
+        if (negation) {
+          negatedVersions.add(value);
+        } else {
+          if (GREATER_EQ_OP.equals(op))
+            lowerVersion = value;
+          else if (LESS_EQ_OP.equals(op))
+            upperVersion = value;
+          else
+            throw new IllegalArgumentException();
+        }
+      } else if (Constants.BUNDLE_VERSION_ATTRIBUTE.equals(attr)) {
+        // bundle-version is like version, but may be specified at the
+        // same time
+        // therefore we have similar code with separate variables
+        if (negation) {
+          negatedBundleVersions.add(value);
+        } else {
+          if (GREATER_EQ_OP.equals(op))
+            lowerBundleVersion = value;
+          else if (LESS_EQ_OP.equals(op))
+            upperBundleVersion = value;
+          else
+            throw new IllegalArgumentException();
+        }
+      } else {
+        result.put(attr, value);
+      }
+    }
+
+    if (lowerVersion != null) {
+      StringBuilder versionAttr = new StringBuilder(lowerVersion);
+      if (upperVersion != null) {
+        versionAttr.append(",").append(upperVersion).insert(0,
+            negatedVersions.contains(lowerVersion) ? '(' : '[').append(
+            negatedVersions.contains(upperVersion) ? ')' : ']');
+      }
+
+      result.put(Constants.VERSION_ATTRIBUTE, versionAttr.toString());
+    }
+    // Do it again for bundle-version
+    if (lowerBundleVersion != null) {
+      StringBuilder versionAttr = new StringBuilder(lowerBundleVersion);
+      if (upperBundleVersion != null) {
+        versionAttr.append(",").append(upperBundleVersion).insert(0,
+            negatedBundleVersions.contains(lowerBundleVersion) ? '(' : '[')
+            .append(
+                negatedBundleVersions.contains(upperBundleVersion) ? ')' : ']');
+      }
+
+      result.put(Constants.BUNDLE_VERSION_ATTRIBUTE, versionAttr.toString());
+    }
+
+    return result;
+  }
+
+  public static Map<String,String> parseFilter(String filter)
+  {
+    Map<String,String> result;
+    if (filter.startsWith("(&")) {
+      result = parseFilterList(filter.substring(2, filter.length()-1));
+    } else {
+      result = parseFilterList(filter);
+    }
+    return result;
+  }
+
+}
+

http://git-wip-us.apache.org/repos/asf/karaf/blob/1bcdb173/region/src/main/java/org/apache/karaf/region/persist/internal/util/ManifestHeaderUtils.java
----------------------------------------------------------------------
diff --git a/region/src/main/java/org/apache/karaf/region/persist/internal/util/ManifestHeaderUtils.java b/region/src/main/java/org/apache/karaf/region/persist/internal/util/ManifestHeaderUtils.java
new file mode 100644
index 0000000..8c87616
--- /dev/null
+++ b/region/src/main/java/org/apache/karaf/region/persist/internal/util/ManifestHeaderUtils.java
@@ -0,0 +1,85 @@
+/*
+ * 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.karaf.region.persist.internal.util;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class ManifestHeaderUtils {
+
+     /**
+     *
+     * Splits a delimiter separated string, tolerating presence of non separator commas
+     * within double quoted segments.
+     *
+     * Eg.
+     * com.ibm.ws.eba.helloWorldService;version="[1.0.0, 1.0.0]" &
+     * com.ibm.ws.eba.helloWorldService;version="1.0.0"
+     * com.ibm.ws.eba.helloWorld;version="2";bundle-version="[2,30)"
+     * com.acme.foo;weirdAttr="one;two;three";weirdDir:="1;2;3"
+     *  @param value          the value to be split
+     *  @param delimiter      the delimiter string such as ',' etc.
+     *  @return List<String>  the components of the split String in a list
+     */
+    public static List<String> split(String value, String delimiter)
+    {
+      List<String> result = new ArrayList<String>();
+      if (value != null) {
+        String[] packages = value.split(delimiter);
+
+        for (int i = 0; i < packages.length; ) {
+          String tmp = packages[i++].trim();
+          // if there is a odd number of " in a string, we need to append
+          while (count(tmp, "\"") % 2 != 0) {
+            // check to see if we need to append the next package[i++]
+              if (i<packages.length)
+                tmp = tmp + delimiter + packages[i++].trim();
+              else
+                // oops. The double quotes are not paired up. We have reached to the end of the string.
+                throw new IllegalArgumentException("Unmatched double quotes: " + tmp);
+          }
+
+          result.add(tmp);
+
+        }
+      }
+      return result;
+    }
+
+    /**
+     * count the number of characters in a string
+     * @param parent The string to be searched
+     * @param subString The substring to be found
+     * @return the number of occurrence of the subString
+     */
+     private static int count(String parent, String subString) {
+
+       int count = 0 ;
+       int i = parent.indexOf(subString);
+       while (i > -1) {
+         if (parent.length() >= i+1)
+           parent = parent.substring(i+1);
+         count ++;
+         i = parent.indexOf(subString);
+       }
+       return count;
+     }
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/1bcdb173/region/src/main/java/org/apache/karaf/region/persist/internal/util/VersionRange.java
----------------------------------------------------------------------
diff --git a/region/src/main/java/org/apache/karaf/region/persist/internal/util/VersionRange.java b/region/src/main/java/org/apache/karaf/region/persist/internal/util/VersionRange.java
new file mode 100644
index 0000000..19bbc77
--- /dev/null
+++ b/region/src/main/java/org/apache/karaf/region/persist/internal/util/VersionRange.java
@@ -0,0 +1,456 @@
+/*
+ * 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.karaf.region.persist.internal.util;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.osgi.framework.Version;
+
+public final class VersionRange {
+
+    /** A string representation of the version. */
+    private String version;
+
+    /** The minimum desired version for the bundle */
+    private Version minimumVersion;
+
+    /** The maximum desired version for the bundle */
+    private Version maximumVersion;
+
+    /** True if the match is exclusive of the minimum version */
+    private boolean minimumExclusive;
+
+    /** True if the match is exclusive of the maximum version */
+    private boolean maximumExclusive;
+
+    /** A regexp to select the version */
+    private static final Pattern versionCapture = Pattern.compile("\"?(.*?)\"?$");
+
+    /**
+     *
+     * @param version
+     *            version for the verioninfo
+     */
+    public VersionRange(String version) {
+        this.version = version;
+        processVersionAttribute(version);
+    }
+
+    /**
+     * This method should be used to create a version range from a single
+     * version string.
+     * @param version
+     *            version for the versioninfo
+     * @param exactVersion
+     *            whether this is an exact version {@code true} or goes to infinity
+     *            {@code false}
+     */
+    public VersionRange(String version, boolean exactVersion) {
+
+        if (exactVersion) {
+            // Do not store this string as it might be just a version, or a range!
+            processExactVersionAttribute(version);
+        } else {
+            this.version = version;
+            processVersionAttribute(this.version);
+        }
+
+        assertInvariants();
+    }
+
+    /**
+     * Constructor designed for internal use only.
+     *
+     * @param maximumVersion
+     * @param maximumExclusive
+     * @param minimumVersion
+     * @param minimumExclusive
+     * @throws IllegalArgumentException
+     *             if parameters are not valid.
+     */
+    private VersionRange(Version maximumVersion,
+                         boolean maximumExclusive,
+                         Version minimumVersion,
+                         boolean minimumExclusive) {
+        this.maximumVersion = maximumVersion;
+        this.maximumExclusive = maximumExclusive;
+        this.minimumVersion = minimumVersion;
+        this.minimumExclusive = minimumExclusive;
+
+        assertInvariants();
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see org.apache.aries.application.impl.VersionRange#toString()
+     */
+    @Override
+    public String toString() {
+        // Some constructors don't take in a string that we can return directly,
+        // so construct one if needed
+        if (version == null) {
+            if (maximumVersion == null) {
+                version = minimumVersion.toString();
+            } else {
+                version = (minimumExclusive ? "(" : "[") + minimumVersion + "," + maximumVersion
+                          + (maximumExclusive ? ")" : "]");
+            }
+        }
+        return this.version;
+    }
+
+    @Override
+    public int hashCode() {
+        int result = 17;
+        result = 31 * result + minimumVersion.hashCode();
+        result = 31 * result + (minimumExclusive ? 1 : 0);
+        result = 31 * result + (maximumVersion != null ? maximumVersion.hashCode() : 0);
+        result = 31 * result + (maximumExclusive ? 1 : 0);
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object other) {
+        boolean result = false;
+        if (this == other) {
+            result = true;
+        } else if (other instanceof VersionRange) {
+            VersionRange vr = (VersionRange) other;
+            result = minimumVersion.equals(vr.minimumVersion)
+                     && minimumExclusive == vr.minimumExclusive
+                     && (maximumVersion == null ? vr.maximumVersion == null : maximumVersion
+                             .equals(vr.maximumVersion)) && maximumExclusive == vr.maximumExclusive;
+        }
+
+        return result;
+    }
+
+    /**
+     * this method returns the exact version from the versionInfo obj.
+     * this is used for DeploymentContent only to return a valid exact version
+     * otherwise, null is returned.
+     * @return the exact version
+     */
+    public Version getExactVersion() {
+        Version v = null;
+        if (isExactVersion()) {
+            v = getMinimumVersion();
+        }
+        return v;
+    }
+
+    /**
+     * get the maximum version
+     * @return    the maximum version
+     */
+    public Version getMaximumVersion() {
+        return maximumVersion;
+    }
+
+    /**
+     * get the minimum version
+     * @return    the minimum version
+     */
+    public Version getMinimumVersion() {
+        return minimumVersion;
+    }
+
+    /**
+     * is the maximum version exclusive
+     * @return is the max version in the range.
+     */
+    public boolean isMaximumExclusive() {
+        return maximumExclusive;
+    }
+
+    /**
+     * is the maximum version unbounded
+     * @return true if no upper bound was specified.
+     */
+    public boolean isMaximumUnbounded() {
+        boolean unbounded = maximumVersion == null;
+        return unbounded;
+    }
+
+    /**
+     * is the minimum version exclusive
+     * @return true if the min version is in range.
+     */
+    public boolean isMinimumExclusive() {
+        return minimumExclusive;
+    }
+
+    /**
+     * this is designed for deployed-version as that is the exact version.
+     *
+     * @param version
+     * @return
+     * @throws IllegalArgumentException
+     */
+    private boolean processExactVersionAttribute(String version) throws IllegalArgumentException {
+        boolean success = processVersionAttribute(version);
+
+        if (maximumVersion == null) {
+            maximumVersion = minimumVersion;
+        }
+
+        if (!minimumVersion.equals(maximumVersion)) {
+            throw new IllegalArgumentException("Version is not exact: " + version);
+        }
+
+        if (!!!isExactVersion()) {
+            throw new IllegalArgumentException("Version is not exact: " + version);
+        }
+
+        return success;
+    }
+
+    /**
+     * process the version attribute,
+     *
+     * @param version
+     *            the value to be processed
+     * @return
+     * @throws IllegalArgumentException
+     */
+    private boolean processVersionAttribute(String version) throws IllegalArgumentException {
+        boolean success = false;
+
+        if (version == null) {
+            throw new IllegalArgumentException("Version is null");
+        }
+
+        Matcher matches = versionCapture.matcher(version);
+
+        if (matches.matches()) {
+            String versions = matches.group(1);
+
+            if ((versions.startsWith("[") || versions.startsWith("("))
+                && (versions.endsWith("]") || versions.endsWith(")"))) {
+                if (versions.startsWith("["))
+                    minimumExclusive = false;
+                else if (versions.startsWith("("))
+                    minimumExclusive = true;
+
+                if (versions.endsWith("]"))
+                    maximumExclusive = false;
+                else if (versions.endsWith(")"))
+                    maximumExclusive = true;
+
+                int index = versions.indexOf(',');
+                String minVersion = versions.substring(1, index);
+                String maxVersion = versions.substring(index + 1, versions.length() - 1);
+
+                try {
+                    minimumVersion = new Version(minVersion.trim());
+                    maximumVersion = new Version(maxVersion.trim());
+                    success = true;
+                } catch (NumberFormatException nfe) {
+                    throw new IllegalArgumentException("Version cannot be decoded: " + version, nfe);
+                }
+            } else {
+                try {
+                    if (versions.trim().length() == 0)
+                        minimumVersion = new Version(0, 0, 0);
+                    else
+                        minimumVersion = new Version(versions.trim());
+                    success = true;
+                } catch (NumberFormatException nfe) {
+                    throw new IllegalArgumentException("Version cannot be decoded: " + version, nfe);
+                }
+            }
+        } else {
+            throw new IllegalArgumentException("Version cannot be decoded: " + version);
+        }
+
+        return success;
+    }
+
+    /**
+     * Assert object invariants. Called by constructors to verify that arguments
+     * were valid.
+     *
+     * @throws IllegalArgumentException
+     *             if invariants are violated.
+     */
+    private void assertInvariants() {
+        if (minimumVersion == null
+            || !isRangeValid(minimumVersion, minimumExclusive, maximumVersion, maximumExclusive)) {
+            IllegalArgumentException e = new IllegalArgumentException();
+            throw e;
+        }
+    }
+
+    /**
+     * Check if the supplied parameters describe a valid version range.
+     *
+     * @param min
+     *            the minimum version.
+     * @param minExclusive
+     *            whether the minimum version is exclusive.
+     * @param max
+     *            the maximum version.
+     * @param maxExclusive
+     *            whether the maximum version is exclusive.
+     * @return true is the range is valid; otherwise false.
+     */
+    private boolean isRangeValid(Version min,
+                                 boolean minExclusive,
+                                 Version max,
+                                 boolean maxExclusive) {
+        boolean result;
+
+        // A null maximum version is unbounded so means that minimum is smaller
+        // than
+        // maximum.
+        int minMaxCompare = (max == null ? -1 : min.compareTo(max));
+        if (minMaxCompare > 0) {
+            // Minimum larger than maximum is invalid.
+            result = false;
+        } else if (minMaxCompare == 0 && (minExclusive || maxExclusive)) {
+            // If min and max are the same, and either are exclusive, no valid
+            // range
+            // exists.
+            result = false;
+        } else {
+            // Range is valid.
+            result = true;
+        }
+
+        return result;
+    }
+
+    /**
+     * This method checks that the provided version matches the desired version.
+     *
+     * @param version
+     *            the version.
+     * @return true if the version matches, false otherwise.
+     */
+    public boolean matches(Version version) {
+        boolean result;
+        if (this.getMaximumVersion() == null) {
+            result = this.getMinimumVersion().compareTo(version) <= 0;
+        } else {
+            int minN = this.isMinimumExclusive() ? 0 : 1;
+            int maxN = this.isMaximumExclusive() ? 0 : 1;
+
+            result = (this.getMinimumVersion().compareTo(version) < minN)
+                     && (version.compareTo(this.getMaximumVersion()) < maxN);
+        }
+        return result;
+    }
+
+    /**
+     * check if the versioninfo is the exact version
+     * @return true if the range will match 1 exact version.
+     */
+    public boolean isExactVersion() {
+        return minimumVersion.equals(maximumVersion) && minimumExclusive == maximumExclusive
+               && !!!minimumExclusive;
+    }
+
+    /**
+     * Create a new version range that is the intersection of {@code this} and the argument.
+     * In other words, the largest version range that lies within both {@code this} and
+     * the parameter.
+     * @param r a version range to be intersected with {@code this}.
+     * @return a new version range, or {@code null} if no intersection is possible.
+     */
+    public VersionRange intersect(VersionRange r) {
+        // Use the highest minimum version.
+        final Version newMinimumVersion;
+        final boolean newMinimumExclusive;
+        int minCompare = minimumVersion.compareTo(r.getMinimumVersion());
+        if (minCompare > 0) {
+            newMinimumVersion = minimumVersion;
+            newMinimumExclusive = minimumExclusive;
+        } else if (minCompare < 0) {
+            newMinimumVersion = r.getMinimumVersion();
+            newMinimumExclusive = r.isMinimumExclusive();
+        } else {
+            newMinimumVersion = minimumVersion;
+            newMinimumExclusive = (minimumExclusive || r.isMinimumExclusive());
+        }
+
+        // Use the lowest maximum version.
+        final Version newMaximumVersion;
+        final boolean newMaximumExclusive;
+        // null maximum version means unbounded, so the highest possible value.
+        if (maximumVersion == null) {
+            newMaximumVersion = r.getMaximumVersion();
+            newMaximumExclusive = r.isMaximumExclusive();
+        } else if (r.getMaximumVersion() == null) {
+            newMaximumVersion = maximumVersion;
+            newMaximumExclusive = maximumExclusive;
+        } else {
+            int maxCompare = maximumVersion.compareTo(r.getMaximumVersion());
+            if (maxCompare < 0) {
+                newMaximumVersion = maximumVersion;
+                newMaximumExclusive = maximumExclusive;
+            } else if (maxCompare > 0) {
+                newMaximumVersion = r.getMaximumVersion();
+                newMaximumExclusive = r.isMaximumExclusive();
+            } else {
+                newMaximumVersion = maximumVersion;
+                newMaximumExclusive = (maximumExclusive || r.isMaximumExclusive());
+            }
+        }
+
+        VersionRange result;
+        if (isRangeValid(newMinimumVersion, newMinimumExclusive, newMaximumVersion,
+                newMaximumExclusive)) {
+            result = new VersionRange(newMaximumVersion, newMaximumExclusive, newMinimumVersion,
+                    newMinimumExclusive);
+        } else {
+            result = null;
+        }
+        return result;
+    }
+
+    /**
+     * Parse a version range..
+     *
+     * @param s
+     * @return VersionRange object.
+     * @throws IllegalArgumentException
+     *             if the String could not be parsed as a VersionRange
+     */
+    public static VersionRange parseVersionRange(String s) throws IllegalArgumentException {
+        return new VersionRange(s);
+    }
+
+    /**
+     * Parse a version range and indicate if the version is an exact version
+     *
+     * @param s
+     * @param exactVersion
+     * @return VersionRange object.
+     * @throws IllegalArgumentException
+     *             if the String could not be parsed as a VersionRange
+     */
+    public static VersionRange parseVersionRange(String s, boolean exactVersion)
+            throws IllegalArgumentException {
+        return new VersionRange(s, exactVersion);
+    }
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/1bcdb173/region/src/main/resources/org/apache/karaf/region/persist/region.xsd
----------------------------------------------------------------------
diff --git a/region/src/main/resources/org/apache/karaf/region/persist/region.xsd b/region/src/main/resources/org/apache/karaf/region/persist/region.xsd
new file mode 100644
index 0000000..8ca26e7
--- /dev/null
+++ b/region/src/main/resources/org/apache/karaf/region/persist/region.xsd
@@ -0,0 +1,109 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+    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.
+-->
+
+<!-- $Rev$ $Date$ -->
+
+<xsd:schema xmlns="http://karaf.apache.org/xmlns/region/v1.0.0"
+        xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+        targetNamespace="http://karaf.apache.org/xmlns/region/v1.0.0"
+        elementFormDefault="qualified"
+        attributeFormDefault="unqualified">
+
+
+    <xsd:annotation>
+        <xsd:documentation>
+            Defines the configuration elements for Apache Karaf region xml configuration.
+        </xsd:documentation>
+    </xsd:annotation>
+
+    <xsd:element name="regions" type="regionsType"/>
+
+
+    <xsd:complexType name="regionsType">
+        <xsd:annotation>
+            <xsd:documentation>
+                Regions element
+            </xsd:documentation>
+        </xsd:annotation>
+        <xsd:sequence>
+            <xsd:element name="region" type="regionType" minOccurs="0" maxOccurs="unbounded"/>
+            <xsd:element name="filter" type="filterType" minOccurs="0" maxOccurs="unbounded"/>
+        </xsd:sequence>
+    </xsd:complexType>
+
+    <xsd:complexType name="regionType">
+        <xsd:annotation>
+            <xsd:documentation>
+                Region element
+            </xsd:documentation>
+        </xsd:annotation>
+        <xsd:sequence>
+            <xsd:element name="bundle" type="regionBundleType" minOccurs="0" maxOccurs="unbounded"/>
+        </xsd:sequence>
+        <xsd:attribute name="name" type="xsd:string" use="required"/>
+    </xsd:complexType>
+
+
+    <xsd:complexType name="regionBundleType">
+        <xsd:sequence/>
+        <xsd:attribute name="id" type="xsd:long"/>
+        <xsd:attribute name="location" type="xsd:string"/>
+    </xsd:complexType>
+
+    <xsd:complexType name="filterBundleType">
+        <xsd:sequence>
+            <xsd:element name="attribute" type="filterAttributeType" minOccurs="0" maxOccurs="unbounded"/>
+        </xsd:sequence>
+        <xsd:attribute name="id" type="xsd:long"/>
+        <xsd:attribute name="symbolic-name" type="xsd:string"/>
+        <xsd:attribute name="version" type="xsd:string"/>
+    </xsd:complexType>
+
+    <xsd:complexType name="filterType">
+        <xsd:sequence>
+            <xsd:element name="bundle" type="filterBundleType" minOccurs="0" maxOccurs="unbounded"/>
+            <xsd:element name="package" type="filterPackageType" minOccurs="0" maxOccurs="unbounded"/>
+            <xsd:element name="namespace" type="filterNamespaceType" minOccurs="0" maxOccurs="unbounded"/>
+        </xsd:sequence>
+        <xsd:attribute name="from" type="xsd:string" use="required"/>
+        <xsd:attribute name="to" type="xsd:string" use="required"/>
+    </xsd:complexType>
+
+    <xsd:complexType name="filterPackageType">
+        <xsd:sequence>
+            <xsd:element name="attribute" type="filterAttributeType" minOccurs="0" maxOccurs="unbounded"/>
+        </xsd:sequence>
+        <xsd:attribute name="name" type="xsd:string" use="required"/>
+        <xsd:attribute name="version" type="xsd:string"/>
+    </xsd:complexType>
+
+    <xsd:complexType name="filterAttributeType">
+        <xsd:sequence/>
+        <xsd:attribute name="name" type="xsd:string" use="required"/>
+        <xsd:attribute name="value" type="xsd:string" use="required"/>
+    </xsd:complexType>
+
+    <xsd:complexType name="filterNamespaceType">
+        <xsd:sequence>
+            <xsd:element name="attribute" type="filterAttributeType" minOccurs="0" maxOccurs="unbounded"/>
+        </xsd:sequence>
+        <xsd:attribute name="name" type="xsd:string" use="required"/>
+    </xsd:complexType>
+</xsd:schema>


[30/59] [abbrv] git commit: [KARAF-2852] Merge instance/core and instance/command

Posted by gn...@apache.org.
[KARAF-2852] Merge instance/core and instance/command

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

Branch: refs/heads/master
Commit: 7c2db062584b2b15afc5bf1727e2f477feac2877
Parents: d33e095
Author: Guillaume Nodet <gn...@gmail.com>
Authored: Wed Apr 9 22:17:39 2014 +0200
Committer: Guillaume Nodet <gn...@gmail.com>
Committed: Thu Apr 10 16:00:16 2014 +0200

----------------------------------------------------------------------
 .../standard/src/main/feature/feature.xml       |    1 -
 instance/NOTICE                                 |   71 ++
 instance/command/NOTICE                         |   71 --
 instance/command/pom.xml                        |  129 --
 .../instance/command/ChangeOptsCommand.java     |   41 -
 .../command/ChangeRmiRegistryPortCommand.java   |   41 -
 .../command/ChangeRmiServerPortCommand.java     |   41 -
 .../instance/command/ChangeSshPortCommand.java  |   41 -
 .../karaf/instance/command/CloneCommand.java    |   66 -
 .../karaf/instance/command/ConnectCommand.java  |   78 --
 .../karaf/instance/command/CreateCommand.java   |   74 --
 .../karaf/instance/command/DestroyCommand.java  |   41 -
 .../command/InstanceCommandSupport.java         |   51 -
 .../karaf/instance/command/ListCommand.java     |   81 --
 .../karaf/instance/command/RenameCommand.java   |   45 -
 .../karaf/instance/command/StartCommand.java    |   76 --
 .../karaf/instance/command/StatusCommand.java   |   40 -
 .../karaf/instance/command/StopCommand.java     |   38 -
 .../command/completers/InstanceCompleter.java   |   52 -
 .../org/apache/karaf/instance/main/Execute.java |  171 ---
 .../services/org/apache/karaf/shell/commands    |   30 -
 .../src/main/resources/OSGI-INF/bundle.info     |   29 -
 .../instance/command/CreateCommandTest.java     |   57 -
 .../apache/karaf/instance/main/ExecuteTest.java |  126 --
 instance/core/NOTICE                            |   71 --
 instance/core/pom.xml                           |  181 ---
 .../apache/karaf/instance/core/Instance.java    |   66 -
 .../karaf/instance/core/InstanceService.java    |   33 -
 .../karaf/instance/core/InstanceSettings.java   |   97 --
 .../karaf/instance/core/InstancesMBean.java     |   55 -
 .../instance/core/internal/InstanceImpl.java    |  110 --
 .../core/internal/InstanceServiceImpl.java      | 1166 ------------------
 .../core/internal/InstanceToTableMapper.java    |   83 --
 .../core/internal/InstancesMBeanImpl.java       |  224 ----
 .../instance/core/internal/osgi/Activator.java  |   35 -
 .../main/java/org/apache/karaf/jpm/Process.java |   47 -
 .../org/apache/karaf/jpm/ProcessBuilder.java    |   59 -
 .../apache/karaf/jpm/ProcessBuilderFactory.java |   25 -
 .../jpm/impl/ProcessBuilderFactoryImpl.java     |   27 -
 .../karaf/jpm/impl/ProcessBuilderImpl.java      |   48 -
 .../org/apache/karaf/jpm/impl/ProcessImpl.java  |  155 ---
 .../org/apache/karaf/jpm/impl/ScriptUtils.java  |  128 --
 .../src/main/resources/OSGI-INF/bundle.info     |   36 -
 .../apache/karaf/instance/resources/bin/karaf   |   25 -
 .../karaf/instance/resources/bin/karaf.bat      |   25 -
 .../apache/karaf/instance/resources/bin/start   |   25 -
 .../karaf/instance/resources/bin/start.bat      |   24 -
 .../apache/karaf/instance/resources/bin/stop    |   25 -
 .../karaf/instance/resources/bin/stop.bat       |   24 -
 .../etc/org.apache.karaf.management.cfg         |   63 -
 .../resources/etc/org.apache.karaf.shell.cfg    |   75 --
 .../instance/resources/etc/system.properties    |  120 --
 .../org/apache/karaf/jpm/impl/unix/start.sh     |   29 -
 .../apache/karaf/jpm/impl/windows/destroy.vbs   |   27 -
 .../apache/karaf/jpm/impl/windows/running.vbs   |   26 -
 .../org/apache/karaf/jpm/impl/windows/start.vbs |   34 -
 .../instance/core/InstanceSettingsTest.java     |   58 -
 .../core/internal/InstanceServiceImplTest.java  |  187 ---
 .../internal/InstanceServiceMBeanImplTest.java  |  239 ----
 .../internal/InstanceToTableMapperTest.java     |   90 --
 .../java/org/apache/karaf/jpm/MainTest.java     |   24 -
 .../java/org/apache/karaf/jpm/ProcessTest.java  |   69 --
 .../src/test/resources/etc/startup.properties   |   20 -
 instance/pom.xml                                |  175 ++-
 .../instance/command/ChangeOptsCommand.java     |   41 +
 .../command/ChangeRmiRegistryPortCommand.java   |   41 +
 .../command/ChangeRmiServerPortCommand.java     |   41 +
 .../instance/command/ChangeSshPortCommand.java  |   41 +
 .../karaf/instance/command/CloneCommand.java    |   66 +
 .../karaf/instance/command/ConnectCommand.java  |   78 ++
 .../karaf/instance/command/CreateCommand.java   |   74 ++
 .../karaf/instance/command/DestroyCommand.java  |   41 +
 .../command/InstanceCommandSupport.java         |   51 +
 .../karaf/instance/command/ListCommand.java     |   81 ++
 .../karaf/instance/command/RenameCommand.java   |   45 +
 .../karaf/instance/command/StartCommand.java    |   76 ++
 .../karaf/instance/command/StatusCommand.java   |   40 +
 .../karaf/instance/command/StopCommand.java     |   38 +
 .../command/completers/InstanceCompleter.java   |   52 +
 .../apache/karaf/instance/core/Instance.java    |   66 +
 .../karaf/instance/core/InstanceService.java    |   33 +
 .../karaf/instance/core/InstanceSettings.java   |   97 ++
 .../karaf/instance/core/InstancesMBean.java     |   55 +
 .../instance/core/internal/InstanceImpl.java    |  110 ++
 .../core/internal/InstanceServiceImpl.java      | 1166 ++++++++++++++++++
 .../core/internal/InstanceToTableMapper.java    |   83 ++
 .../core/internal/InstancesMBeanImpl.java       |  224 ++++
 .../instance/core/internal/osgi/Activator.java  |   35 +
 .../org/apache/karaf/instance/main/Execute.java |  171 +++
 .../main/java/org/apache/karaf/jpm/Process.java |   47 +
 .../org/apache/karaf/jpm/ProcessBuilder.java    |   59 +
 .../apache/karaf/jpm/ProcessBuilderFactory.java |   25 +
 .../jpm/impl/ProcessBuilderFactoryImpl.java     |   27 +
 .../karaf/jpm/impl/ProcessBuilderImpl.java      |   48 +
 .../org/apache/karaf/jpm/impl/ProcessImpl.java  |  155 +++
 .../org/apache/karaf/jpm/impl/ScriptUtils.java  |  128 ++
 .../services/org/apache/karaf/shell/commands    |   30 +
 .../src/main/resources/OSGI-INF/bundle.info     |   36 +
 .../apache/karaf/instance/resources/bin/karaf   |   25 +
 .../karaf/instance/resources/bin/karaf.bat      |   25 +
 .../apache/karaf/instance/resources/bin/start   |   25 +
 .../karaf/instance/resources/bin/start.bat      |   24 +
 .../apache/karaf/instance/resources/bin/stop    |   25 +
 .../karaf/instance/resources/bin/stop.bat       |   24 +
 .../etc/org.apache.karaf.management.cfg         |   63 +
 .../resources/etc/org.apache.karaf.shell.cfg    |   75 ++
 .../instance/resources/etc/system.properties    |  120 ++
 .../org/apache/karaf/jpm/impl/unix/start.sh     |   29 +
 .../apache/karaf/jpm/impl/windows/destroy.vbs   |   27 +
 .../apache/karaf/jpm/impl/windows/running.vbs   |   26 +
 .../org/apache/karaf/jpm/impl/windows/start.vbs |   34 +
 .../instance/command/CreateCommandTest.java     |   57 +
 .../instance/core/InstanceSettingsTest.java     |   58 +
 .../core/internal/InstanceServiceImplTest.java  |  187 +++
 .../internal/InstanceServiceMBeanImplTest.java  |  239 ++++
 .../internal/InstanceToTableMapperTest.java     |   90 ++
 .../apache/karaf/instance/main/ExecuteTest.java |  126 ++
 .../java/org/apache/karaf/jpm/MainTest.java     |   24 +
 .../java/org/apache/karaf/jpm/ProcessTest.java  |   69 ++
 .../src/test/resources/etc/startup.properties   |   20 +
 120 files changed, 5031 insertions(+), 5283 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/karaf/blob/7c2db062/assemblies/features/standard/src/main/feature/feature.xml
----------------------------------------------------------------------
diff --git a/assemblies/features/standard/src/main/feature/feature.xml b/assemblies/features/standard/src/main/feature/feature.xml
index 1c67ca7..830ba9d 100644
--- a/assemblies/features/standard/src/main/feature/feature.xml
+++ b/assemblies/features/standard/src/main/feature/feature.xml
@@ -134,7 +134,6 @@
 
     <feature name="instance" description="Provide Instance support" version="${project.version}">
         <bundle start-level="30" start="true">mvn:org.apache.karaf.instance/org.apache.karaf.instance.core/${project.version}</bundle>
-        <bundle start-level="30" start="true">mvn:org.apache.karaf.instance/org.apache.karaf.instance.command/${project.version}</bundle>
     </feature>
 
     <feature name="jaas" description="Provide JAAS support" version="${project.version}">

http://git-wip-us.apache.org/repos/asf/karaf/blob/7c2db062/instance/NOTICE
----------------------------------------------------------------------
diff --git a/instance/NOTICE b/instance/NOTICE
new file mode 100644
index 0000000..b70f1f9
--- /dev/null
+++ b/instance/NOTICE
@@ -0,0 +1,71 @@
+Apache Karaf
+Copyright 2010-2014 The Apache Software Foundation
+
+
+I. Included Software
+
+This product includes software developed at
+The Apache Software Foundation (http://www.apache.org/).
+Licensed under the Apache License 2.0.
+
+This product uses software developed at
+The OSGi Alliance (http://www.osgi.org/).
+Copyright (c) OSGi Alliance (2000, 2010).
+Licensed under the Apache License 2.0.
+
+This product includes software developed at
+OW2 (http://www.ow2.org/).
+Licensed under the BSD License.
+
+This product includes software developed at
+OPS4J (http://www.ops4j.org/).
+Licensed under the Apache License 2.0.
+
+This product includes software developed at
+Eclipse Foundation (http://www.eclipse.org/).
+Licensed under the EPL.
+
+This product includes software written by
+Antony Lesuisse.
+Licensed under Public Domain.
+
+
+II. Used Software
+
+This product uses software developed at
+FUSE Source (http://www.fusesource.org/).
+Licensed under the Apache License 2.0.
+
+This product uses software developed at
+AOP Alliance (http://aopalliance.sourceforge.net/).
+Licensed under the Public Domain.
+
+This product uses software developed at
+Tanuki Software (http://www.tanukisoftware.com/).
+Licensed under the Apache License 2.0.
+
+This product uses software developed at
+Jasypt (http://jasypt.sourceforge.net/).
+Licensed under the Apache License 2.0.
+
+This product uses software developed at
+JLine (http://jline.sourceforge.net).
+Licensed under the BSD License.
+
+This product uses software developed at
+SLF4J (http://www.slf4j.org/).
+Licensed under the MIT License.
+
+This product uses software developed at
+SpringSource (http://www.springsource.org/).
+Licensed under the Apache License 2.0.
+
+This product includes software from http://www.json.org.
+Copyright (c) 2002 JSON.org
+
+
+III. License Summary
+- Apache License 2.0
+- BSD License
+- EPL License
+- MIT License

http://git-wip-us.apache.org/repos/asf/karaf/blob/7c2db062/instance/command/NOTICE
----------------------------------------------------------------------
diff --git a/instance/command/NOTICE b/instance/command/NOTICE
deleted file mode 100644
index b70f1f9..0000000
--- a/instance/command/NOTICE
+++ /dev/null
@@ -1,71 +0,0 @@
-Apache Karaf
-Copyright 2010-2014 The Apache Software Foundation
-
-
-I. Included Software
-
-This product includes software developed at
-The Apache Software Foundation (http://www.apache.org/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-The OSGi Alliance (http://www.osgi.org/).
-Copyright (c) OSGi Alliance (2000, 2010).
-Licensed under the Apache License 2.0.
-
-This product includes software developed at
-OW2 (http://www.ow2.org/).
-Licensed under the BSD License.
-
-This product includes software developed at
-OPS4J (http://www.ops4j.org/).
-Licensed under the Apache License 2.0.
-
-This product includes software developed at
-Eclipse Foundation (http://www.eclipse.org/).
-Licensed under the EPL.
-
-This product includes software written by
-Antony Lesuisse.
-Licensed under Public Domain.
-
-
-II. Used Software
-
-This product uses software developed at
-FUSE Source (http://www.fusesource.org/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-AOP Alliance (http://aopalliance.sourceforge.net/).
-Licensed under the Public Domain.
-
-This product uses software developed at
-Tanuki Software (http://www.tanukisoftware.com/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-Jasypt (http://jasypt.sourceforge.net/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-JLine (http://jline.sourceforge.net).
-Licensed under the BSD License.
-
-This product uses software developed at
-SLF4J (http://www.slf4j.org/).
-Licensed under the MIT License.
-
-This product uses software developed at
-SpringSource (http://www.springsource.org/).
-Licensed under the Apache License 2.0.
-
-This product includes software from http://www.json.org.
-Copyright (c) 2002 JSON.org
-
-
-III. License Summary
-- Apache License 2.0
-- BSD License
-- EPL License
-- MIT License

http://git-wip-us.apache.org/repos/asf/karaf/blob/7c2db062/instance/command/pom.xml
----------------------------------------------------------------------
diff --git a/instance/command/pom.xml b/instance/command/pom.xml
deleted file mode 100644
index d9741ca..0000000
--- a/instance/command/pom.xml
+++ /dev/null
@@ -1,129 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-
-    <!--
-
-        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.
-    -->
-
-    <modelVersion>4.0.0</modelVersion>
-
-    <parent>
-        <groupId>org.apache.karaf.instance</groupId>
-        <artifactId>instance</artifactId>
-        <version>4.0.0-SNAPSHOT</version>
-        <relativePath>../pom.xml</relativePath>
-    </parent>
-
-    <artifactId>org.apache.karaf.instance.command</artifactId>
-    <packaging>bundle</packaging>
-    <name>Apache Karaf :: Instance :: Command</name>
-    <description>Instance shell commands to manipulate Karaf child instances.</description>
-
-    <properties>
-        <appendedResourcesDirectory>${basedir}/../../etc/appended-resources</appendedResourcesDirectory>
-    </properties>
-
-    <dependencies>
-        <dependency>
-            <groupId>org.osgi</groupId>
-            <artifactId>org.osgi.core</artifactId>
-            <scope>provided</scope>
-        </dependency>
-
-        <dependency>
-            <groupId>org.osgi</groupId>
-            <artifactId>org.osgi.compendium</artifactId>
-            <scope>provided</scope>
-        </dependency>
-
-        <dependency>
-            <groupId>org.apache.karaf.instance</groupId>
-            <artifactId>org.apache.karaf.instance.core</artifactId>
-        </dependency>
-
-        <dependency>
-            <groupId>org.apache.karaf.shell</groupId>
-            <artifactId>org.apache.karaf.shell.core</artifactId>
-        </dependency>
-
-        <dependency>
-            <groupId>org.apache.karaf.features</groupId>
-            <artifactId>org.apache.karaf.features.command</artifactId>
-        </dependency>
-
-        <dependency>
-            <groupId>org.slf4j</groupId>
-            <artifactId>slf4j-jdk14</artifactId>
-            <scope>test</scope>
-        </dependency>
-
-        <dependency>
-            <groupId>org.easymock</groupId>
-            <artifactId>easymockclassextension</artifactId>
-            <version>${easymock.version}</version>
-            <scope>test</scope>
-        </dependency>
-
-     </dependencies>
-
-    <build>
-        <resources>
-            <resource>
-                <directory>${project.basedir}/src/main/resources</directory>
-                <includes>
-                    <include>**/*</include>
-                </includes>
-            </resource>
-            <resource>
-                <directory>${project.basedir}/src/main/resources</directory>
-                <filtering>true</filtering>
-                <includes>
-                    <include>**/*.info</include>
-                </includes>
-            </resource>
-        </resources>
-        <plugins>
-            <plugin>
-                <groupId>org.apache.felix</groupId>
-                <artifactId>maven-bundle-plugin</artifactId>
-                <configuration>
-                    <instructions>
-                        <Export-Package>
-                        	!*
-                        </Export-Package>
-                        <!-- We have to avoid importing instance.core.internal and jansi
-                             as Execute.java accesses the InstanceServiceImpl and jansi
-                             (but only outside OSGi) -->
-                        <Import-Package>
-                        	!org.apache.karaf.shell.impl.action.command,
-                            !org.apache.karaf.instance.core.internal,
-                            !org.fusesource.jansi,
-                        	*
-                        </Import-Package>
-                        <Private-Package>
-                            org.apache.karaf.instance.main,
-                            org.apache.karaf.instance.command,
-                            org.apache.karaf.instance.command.completers
-                        </Private-Package>
-                        <Karaf-Commands>org.apache.karaf.instance.command.*</Karaf-Commands>
-                    </instructions>
-                </configuration>
-            </plugin>
-        </plugins>
-    </build>
-
-</project>

http://git-wip-us.apache.org/repos/asf/karaf/blob/7c2db062/instance/command/src/main/java/org/apache/karaf/instance/command/ChangeOptsCommand.java
----------------------------------------------------------------------
diff --git a/instance/command/src/main/java/org/apache/karaf/instance/command/ChangeOptsCommand.java b/instance/command/src/main/java/org/apache/karaf/instance/command/ChangeOptsCommand.java
deleted file mode 100644
index c526c07..0000000
--- a/instance/command/src/main/java/org/apache/karaf/instance/command/ChangeOptsCommand.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * 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.karaf.instance.command;
-
-import org.apache.karaf.instance.command.completers.InstanceCompleter;
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Completion;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-
-@Command(scope = "instance", name = "opts-change", description = "Changes the Java options of an existing container instance.")
-@Service
-public class ChangeOptsCommand extends InstanceCommandSupport {
-
-    @Argument(index = 0, name = "name", description="The name of the container instance", required = true, multiValued = false)
-    @Completion(InstanceCompleter.class)
-    private String instance = null;
-
-    @Argument(index = 1, name = "javaOpts", description = "The new Java options to set", required = true, multiValued = false)
-    private String javaOpts;
-
-    protected Object doExecute() throws Exception {
-        getExistingInstance(instance).changeJavaOpts(javaOpts);
-        return null;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/7c2db062/instance/command/src/main/java/org/apache/karaf/instance/command/ChangeRmiRegistryPortCommand.java
----------------------------------------------------------------------
diff --git a/instance/command/src/main/java/org/apache/karaf/instance/command/ChangeRmiRegistryPortCommand.java b/instance/command/src/main/java/org/apache/karaf/instance/command/ChangeRmiRegistryPortCommand.java
deleted file mode 100644
index de5bfaf..0000000
--- a/instance/command/src/main/java/org/apache/karaf/instance/command/ChangeRmiRegistryPortCommand.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * 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.karaf.instance.command;
-
-import org.apache.karaf.instance.command.completers.InstanceCompleter;
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Completion;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-
-@Command(scope = "instance", name = "rmi-registry-port-change", description = "Changes the RMI registry port (used by management layer) of an existing container instance.")
-@Service
-public class ChangeRmiRegistryPortCommand extends InstanceCommandSupport {
-
-    @Argument(index = 0, name = "name", description = "The name of the container instance", required = true, multiValued = false)
-    @Completion(InstanceCompleter.class)
-    private String instance = null;
-
-    @Argument(index = 1, name = "port", description = "The new RMI registry port to set", required = true, multiValued = false)
-    private int port = 0;
-
-    protected Object doExecute() throws Exception {
-        getExistingInstance(instance).changeRmiRegistryPort(port);
-        return null;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/7c2db062/instance/command/src/main/java/org/apache/karaf/instance/command/ChangeRmiServerPortCommand.java
----------------------------------------------------------------------
diff --git a/instance/command/src/main/java/org/apache/karaf/instance/command/ChangeRmiServerPortCommand.java b/instance/command/src/main/java/org/apache/karaf/instance/command/ChangeRmiServerPortCommand.java
deleted file mode 100644
index 0ac2cf7..0000000
--- a/instance/command/src/main/java/org/apache/karaf/instance/command/ChangeRmiServerPortCommand.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * 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.karaf.instance.command;
-
-import org.apache.karaf.instance.command.completers.InstanceCompleter;
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Completion;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-
-@Command(scope = "instance", name = "rmi-server-port-change", description = "Changes the RMI server port (used by management layer) of an existing instance.")
-@Service
-public class ChangeRmiServerPortCommand extends InstanceCommandSupport {
-
-    @Argument(index = 0, name = "name", description = "The name of the container instance", required = true, multiValued = false)
-    @Completion(InstanceCompleter.class)
-    private String instance = null;
-
-    @Argument(index = 1, name = "port", description = "The new RMI server port to set", required = true, multiValued = false)
-    private int port = 0;
-
-    protected Object doExecute() throws Exception {
-        getExistingInstance(instance).changeRmiServerPort(port);
-        return null;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/7c2db062/instance/command/src/main/java/org/apache/karaf/instance/command/ChangeSshPortCommand.java
----------------------------------------------------------------------
diff --git a/instance/command/src/main/java/org/apache/karaf/instance/command/ChangeSshPortCommand.java b/instance/command/src/main/java/org/apache/karaf/instance/command/ChangeSshPortCommand.java
deleted file mode 100644
index 17ad26c..0000000
--- a/instance/command/src/main/java/org/apache/karaf/instance/command/ChangeSshPortCommand.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * 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.karaf.instance.command;
-
-import org.apache.karaf.instance.command.completers.InstanceCompleter;
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Completion;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-
-@Command(scope = "instance", name = "ssh-port-change", description = "Changes the secure shell port of an existing container instance.")
-@Service
-public class ChangeSshPortCommand extends InstanceCommandSupport {
-
-    @Argument(index = 0, name = "name", description="The name of the container instance", required = true, multiValued = false)
-    @Completion(InstanceCompleter.class)
-    private String instance = null;
-
-    @Argument(index = 1, name = "port", description = "The new secure shell port to set", required = true, multiValued = false)
-    private int port = 0;
-
-    protected Object doExecute() throws Exception {
-        getExistingInstance(instance).changeSshPort(port);
-        return null;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/7c2db062/instance/command/src/main/java/org/apache/karaf/instance/command/CloneCommand.java
----------------------------------------------------------------------
diff --git a/instance/command/src/main/java/org/apache/karaf/instance/command/CloneCommand.java b/instance/command/src/main/java/org/apache/karaf/instance/command/CloneCommand.java
deleted file mode 100644
index e4f28c5..0000000
--- a/instance/command/src/main/java/org/apache/karaf/instance/command/CloneCommand.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * 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.karaf.instance.command;
-
-import org.apache.karaf.instance.command.completers.InstanceCompleter;
-import org.apache.karaf.instance.core.InstanceSettings;
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Completion;
-import org.apache.karaf.shell.api.action.Option;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-
-/**
- * Clone an existing instance.
- */
-@Command(scope = "instance", name = "clone", description = "Clones an existing container instance.")
-@Service
-public class CloneCommand extends InstanceCommandSupport {
-
-    @Option(name = "-s", aliases = {"--ssh-port"}, description = "Port number for remote secure shell connection", required = false, multiValued = false)
-    int sshPort = 0;
-
-    @Option(name = "-r", aliases = {"-rr", "--rmi-port", "--rmi-registry-port"}, description = "Port number for RMI registry connection", required = false, multiValued = false)
-    int rmiRegistryPort = 0;
-
-    @Option(name = "-rs", aliases = {"--rmi-server-port"}, description = "Port number for RMI server connection", required = false, multiValued = false)
-    int rmiServerPort = 0;
-
-    @Option(name = "-l", aliases = {"--location"}, description = "Location of the cloned container instance in the file system", required = false, multiValued = false)
-    String location;
-
-    @Option(name = "-o", aliases = {"--java-opts"}, description = "JVM options to use when launching the cloned instance", required = false, multiValued = false)
-    String javaOpts;
-
-    @Option(name = "-v", aliases = {"--verbose"}, description = "Display actions performed by the command (disabled by default)", required = false, multiValued = false)
-    boolean verbose = false;
-
-    @Argument(index = 0, name = "name", description = "The name of the source container instance", required = true, multiValued = false)
-    @Completion(InstanceCompleter.class)
-    String name;
-
-    @Argument(index = 1, name = "cloneName", description = "The name of the cloned container instance", required = true, multiValued = false)
-    String cloneName;
-
-
-    protected Object doExecute() throws Exception {
-        InstanceSettings settings = new InstanceSettings(sshPort, rmiRegistryPort, rmiServerPort, location, javaOpts, null, null);
-        getInstanceService().cloneInstance(name, cloneName, settings, verbose);
-        return null;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/7c2db062/instance/command/src/main/java/org/apache/karaf/instance/command/ConnectCommand.java
----------------------------------------------------------------------
diff --git a/instance/command/src/main/java/org/apache/karaf/instance/command/ConnectCommand.java b/instance/command/src/main/java/org/apache/karaf/instance/command/ConnectCommand.java
deleted file mode 100644
index c81a3eb..0000000
--- a/instance/command/src/main/java/org/apache/karaf/instance/command/ConnectCommand.java
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * 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.karaf.instance.command;
-
-import java.util.List;
-
-import org.apache.karaf.instance.command.completers.InstanceCompleter;
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Completion;
-import org.apache.karaf.shell.api.action.Option;
-import org.apache.karaf.shell.api.action.lifecycle.Reference;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.apache.karaf.shell.api.console.Session;
-
-@Command(scope = "instance", name = "connect", description = "Connects to an existing container instance.")
-@Service
-public class ConnectCommand extends InstanceCommandSupport {
-
-    @Option(name="-u", aliases={"--username"}, description="Remote user name", required = false, multiValued = false)
-    private String username;
-
-    @Option(name = "-p", aliases = {"--password"}, description = "Remote password", required = false, multiValued = false)
-    private String password;
-
-    @Argument(index = 0, name="name", description="The name of the container instance", required = true, multiValued = false)
-    @Completion(InstanceCompleter.class)
-    private String instance = null;
-
-    @Argument(index = 1, name = "command", description = "Optional command to execute", required = false, multiValued = true)
-    private List<String> command;
-
-    @Reference
-    Session session;
-
-    protected Object doExecute() throws Exception {
-        String cmdStr = "";
-        if (command != null) {
-            StringBuilder sb = new StringBuilder();
-            for (String cmd : command) {
-                if (sb.length() > 0) {
-                    sb.append(' ');
-                }
-                sb.append(cmd);
-            }
-            cmdStr = "'" + sb.toString().replaceAll("'", "\\'") + "'";
-        }
-
-        int port = getExistingInstance(instance).getSshPort();
-        if (username != null) {
-            if (password == null) {
-                session.execute("ssh:ssh -q -l " + username + " -p " + port + " localhost " + cmdStr);
-            } else {
-                session.execute("ssh:ssh -q -l " + username + " -P " + password + " -p " + port + " localhost " + cmdStr);
-            }
-        } else {
-            session.execute("ssh:ssh -q -p " + port + " localhost " + cmdStr);
-        }
-        return null;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/7c2db062/instance/command/src/main/java/org/apache/karaf/instance/command/CreateCommand.java
----------------------------------------------------------------------
diff --git a/instance/command/src/main/java/org/apache/karaf/instance/command/CreateCommand.java b/instance/command/src/main/java/org/apache/karaf/instance/command/CreateCommand.java
deleted file mode 100644
index 0dcc3ac..0000000
--- a/instance/command/src/main/java/org/apache/karaf/instance/command/CreateCommand.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * 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.karaf.instance.command;
-
-import java.util.List;
-
-import org.apache.karaf.features.command.completers.AllFeatureCompleter;
-import org.apache.karaf.features.command.completers.InstalledRepoUriCompleter;
-import org.apache.karaf.instance.core.InstanceSettings;
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Completion;
-import org.apache.karaf.shell.api.action.Option;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-
-/**
- * Creates a new instance.
- */
-@Command(scope = "instance", name = "create", description = "Creates a new container instance.")
-@Service
-public class CreateCommand extends InstanceCommandSupport
-{
-    @Option(name = "-s", aliases = {"--ssh-port"}, description = "Port number for remote secure shell connection", required = false, multiValued = false)
-    int sshPort = 0;
-
-    @Option(name = "-r", aliases = {"-rr", "--rmi-port", "--rmi-registry-port"}, description = "Port number for RMI registry connection", required = false, multiValued = false)
-    int rmiRegistryPort = 0;
-
-    @Option(name = "-rs", aliases = {"--rmi-server-port"}, description = "Port number for RMI server connection", required = false, multiValued = false)
-    int rmiServerPort = 0;
-
-    @Option(name = "-l", aliases = {"--location"}, description = "Location of the new container instance in the file system", required = false, multiValued = false)
-    String location;
-
-    @Option(name = "-o", aliases = {"--java-opts"}, description = "JVM options to use when launching the instance", required = false, multiValued = false)
-    String javaOpts;
-    
-    @Option(name = "-f", aliases = {"--feature"},
-            description = "Initial features. This option can be specified multiple times to enable multiple initial features", required = false, multiValued = true)
-    @Completion(AllFeatureCompleter.class)
-    List<String> features;
-    
-    @Option(name = "-furl", aliases = {"--featureURL"}, 
-            description = "Additional feature descriptor URLs. This option can be specified multiple times to add multiple URLs", required = false, multiValued = true)
-    @Completion(InstalledRepoUriCompleter.class)
-    List<String> featureURLs;
-
-    @Option(name = "-v", aliases = {"--verbose"}, description = "Display actions performed by the command (disabled by default)", required = false, multiValued = false)
-    boolean verbose = false;
-
-    @Argument(index = 0, name = "name", description="The name of the new container instance", required = true, multiValued = false)
-    String instance = null;
-
-    protected Object doExecute() throws Exception {
-        InstanceSettings settings = new InstanceSettings(sshPort, rmiRegistryPort, rmiServerPort, location, javaOpts, featureURLs, features);
-        getInstanceService().createInstance(instance, settings, verbose);
-        return null;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/7c2db062/instance/command/src/main/java/org/apache/karaf/instance/command/DestroyCommand.java
----------------------------------------------------------------------
diff --git a/instance/command/src/main/java/org/apache/karaf/instance/command/DestroyCommand.java b/instance/command/src/main/java/org/apache/karaf/instance/command/DestroyCommand.java
deleted file mode 100644
index fb2964f..0000000
--- a/instance/command/src/main/java/org/apache/karaf/instance/command/DestroyCommand.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * 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.karaf.instance.command;
-
-import org.apache.karaf.instance.command.completers.InstanceCompleter;
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Completion;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-
-/**
- * Destroy an existing instance.
- */
-@Command(scope = "instance", name = "destroy", description = "Destroys an existing container instance.")
-@Service
-public class DestroyCommand extends InstanceCommandSupport
-{
-    @Argument(index = 0, name = "name", description= "The name of the container instance to destroy", required = true, multiValued = false)
-    @Completion(InstanceCompleter.class)
-    private String instance = null;
-
-    protected Object doExecute() throws Exception {
-        getExistingInstance(instance).destroy();
-        return null;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/7c2db062/instance/command/src/main/java/org/apache/karaf/instance/command/InstanceCommandSupport.java
----------------------------------------------------------------------
diff --git a/instance/command/src/main/java/org/apache/karaf/instance/command/InstanceCommandSupport.java b/instance/command/src/main/java/org/apache/karaf/instance/command/InstanceCommandSupport.java
deleted file mode 100644
index 3b0b535..0000000
--- a/instance/command/src/main/java/org/apache/karaf/instance/command/InstanceCommandSupport.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * 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.karaf.instance.command;
-
-import org.apache.karaf.instance.core.Instance;
-import org.apache.karaf.instance.core.InstanceService;
-import org.apache.karaf.shell.api.action.Action;
-import org.apache.karaf.shell.api.action.lifecycle.Reference;
-
-public abstract class InstanceCommandSupport implements Action {
-
-    @Reference
-    private InstanceService instanceService;
-
-    public InstanceService getInstanceService() {
-        return instanceService;
-    }
-
-    public void setInstanceService(InstanceService instanceService) {
-        this.instanceService = instanceService;
-    }
-
-    protected Instance getExistingInstance(String name) {
-        Instance i = instanceService.getInstance(name);
-        if (i == null) {
-            throw new IllegalArgumentException("Instances '" + name + "' does not exist");
-        }
-        return i;
-    }
-
-    @Override
-    public Object execute() throws Exception {
-        return doExecute();
-    }
-
-    protected abstract Object doExecute() throws Exception;
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/7c2db062/instance/command/src/main/java/org/apache/karaf/instance/command/ListCommand.java
----------------------------------------------------------------------
diff --git a/instance/command/src/main/java/org/apache/karaf/instance/command/ListCommand.java b/instance/command/src/main/java/org/apache/karaf/instance/command/ListCommand.java
deleted file mode 100644
index fe571a8..0000000
--- a/instance/command/src/main/java/org/apache/karaf/instance/command/ListCommand.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * 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.karaf.instance.command;
-
-import org.apache.karaf.instance.core.Instance;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Option;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.apache.karaf.shell.support.table.ShellTable;
-
-@Command(scope = "instance", name = "list", description = "Lists all existing container instances.")
-@Service
-public class ListCommand extends InstanceCommandSupport {
-
-    @Option(name = "-l", aliases = { "--location" }, description = "Displays the location of the container instances", required = false, multiValued = false)
-    boolean location;
-
-    @Option(name = "-o", aliases = { "--java-opts" }, description = "Displays the Java options used to launch the JVM", required = false, multiValued = false)
-    boolean javaOpts;
-
-    @Option(name = "--no-color", description = "Disable table rendered output", required = false, multiValued = false)
-    boolean noFormat;
-
-    protected Object doExecute() throws Exception {
-        getInstanceService().refreshInstance();
-        Instance[] instances = getInstanceService().getInstances();
-        ShellTable table = new ShellTable();
-        table.column("SSH Port").alignRight();
-        table.column("RMI Registry").alignRight();
-        table.column("RMI Server").alignRight();
-        table.column("State");
-        table.column("PID");
-        table.column(getRightColumnHeader());
-        for (Instance instance : instances) {
-            table.addRow().addContent(
-                    instance.getSshPort(),
-                    instance.getRmiRegistryPort(),
-                    instance.getRmiServerPort(),
-                    instance.getState(),
-                    instance.getPid(),
-                    getRightColumnValue(instance));
-        }
-        table.print(System.out, !noFormat);
-        return null;
-    }
-
-    private String getRightColumnHeader() {
-        if (javaOpts) {
-            return "JavaOpts";
-        } else if (location) {
-            return "Location";
-        } else {
-            return "Name";
-        }
-    }
-
-    private String getRightColumnValue(Instance instance) {
-        if (javaOpts) {
-            return instance.getJavaOpts();
-        } else if (location) {
-            return instance.getLocation();
-        } else {
-            return instance.getName();
-        }
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/7c2db062/instance/command/src/main/java/org/apache/karaf/instance/command/RenameCommand.java
----------------------------------------------------------------------
diff --git a/instance/command/src/main/java/org/apache/karaf/instance/command/RenameCommand.java b/instance/command/src/main/java/org/apache/karaf/instance/command/RenameCommand.java
deleted file mode 100644
index ef68400..0000000
--- a/instance/command/src/main/java/org/apache/karaf/instance/command/RenameCommand.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * 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.karaf.instance.command;
-
-import org.apache.karaf.instance.command.completers.InstanceCompleter;
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Completion;
-import org.apache.karaf.shell.api.action.Option;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-
-@Command(scope = "instance", name = "rename", description = "Rename an existing container instance.")
-@Service
-public class RenameCommand extends InstanceCommandSupport {
-
-    @Option(name = "-v", aliases = {"--verbose"}, description = "Display actions performed by the command (disabled by default)", required = false, multiValued = false)
-    boolean verbose = false;
-
-    @Argument(index = 0, name = "name", description = "The name of the container instance to rename", required = true, multiValued = false)
-    @Completion(InstanceCompleter.class)
-    String instance = null;
-
-    @Argument(index = 1, name = "new-name", description = "The new name of the container instance", required = true, multiValued = false)
-    String newName = null;
-
-    protected Object doExecute() throws Exception {
-        getInstanceService().renameInstance(instance, newName, verbose);
-        return null;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/7c2db062/instance/command/src/main/java/org/apache/karaf/instance/command/StartCommand.java
----------------------------------------------------------------------
diff --git a/instance/command/src/main/java/org/apache/karaf/instance/command/StartCommand.java b/instance/command/src/main/java/org/apache/karaf/instance/command/StartCommand.java
deleted file mode 100644
index 8c52d5e..0000000
--- a/instance/command/src/main/java/org/apache/karaf/instance/command/StartCommand.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * 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.karaf.instance.command;
-
-import org.apache.karaf.instance.command.completers.InstanceCompleter;
-import org.apache.karaf.instance.core.Instance;
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Completion;
-import org.apache.karaf.shell.api.action.Option;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-
-@Command(scope = "instance", name = "start", description = "Start an existing container instance.")
-@Service
-public class StartCommand extends InstanceCommandSupport {
-                      
-    @Option(name = "-d", aliases = { "--debug"}, description = "Start the instance in debug mode", required = false, multiValued = false)
-    private boolean debug; 
-    
-    @Option(name = "-o", aliases = { "--java-opts"}, description = "Java options when launching the instance", required = false, multiValued = false)
-    private String javaOpts;
-
-    @Option(name = "-w", aliases = { "--wait"}, description = "Wait for the instance to be fully started", required = false, multiValued = false)
-    private boolean wait;
-
-    @Argument(index = 0, name = "name", description = "The name of the container instance", required = true, multiValued = false)
-    @Completion(InstanceCompleter.class)
-    private String instance = null;
-
-    static final String DEBUG_OPTS = " -Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005";
-    static final String DEFAULT_OPTS = "-server -Xmx512M -Dcom.sun.management.jmxremote";
-
-    protected Object doExecute() throws Exception {
-        Instance child = getExistingInstance(instance);
-        String opts = javaOpts;
-        if (opts == null) {
-            opts = child.getJavaOpts();
-        }
-        if (opts == null) {
-            opts = DEFAULT_OPTS;
-        }
-        if (debug) {
-            opts += DEBUG_OPTS;
-        }
-        if (wait) {
-            String state = child.getState();
-            if (Instance.STOPPED.equals(state)) {
-                child.start(opts);
-            }
-            if (!Instance.STARTED.equals(state)) {
-                do {
-                    Thread.sleep(500);
-                    state = child.getState();
-                } while (Instance.STARTING.equals(state));
-            }
-        } else {
-            child.start(opts);
-        }
-        return null;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/7c2db062/instance/command/src/main/java/org/apache/karaf/instance/command/StatusCommand.java
----------------------------------------------------------------------
diff --git a/instance/command/src/main/java/org/apache/karaf/instance/command/StatusCommand.java b/instance/command/src/main/java/org/apache/karaf/instance/command/StatusCommand.java
deleted file mode 100644
index 82100e1..0000000
--- a/instance/command/src/main/java/org/apache/karaf/instance/command/StatusCommand.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * 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.karaf.instance.command;
-
-import org.apache.karaf.instance.command.completers.InstanceCompleter;
-import org.apache.karaf.instance.core.Instance;
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Completion;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-
-@Command(scope = "instance", name = "status", description = "Check the current status of an instance.")
-@Service
-public class StatusCommand extends InstanceCommandSupport {
-
-    @Argument(index = 0, name = "name", description = "The name of the instance", required = true, multiValued = false)
-    @Completion(InstanceCompleter.class)
-    private String name;
-
-    protected Object doExecute() throws Exception {
-        Instance instance = getExistingInstance(name);
-        System.out.println(instance.getState());
-        return null;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/7c2db062/instance/command/src/main/java/org/apache/karaf/instance/command/StopCommand.java
----------------------------------------------------------------------
diff --git a/instance/command/src/main/java/org/apache/karaf/instance/command/StopCommand.java b/instance/command/src/main/java/org/apache/karaf/instance/command/StopCommand.java
deleted file mode 100644
index 6c8de10..0000000
--- a/instance/command/src/main/java/org/apache/karaf/instance/command/StopCommand.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * 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.karaf.instance.command;
-
-import org.apache.karaf.instance.command.completers.InstanceCompleter;
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Completion;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-
-@Command(scope = "instance", name = "stop", description = "Stop an existing container instance.")
-@Service
-public class StopCommand extends InstanceCommandSupport {
-
-    @Argument(index = 0, name = "name", description = "The name of the container instance", required = true, multiValued = false)
-    @Completion(InstanceCompleter.class)
-    private String instance = null;
-
-    protected Object doExecute() throws Exception {
-        getExistingInstance(instance).stop();
-        return null;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/7c2db062/instance/command/src/main/java/org/apache/karaf/instance/command/completers/InstanceCompleter.java
----------------------------------------------------------------------
diff --git a/instance/command/src/main/java/org/apache/karaf/instance/command/completers/InstanceCompleter.java b/instance/command/src/main/java/org/apache/karaf/instance/command/completers/InstanceCompleter.java
deleted file mode 100644
index 4468374..0000000
--- a/instance/command/src/main/java/org/apache/karaf/instance/command/completers/InstanceCompleter.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * 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.karaf.instance.command.completers;
-
-import java.util.List;
-
-import org.apache.karaf.instance.core.Instance;
-import org.apache.karaf.instance.core.InstanceService;
-import org.apache.karaf.shell.api.action.lifecycle.Reference;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.apache.karaf.shell.api.console.CommandLine;
-import org.apache.karaf.shell.api.console.Completer;
-import org.apache.karaf.shell.api.console.Session;
-import org.apache.karaf.shell.support.completers.StringsCompleter;
-
-/**
- * Displays a list of configured server instances for the instance commands.
- *
- */
-@Service
-public class InstanceCompleter implements Completer {
-
-    @Reference
-    private InstanceService instanceService;
-
-    public void setInstanceService(InstanceService instanceService) {
-        this.instanceService = instanceService;
-    }
-
-    public int complete(Session session, CommandLine commandLine, List<String> candidates) {
-        StringsCompleter delegate = new StringsCompleter();
-        for (Instance instance : instanceService.getInstances()) {
-            delegate.getStrings().add(instance.getName());
-        }
-        return delegate.complete(session, commandLine, candidates);
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/7c2db062/instance/command/src/main/java/org/apache/karaf/instance/main/Execute.java
----------------------------------------------------------------------
diff --git a/instance/command/src/main/java/org/apache/karaf/instance/main/Execute.java b/instance/command/src/main/java/org/apache/karaf/instance/main/Execute.java
deleted file mode 100644
index 591873e..0000000
--- a/instance/command/src/main/java/org/apache/karaf/instance/main/Execute.java
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * 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.karaf.instance.main;
-
-import java.io.File;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Map;
-import java.util.TreeMap;
-
-import org.apache.karaf.instance.command.ChangeOptsCommand;
-import org.apache.karaf.instance.command.ChangeRmiRegistryPortCommand;
-import org.apache.karaf.instance.command.ChangeRmiServerPortCommand;
-import org.apache.karaf.instance.command.ChangeSshPortCommand;
-import org.apache.karaf.instance.command.CloneCommand;
-import org.apache.karaf.instance.command.CreateCommand;
-import org.apache.karaf.instance.command.DestroyCommand;
-import org.apache.karaf.instance.command.InstanceCommandSupport;
-import org.apache.karaf.instance.command.ListCommand;
-import org.apache.karaf.instance.command.RenameCommand;
-import org.apache.karaf.instance.command.StartCommand;
-import org.apache.karaf.instance.command.StatusCommand;
-import org.apache.karaf.instance.command.StopCommand;
-import org.apache.karaf.instance.core.internal.InstanceServiceImpl;
-import org.apache.karaf.shell.api.action.Action;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.impl.action.command.DefaultActionPreparator;
-import org.fusesource.jansi.AnsiConsole;
-
-public class Execute {
-    static Class<? extends Action> x = CreateCommand.class;
-    private static final Class<?>[] COMMAND_CLASSES = new Class[]{
-            ChangeOptsCommand.class,
-            ChangeRmiRegistryPortCommand.class,
-            ChangeRmiServerPortCommand.class,
-            ChangeSshPortCommand.class,
-            CloneCommand.class,
-            CreateCommand.class,
-            DestroyCommand.class,
-            ListCommand.class,
-            RenameCommand.class,
-            StartCommand.class,
-            StatusCommand.class,
-            StopCommand.class};
-    private static final Map<String, Class<?>> COMMANDS = new TreeMap<String, Class<?>>();
-
-    static {
-        for (Class<?> c : COMMAND_CLASSES) {
-            Command ann = c.getAnnotation(Command.class);
-            if (ann == null) {
-                continue;
-            }
-            COMMANDS.put(ann.name(), c);
-        }
-    }
-
-    // For testing
-    static boolean exitAllowed = true;
-
-    /**
-     * Environment variable for specifying extra options to the Karaf instance
-     * process kicked off from this Java process.
-     */
-    private static final String ENV_KARAF_OPTS = "KARAF_OPTS";
-
-    /**
-     * System property for specifying extra options to the Karaf instance
-     * process kicked off from this Java process.
-     */
-    private static final String PROP_KARAF_OPTS = "karaf.opts";
-
-    public static void main(String[] args) throws Exception {
-        AnsiConsole.systemInstall();
-
-        if (args.length == 0) {
-            listCommands();
-            exit(0);
-        }
-        String commandName = args[0];
-        Class<?> cls = COMMANDS.get(commandName);
-        if (cls == null) {
-            System.err.println("Command not found: " + commandName);
-            exit(-1);
-        }
-
-        String storage = System.getProperty("karaf.instances");
-        if (storage == null) {
-            System.err.println("System property 'karaf.instances' is not set. \n" +
-                    "This property needs to be set to the full path of the instance.properties file.");
-            exit(-2);
-        }
-        File storageFile = new File(storage);
-        System.setProperty("user.dir", storageFile.getParentFile().getParentFile().getCanonicalPath());
-
-        try {
-            String karafOpts = System.getenv(ENV_KARAF_OPTS);
-            if (karafOpts != null) {
-                System.setProperty(PROP_KARAF_OPTS, karafOpts);
-            }
-        } catch (Exception e) {
-            System.err.println("Could not read KARAF_OPTS environment variable: " + e.getMessage());
-            if (System.getProperty("karaf.showStackTrace") != null) {
-                throw e;
-            }
-        }
-
-        Object command = cls.newInstance();
-        if (command instanceof InstanceCommandSupport) {
-            try {
-                execute((InstanceCommandSupport) command, storageFile, args);
-            } catch (Exception e) {
-                System.err.println("Error execution command '" + commandName + "': " + e.getMessage());
-                if (System.getProperty("karaf.showStackTrace") != null) {
-                    throw e;
-                }
-            }
-        } else {
-            System.err.println("Not an instance command: " + commandName);
-            exit(-3);
-        }
-    }
-
-    static void execute(InstanceCommandSupport command, File storageFile, String[] args) throws Exception {
-        DefaultActionPreparator dap = new DefaultActionPreparator();
-        List<Object> params = new ArrayList<Object>(Arrays.asList(args));
-        params.remove(0); // this is the actual command name
-
-        if (!dap.prepare(command, null, params)) {
-            return;
-        }
-
-        InstanceServiceImpl instanceService = new InstanceServiceImpl();
-        instanceService.setStorageLocation(storageFile);
-        command.setInstanceService(instanceService);
-        command.execute();
-    }
-
-    private static void listCommands() {
-        System.out.println("Available commands:");
-        for (Map.Entry<String, Class<?>> entry : COMMANDS.entrySet()) {
-            Command ann = entry.getValue().getAnnotation(Command.class);
-            System.out.printf("  %s - %s\n", entry.getKey(), ann.description());
-        }
-
-        System.out.println("Type 'command --help' for more help on the specified command.");
-    }
-
-    private static void exit(int rc) {
-        if (exitAllowed) {
-            System.exit(rc);
-        } else {
-            throw new RuntimeException("" + rc);
-        }
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/7c2db062/instance/command/src/main/resources/META-INF/services/org/apache/karaf/shell/commands
----------------------------------------------------------------------
diff --git a/instance/command/src/main/resources/META-INF/services/org/apache/karaf/shell/commands b/instance/command/src/main/resources/META-INF/services/org/apache/karaf/shell/commands
deleted file mode 100644
index 92245c7..0000000
--- a/instance/command/src/main/resources/META-INF/services/org/apache/karaf/shell/commands
+++ /dev/null
@@ -1,30 +0,0 @@
-##---------------------------------------------------------------------------
-##  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.
-##---------------------------------------------------------------------------
-org.apache.karaf.instance.core.internal.InstanceServiceImpl
-org.apache.karaf.instance.command.ChangeOptsCommand
-org.apache.karaf.instance.command.ChangeRmiRegistryPortCommand
-org.apache.karaf.instance.command.ChangeRmiServerPortCommand
-org.apache.karaf.instance.command.ChangeSshPortCommand
-org.apache.karaf.instance.command.CloneCommand
-org.apache.karaf.instance.command.ConnectCommand
-org.apache.karaf.instance.command.CreateCommand
-org.apache.karaf.instance.command.DestroyCommand
-org.apache.karaf.instance.command.ListCommand
-org.apache.karaf.instance.command.RenameCommand
-org.apache.karaf.instance.command.StartCommand
-org.apache.karaf.instance.command.StatusCommand
-org.apache.karaf.instance.command.StopCommand

http://git-wip-us.apache.org/repos/asf/karaf/blob/7c2db062/instance/command/src/main/resources/OSGI-INF/bundle.info
----------------------------------------------------------------------
diff --git a/instance/command/src/main/resources/OSGI-INF/bundle.info b/instance/command/src/main/resources/OSGI-INF/bundle.info
deleted file mode 100644
index afeac5e..0000000
--- a/instance/command/src/main/resources/OSGI-INF/bundle.info
+++ /dev/null
@@ -1,29 +0,0 @@
-h1. Synopsis
-
-${project.name}
-
-${project.description}
-
-Maven URL:
-[mvn:${project.groupId}/${project.artifactId}/${project.version}]
-
-h1. Description
-
-This bundle contains all Karaf shell commands related to the instance feature.
-
-The following commands are available:
-* instance:create - Creates a new container instance.
-* instance:connect - Connects to an existing container instance.
-* instance:list - Lists all existing container instances.
-* instance:start - Starts an existing container instance.
-* instance:stop - Stops an existing container instance.
-* instance:destroy - Destroys an existing container instance.
-* instance:rename - Renames an existing container instance.
-* instance:change-ssh-port - Changes the secure shell port of an existing container instance.
-* instance:change-rmi-registry-port - Changes the RMI registry port (used by management layer) of an existing container instance.
-* instance:change-rmi-server-port - Changes the RMI server port (used by management layer) of an existing container instance.
-* instance:change-opts - Changes the java options of an existing container instance.
-
-h1. See also
-
-Commands - section of the Karaf User Guide.
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/karaf/blob/7c2db062/instance/command/src/test/java/org/apache/karaf/instance/command/CreateCommandTest.java
----------------------------------------------------------------------
diff --git a/instance/command/src/test/java/org/apache/karaf/instance/command/CreateCommandTest.java b/instance/command/src/test/java/org/apache/karaf/instance/command/CreateCommandTest.java
deleted file mode 100644
index 359a183..0000000
--- a/instance/command/src/test/java/org/apache/karaf/instance/command/CreateCommandTest.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * 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.karaf.instance.command;
-
-import java.util.Arrays;
-import java.util.Collections;
-
-import junit.framework.TestCase;
-
-import org.apache.karaf.instance.core.InstanceService;
-import org.apache.karaf.instance.core.InstanceSettings;
-import org.easymock.EasyMock;
-
-public class CreateCommandTest extends TestCase {
-
-    public void testCreateCommandExecute() throws Exception {
-        InstanceService instanceService = EasyMock.createMock(InstanceService.class);
-        EasyMock.replay(instanceService);
-        
-        CreateCommand cc = new CreateCommand();
-        cc.setInstanceService(instanceService);
-        cc.sshPort = 9941;
-        cc.rmiRegistryPort = 1122;
-        cc.rmiServerPort = 44444;
-        cc.location = "top";
-        cc.javaOpts = "foo";
-        cc.features = Arrays.asList("abc", "def");
-        cc.featureURLs = Collections.singletonList("http://something");
-        cc.instance = "myInstance";
-        cc.verbose = true;
-        
-        EasyMock.verify(instanceService); // check precondition
-        EasyMock.reset(instanceService);
-        InstanceSettings expectedIS =
-            new InstanceSettings(9941, 1122, 44444, "top", "foo", Collections.singletonList("http://something"), Arrays.asList("abc", "def"));
-        EasyMock.expect(instanceService.createInstance("myInstance", expectedIS, true)).andReturn(null);
-        EasyMock.replay(instanceService);
-        
-        cc.doExecute();
-        EasyMock.verify(instanceService);
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/7c2db062/instance/command/src/test/java/org/apache/karaf/instance/main/ExecuteTest.java
----------------------------------------------------------------------
diff --git a/instance/command/src/test/java/org/apache/karaf/instance/main/ExecuteTest.java b/instance/command/src/test/java/org/apache/karaf/instance/main/ExecuteTest.java
deleted file mode 100644
index 1e49a88..0000000
--- a/instance/command/src/test/java/org/apache/karaf/instance/main/ExecuteTest.java
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * 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.karaf.instance.main;
-
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.PrintStream;
-import java.io.IOException;
-import java.util.Properties;
-
-import junit.framework.TestCase;
-
-public class ExecuteTest extends TestCase {
-    private String userDir;
-    
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        Execute.exitAllowed = false;
-        userDir = System.getProperty("user.dir");
-    }
-
-    @Override
-    protected void tearDown() throws Exception {
-        super.tearDown();
-        Execute.exitAllowed = true;
-        System.setProperty("user.dir", userDir);
-    }
-
-    public void testListCommands() throws Exception {
-        PrintStream oldOut = System.out;
-        
-        ByteArrayOutputStream baos = new ByteArrayOutputStream();
-        PrintStream capturedOut = new PrintStream(baos); 
-        System.setOut(capturedOut);
-
-        try {
-            Execute.main(new String [] {});            
-        } catch (RuntimeException re) {
-            assertEquals("0", re.getMessage());
-
-            String s = new String(baos.toByteArray());            
-            assertTrue(s.contains("list"));
-            assertTrue(s.contains("create"));
-            assertTrue(s.contains("destroy"));
-        } finally {
-            System.setOut(oldOut);
-        }
-    }
-    
-    public void testNonexistingCommand() throws Exception {
-        try {
-            Execute.main(new String [] {"bheuaark"});
-        } catch (RuntimeException re) {
-            assertEquals("-1", re.getMessage());
-        }
-    }
-    
-    public void testNoStorageFile() throws Exception {
-        PrintStream oldErr = System.err;
-        
-        ByteArrayOutputStream baos = new ByteArrayOutputStream();
-        PrintStream capturedErr = new PrintStream(baos); 
-        System.setErr(capturedErr);
-
-        try {
-            Execute.main(new String [] {"create"});            
-        } catch (RuntimeException re) {
-            assertEquals("-2", re.getMessage());
-            
-            String s = new String(baos.toByteArray());            
-            assertTrue(s.contains("karaf.instances"));
-            assertTrue(s.contains("instance.properties"));
-        } finally {
-            System.setErr(oldErr);
-        } 
-    }
-    
-    public void testSetDir() throws Exception {
-        Properties oldProps = (Properties) System.getProperties().clone();
-        final File tempFile = createTempDir(getName());
-        assertFalse("Precondition failed", 
-            tempFile.getParentFile().getParentFile().getCanonicalPath().equals(System.getProperty("user.dir")));
-
-        System.setProperty("karaf.instances", tempFile.getCanonicalPath());
-        try {
-            Execute.main(new String [] {"list"});            
-            assertTrue(tempFile.getParentFile().getParentFile().getCanonicalPath().equals(System.getProperty("user.dir")));
-        } finally {
-            System.setProperties(oldProps);
-            assertNull("Postcondition failed", System.getProperty("karaf.instances"));
-            delete(tempFile);
-        }        
-    }
-    
-    private static File createTempDir(String name) throws IOException {
-        final File tempFile = File.createTempFile(name, null);
-        tempFile.delete();
-        tempFile.mkdirs();
-        return tempFile.getCanonicalFile();
-    }
-
-    private static void delete(File tmp) {
-        if (tmp.isDirectory()) {
-            for (File f : tmp.listFiles()) {
-                delete(f);
-            }
-        }
-        tmp.delete();
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/7c2db062/instance/core/NOTICE
----------------------------------------------------------------------
diff --git a/instance/core/NOTICE b/instance/core/NOTICE
deleted file mode 100644
index b70f1f9..0000000
--- a/instance/core/NOTICE
+++ /dev/null
@@ -1,71 +0,0 @@
-Apache Karaf
-Copyright 2010-2014 The Apache Software Foundation
-
-
-I. Included Software
-
-This product includes software developed at
-The Apache Software Foundation (http://www.apache.org/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-The OSGi Alliance (http://www.osgi.org/).
-Copyright (c) OSGi Alliance (2000, 2010).
-Licensed under the Apache License 2.0.
-
-This product includes software developed at
-OW2 (http://www.ow2.org/).
-Licensed under the BSD License.
-
-This product includes software developed at
-OPS4J (http://www.ops4j.org/).
-Licensed under the Apache License 2.0.
-
-This product includes software developed at
-Eclipse Foundation (http://www.eclipse.org/).
-Licensed under the EPL.
-
-This product includes software written by
-Antony Lesuisse.
-Licensed under Public Domain.
-
-
-II. Used Software
-
-This product uses software developed at
-FUSE Source (http://www.fusesource.org/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-AOP Alliance (http://aopalliance.sourceforge.net/).
-Licensed under the Public Domain.
-
-This product uses software developed at
-Tanuki Software (http://www.tanukisoftware.com/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-Jasypt (http://jasypt.sourceforge.net/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-JLine (http://jline.sourceforge.net).
-Licensed under the BSD License.
-
-This product uses software developed at
-SLF4J (http://www.slf4j.org/).
-Licensed under the MIT License.
-
-This product uses software developed at
-SpringSource (http://www.springsource.org/).
-Licensed under the Apache License 2.0.
-
-This product includes software from http://www.json.org.
-Copyright (c) 2002 JSON.org
-
-
-III. License Summary
-- Apache License 2.0
-- BSD License
-- EPL License
-- MIT License


[33/59] [abbrv] [KARAF-2852] Merge kar/core and kar/command

Posted by gn...@apache.org.
http://git-wip-us.apache.org/repos/asf/karaf/blob/f13d140c/kar/src/main/java/org/apache/karaf/kar/command/UninstallKarCommand.java
----------------------------------------------------------------------
diff --git a/kar/src/main/java/org/apache/karaf/kar/command/UninstallKarCommand.java b/kar/src/main/java/org/apache/karaf/kar/command/UninstallKarCommand.java
new file mode 100644
index 0000000..506bdb3
--- /dev/null
+++ b/kar/src/main/java/org/apache/karaf/kar/command/UninstallKarCommand.java
@@ -0,0 +1,45 @@
+/*
+ * 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.karaf.kar.command;
+
+import org.apache.karaf.kar.KarService;
+import org.apache.karaf.kar.command.completers.KarCompleter;
+import org.apache.karaf.shell.api.action.Action;
+import org.apache.karaf.shell.api.action.Argument;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.Completion;
+import org.apache.karaf.shell.api.action.lifecycle.Reference;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+
+@Command(scope = "kar", name = "uninstall", description = "Uninstall a KAR file.")
+@Service
+public class UninstallKarCommand implements Action {
+
+    @Argument(index = 0, name = "name", description = "The name of the KAR file to uninstall.", required = true, multiValued = false)
+    @Completion(KarCompleter.class)
+    private String name;
+
+    @Reference
+    private KarService karService;
+
+    @Override
+    public Object execute() throws Exception {
+        karService.uninstall(name);
+        return null;
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/f13d140c/kar/src/main/java/org/apache/karaf/kar/command/completers/KarCompleter.java
----------------------------------------------------------------------
diff --git a/kar/src/main/java/org/apache/karaf/kar/command/completers/KarCompleter.java b/kar/src/main/java/org/apache/karaf/kar/command/completers/KarCompleter.java
new file mode 100644
index 0000000..539cfaf
--- /dev/null
+++ b/kar/src/main/java/org/apache/karaf/kar/command/completers/KarCompleter.java
@@ -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.karaf.kar.command.completers;
+
+import java.util.List;
+
+import org.apache.karaf.kar.KarService;
+import org.apache.karaf.shell.api.action.lifecycle.Reference;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.apache.karaf.shell.api.console.CommandLine;
+import org.apache.karaf.shell.api.console.Completer;
+import org.apache.karaf.shell.api.console.Session;
+import org.apache.karaf.shell.support.completers.StringsCompleter;
+
+/**
+ * Completer on all installed KAR files.
+ */
+@Service
+public class KarCompleter implements Completer {
+
+    @Reference
+    private KarService karService;
+    
+    public int complete(Session session, CommandLine commandLine, List<String> candidates) {
+        StringsCompleter delegate = new StringsCompleter();
+        try {
+            for (String karName : karService.list()) {
+                delegate.getStrings().add(karName);
+            }
+        } catch (Exception e) {
+            // ignore
+        }
+        return delegate.complete(session, commandLine, candidates);
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/f13d140c/kar/src/main/java/org/apache/karaf/kar/internal/FeatureDetector.java
----------------------------------------------------------------------
diff --git a/kar/src/main/java/org/apache/karaf/kar/internal/FeatureDetector.java b/kar/src/main/java/org/apache/karaf/kar/internal/FeatureDetector.java
new file mode 100644
index 0000000..aca1f53
--- /dev/null
+++ b/kar/src/main/java/org/apache/karaf/kar/internal/FeatureDetector.java
@@ -0,0 +1,87 @@
+/*
+ * 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.karaf.kar.internal;
+
+import java.io.File;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.w3c.dom.Document;
+import org.xml.sax.ErrorHandler;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+
+/**
+ * Simple helper to determine if a file is a feature repo
+ */
+class FeatureDetector {
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(FeatureDetector.class);
+    
+    private DocumentBuilderFactory dbf;
+
+    FeatureDetector() {
+        dbf = DocumentBuilderFactory.newInstance();
+        dbf.setNamespaceAware(true);
+    }
+    /**
+     * Check if a file is a features XML.
+     *
+     * @param artifact the file to check.
+     * @return true if the artifact is a features XML, false else.
+     */
+    boolean isFeaturesRepository(File artifact) {
+        try {
+            if (artifact.isFile() && artifact.getName().endsWith(".xml")) {
+                Document doc = parse(artifact);
+                String name = doc.getDocumentElement().getLocalName();
+                String uri  = doc.getDocumentElement().getNamespaceURI();
+                if ("features".equals(name) && (uri == null || "".equals(uri) || uri.startsWith("http://karaf.apache.org/xmlns/features/v"))) {
+                    return true;
+                }
+            }
+        } catch (Exception e) {
+            LOGGER.debug("File '{}' is not a features file.", artifact.getName(), e);
+        }
+        return false;
+    }
+    
+    /**
+     * Parse a features XML.
+     *
+     * @param artifact the features XML to parse.
+     * @return the parsed document.
+     * @throws Exception in case of parsing failure.
+     */
+    private Document parse(File artifact) throws Exception {
+        DocumentBuilder db = dbf.newDocumentBuilder();
+        db.setErrorHandler(new ErrorHandler() {
+            public void warning(SAXParseException exception) throws SAXException {
+            }
+            public void error(SAXParseException exception) throws SAXException {
+            }
+            public void fatalError(SAXParseException exception) throws SAXException {
+                throw exception;
+            }
+        });
+        return db.parse(artifact);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/f13d140c/kar/src/main/java/org/apache/karaf/kar/internal/Kar.java
----------------------------------------------------------------------
diff --git a/kar/src/main/java/org/apache/karaf/kar/internal/Kar.java b/kar/src/main/java/org/apache/karaf/kar/internal/Kar.java
new file mode 100644
index 0000000..005cd17
--- /dev/null
+++ b/kar/src/main/java/org/apache/karaf/kar/internal/Kar.java
@@ -0,0 +1,203 @@
+/*
+ * 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.karaf.kar.internal;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.jar.Attributes;
+import java.util.jar.JarInputStream;
+import java.util.jar.Manifest;
+import java.util.zip.ZipEntry;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Representation of a Karaf Kar archive
+ * 
+ * A Kar archive is a jar file with a special structure that can be used
+ * to deploy feature repositories, maven repo contents and resources for the
+ * karaf installation.
+ * 
+ * meta-inf/Manifest: 
+ *   Karaf-Feature-Start: (true|false) Controls if the features in the feature repos should be started on deploy
+ *   Karaf-Feature-Repos: (uri)* If present then only the given feature repo urls are added to karaf if it is not
+ *      present then the karaf file is scanned for repo files
+ *      
+ * repository/
+ *   Everything below this directory is treated as a maven repository. On deploy the contents
+ *   will be copied to a directory below data. This directory will then be added to the 
+ *   maven repos of pax url maven
+ *   
+ * resource/
+ *   Everything below this directory will be copied to the karaf base dir on deploy
+ * 
+ */
+public class Kar {
+
+    public static final Logger LOGGER = LoggerFactory.getLogger(KarServiceImpl.class);
+    public static final String MANIFEST_ATTR_KARAF_FEATURE_START = "Karaf-Feature-Start";
+    public static final String MANIFEST_ATTR_KARAF_FEATURE_REPOS = "Karaf-Feature-Repos";
+    private final URI karUri;
+    private boolean shouldInstallFeatures;
+    private List<URI> featureRepos;
+
+    public Kar(URI karUri) {
+        this.karUri = karUri;
+    }
+
+    /**
+     * Extract a kar from a given URI into a repository dir and resource dir
+     * and populate shouldInstallFeatures and featureRepos
+     *
+     * @param repoDir directory to write the repository contents of the kar to
+     * @param resourceDir directory to write the resource contents of the kar to
+     */
+    public void extract(File repoDir, File resourceDir) {
+        InputStream is = null;
+        JarInputStream zipIs = null;
+        FeatureDetector featureDetector = new FeatureDetector();
+        this.featureRepos = new ArrayList<URI>();
+        this.shouldInstallFeatures = true;
+
+        try {
+            is = karUri.toURL().openStream();
+            repoDir.mkdirs();
+
+            if (!repoDir.isDirectory()) {
+                throw new RuntimeException("The KAR file " + karUri + " is already installed");
+            }
+
+            LOGGER.debug("Uncompress the KAR file {} into directory {}", karUri, repoDir);
+            zipIs = new JarInputStream(is);
+            boolean scanForRepos = true;
+
+            Manifest manifest = zipIs.getManifest();
+            if (manifest != null) {
+                Attributes attr = manifest.getMainAttributes();
+                String featureStartSt = (String)attr
+                    .get(new Attributes.Name(MANIFEST_ATTR_KARAF_FEATURE_START));
+                if ("false".equals(featureStartSt)) {
+                    shouldInstallFeatures = false;
+                }
+                String featureReposAttr = (String)attr
+                    .get(new Attributes.Name(MANIFEST_ATTR_KARAF_FEATURE_REPOS));
+                if (featureReposAttr != null) {
+                    featureRepos.add(new URI(featureReposAttr));
+                    scanForRepos = false;
+                }
+            }
+
+            ZipEntry entry = zipIs.getNextEntry();
+            while (entry != null) {
+                if (entry.getName().startsWith("repository")) {
+                    String path = entry.getName().substring("repository/".length());
+                    File destFile = new File(repoDir, path);
+                    extract(zipIs, entry, destFile);
+                    if (scanForRepos && featureDetector.isFeaturesRepository(destFile)) {
+                        featureRepos.add(destFile.toURI());
+                    }
+                }
+
+                if (entry.getName().startsWith("resource")) {
+                    String path = entry.getName().substring("resource/".length());
+                    File destFile = new File(resourceDir, path);
+                    extract(zipIs, entry, destFile);
+                }
+                entry = zipIs.getNextEntry();
+            }
+        } catch (Exception e) {
+            throw new RuntimeException("Error extracting kar file " + karUri + " into dir " + repoDir + ": " + e.getMessage(), e);
+        } finally {
+            closeStream(zipIs);
+            closeStream(is);
+        }
+    }
+
+    /**
+     * Extract an entry from a KAR file
+     * 
+     * @param is
+     * @param zipEntry
+     * @param dest
+     * @return
+     * @throws Exception
+     */
+    private static File extract(InputStream is, ZipEntry zipEntry, File dest) throws Exception {
+        if (zipEntry.isDirectory()) {
+            LOGGER.debug("Creating directory {}", dest.getName());
+            dest.mkdirs();
+        } else {
+            dest.getParentFile().mkdirs();
+            FileOutputStream out = new FileOutputStream(dest);
+            copyStream(is, out);
+            out.close();
+        }
+        return dest;
+    }
+
+    private static void closeStream(InputStream is) {
+        if (is != null) {
+            try {
+                is.close();
+            } catch (IOException e) {
+                LOGGER.warn("Error closing stream", e);
+            }
+        }
+    }
+
+    static long copyStream(InputStream input, OutputStream output) throws IOException {
+        byte[] buffer = new byte[10000];
+        long count = 0;
+        int n = 0;
+        while (-1 != (n = input.read(buffer))) {
+            output.write(buffer, 0, n);
+            count += n;
+        }
+        return count;
+    }
+
+    public String getKarName() {
+        try {
+            String karName = new File(karUri.toURL().getFile()).getName();
+            karName = karName.substring(0, karName.lastIndexOf("."));
+            return karName;
+        } catch (MalformedURLException e) {
+            throw new RuntimeException("Invalid kar URI " + karUri, e);
+        }
+    }
+    
+    public URI getKarUri() {
+        return karUri;
+    }
+
+    public boolean isShouldInstallFeatures() {
+        return shouldInstallFeatures;
+    }
+
+    public List<URI> getFeatureRepos() {
+        return featureRepos;
+    } 
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/f13d140c/kar/src/main/java/org/apache/karaf/kar/internal/KarServiceImpl.java
----------------------------------------------------------------------
diff --git a/kar/src/main/java/org/apache/karaf/kar/internal/KarServiceImpl.java b/kar/src/main/java/org/apache/karaf/kar/internal/KarServiceImpl.java
new file mode 100644
index 0000000..0f86466
--- /dev/null
+++ b/kar/src/main/java/org/apache/karaf/kar/internal/KarServiceImpl.java
@@ -0,0 +1,382 @@
+/*
+ * 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.karaf.kar.internal;
+
+import java.io.BufferedOutputStream;
+import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.PrintStream;
+import java.io.UnsupportedEncodingException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.EnumSet;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.jar.JarEntry;
+import java.util.jar.JarOutputStream;
+import java.util.jar.Manifest;
+
+import org.apache.karaf.features.BundleInfo;
+import org.apache.karaf.features.ConfigFileInfo;
+import org.apache.karaf.features.Dependency;
+import org.apache.karaf.features.Feature;
+import org.apache.karaf.features.FeaturesService;
+import org.apache.karaf.features.Repository;
+import org.apache.karaf.kar.KarService;
+import org.apache.karaf.util.maven.Parser;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Implementation of the KAR service.
+ */
+public class KarServiceImpl implements KarService {
+    private static final String FEATURE_CONFIG_FILE = "features.cfg";
+    private static final Logger LOGGER = LoggerFactory.getLogger(KarServiceImpl.class);
+
+    private File storage;
+    private File base;
+    private FeaturesService featuresService;
+    
+    private boolean noAutoRefreshBundles;
+
+    public KarServiceImpl(String karafBase, FeaturesService featuresService) {
+        this.base = new File(karafBase);
+        this.storage = new File(this.base, "data" + File.separator + "kar");
+        this.featuresService = featuresService;
+        this.storage.mkdirs();
+        if (!storage.isDirectory()) {
+            throw new IllegalStateException("KAR storage " + storage + " is not a directory");
+        }
+    }
+    
+    @Override
+    public void install(URI karUri) throws Exception {
+        String karName = new Kar(karUri).getKarName();
+        LOGGER.debug("Installing KAR {} from {}", karName, karUri);
+        File karDir = new File(storage, karName);
+        install(karUri, karDir, base);
+    }
+    
+    @Override
+    public void install(URI karUri, File repoDir, File resourceDir) throws Exception {
+        Kar kar = new Kar(karUri);
+        kar.extract(repoDir, resourceDir);
+        writeToFile(kar.getFeatureRepos(), new File(repoDir, FEATURE_CONFIG_FILE));
+        for (URI uri : kar.getFeatureRepos()) {
+            addToFeaturesRepositories(uri);
+        }
+        if (kar.isShouldInstallFeatures()) {
+            installFeatures(kar.getFeatureRepos());
+        }
+
+    }
+
+
+    private List<URI> readFromFile(File repoListFile) {
+        ArrayList<URI> uriList = new ArrayList<URI>();
+        FileReader fr = null;
+        try {
+            fr = new FileReader(repoListFile);
+            BufferedReader br = new BufferedReader(fr);
+            String line;
+            while ((line = br.readLine()) != null) {
+                uriList.add(new URI(line));
+            }
+        } catch (Exception e) {
+            throw new RuntimeException("Error reading repo list from file " + repoListFile.getAbsolutePath(), e);
+        } finally {
+            try {
+                fr.close();
+            } catch (IOException e) {
+                LOGGER.warn("Error closing reader for file " + repoListFile, e);
+            }
+        }
+        return uriList;
+    }
+    
+    private void writeToFile(List<URI> featuresRepositoriesInKar, File repoListFile) {
+        FileOutputStream fos = null;
+        PrintStream ps = null;
+        try {
+            fos = new FileOutputStream(repoListFile);
+            ps = new PrintStream(fos);
+            for (URI uri : featuresRepositoriesInKar) {
+                ps.println(uri);
+            }
+            ps.close();
+            fos.close();
+        } catch (Exception e) {
+            throw new RuntimeException("Error writing feature repo list to file " + repoListFile.getAbsolutePath(), e);
+        } finally {
+            closeStream(ps);
+            closeStream(fos);
+        }
+    }
+
+    private void deleteRecursively(File dir) {
+        if (dir.isDirectory()) {
+            File[] children = dir.listFiles();
+            for (File child : children) {
+                deleteRecursively(child);
+            }
+        }
+        dir.delete();
+    }
+
+    @Override
+    public void uninstall(String karName) throws Exception {
+        File karDir = new File(storage, karName);
+
+        if (!karDir.exists()) {
+            throw new IllegalArgumentException("The KAR " + karName + " is not installed");
+        }
+
+        List<URI> featuresRepositories = readFromFile(new File(karDir, FEATURE_CONFIG_FILE));
+        uninstallFeatures(featuresRepositories);
+        for (URI featuresRepository : featuresRepositories) {
+            featuresService.removeRepository(featuresRepository);
+        }
+        
+        deleteRecursively(karDir);
+    }
+    
+    @Override
+    public List<String> list() throws Exception {
+        List<String> kars = new ArrayList<String>();
+        for (File kar : storage.listFiles()) {
+            if (kar.isDirectory()) {
+                kars.add(kar.getName());
+            }
+        }
+        return kars;
+    }
+
+
+
+    /**
+     * Add an URI to the list of features repositories.
+     *
+     * @param uri the URI to add.
+     * @throws Exception in case of add failure.
+     */
+    private void addToFeaturesRepositories(URI uri) throws Exception {
+        try {
+            featuresService.removeRepository(uri);
+            featuresService.addRepository(uri);
+            LOGGER.info("Added feature repository '{}'", uri);
+        } catch (Exception e) {
+            LOGGER.warn("Unable to add repository '{}'", uri, e);
+        }
+    }
+
+    /**
+     * Install all features contained in the list of features XML.
+     *
+     * @param featuresRepositories the list of features XML.
+     */
+    private void installFeatures(List<URI> featuresRepositories) throws Exception {
+        for (Repository repository : featuresService.listRepositories()) {
+            for (URI karFeatureRepoUri : featuresRepositories) {
+                if (repository.getURI().equals(karFeatureRepoUri)) {
+                    try {
+                        for (Feature feature : repository.getFeatures()) {
+                            try {
+                                LOGGER.debug("noAutoRefreshBundles is " + isNoAutoRefreshBundles());
+                                if (isNoAutoRefreshBundles()) {
+                                    featuresService.installFeature(feature, EnumSet.of(FeaturesService.Option.NoAutoRefreshBundles));
+                                } else {
+                                    featuresService.installFeature(feature, EnumSet.noneOf(FeaturesService.Option.class));
+                                }
+                            } catch (Exception e) {
+                                LOGGER.warn("Unable to install Kar feature {}", feature.getName() + "/" + feature.getVersion(), e);
+                            }
+                        }
+                    } catch (Exception e) {
+                        LOGGER.warn("Can't get features for KAR {}", karFeatureRepoUri, e);
+                    }
+                }
+            }
+        }
+    }
+    
+    @Override
+    public void create(String repoName, List<String> features, PrintStream console) {
+        FileOutputStream fos = null;
+        JarOutputStream jos = null;
+        try {
+            Repository repo = featuresService.getRepository(repoName);
+            if (repo == null) {
+                throw new RuntimeException("Could not find a repository with name " + repoName);
+            }
+            String karPath = storage + File.separator + repoName + ".kar";
+            File karFile = new File(karPath);
+            karFile.getParentFile().mkdirs();
+            fos = new FileOutputStream(karFile);
+            Manifest manifest = createNonAutoStartManifest(repo.getURI());
+            jos = new JarOutputStream(new BufferedOutputStream(fos, 100000), manifest);
+            
+            Map<URI, Integer> locationMap = new HashMap<URI, Integer>();
+            copyResourceToJar(jos, repo.getURI(), locationMap);
+        
+            Map<String, Feature> featureMap = new HashMap<String, Feature>();
+            for (Feature feature : repo.getFeatures()) {
+                featureMap.put(feature.getName(), feature);
+            }
+            
+            Set<Feature> featuresToCopy = getFeatures(featureMap, features, 1);
+            
+            for (Feature feature : featuresToCopy) {
+                if (console != null)
+                    console.println("Adding feature " + feature.getName());
+                copyFeatureToJar(jos, feature, locationMap);
+            }
+
+            if (console != null)
+                console.println("Kar file created : " + karPath);
+        } catch (Exception e) {
+            throw new RuntimeException("Error creating kar: " + e.getMessage(), e);
+        } finally {
+            closeStream(jos);
+            closeStream(fos);
+        }
+        
+    }
+
+    private Set<Feature> getFeatures(Map<String, Feature> featureMap, List<String> features, int depth) {
+        Set<Feature> featureSet = new HashSet<Feature>();
+        if (depth > 5) {
+            // Break after some recursions to avoid endless loops 
+            return featureSet;
+        }
+        if (features == null) {
+            featureSet.addAll(featureMap.values());
+            return featureSet;
+        }
+        for (String featureName : features) {
+            Feature feature = featureMap.get(featureName);
+            if (feature == null) {
+                System.out.println("Feature " + featureName + " not found in repository.");
+                //throw new RuntimeException();
+            } else {
+                featureSet.add(feature);
+                List<Dependency> deps = feature.getDependencies();
+                List<String> depNames = new ArrayList<String>();
+                for (Dependency dependency : deps) {
+                    depNames.add(dependency.getName());
+                }
+                featureSet.addAll(getFeatures(featureMap, depNames, depth ++));
+            }
+        }
+        return featureSet;
+    }
+
+    private Manifest createNonAutoStartManifest(URI repoUri) throws UnsupportedEncodingException, IOException {
+        String manifestSt = "Manifest-Version: 1.0\n" +
+            Kar.MANIFEST_ATTR_KARAF_FEATURE_START +": false\n" +
+            Kar.MANIFEST_ATTR_KARAF_FEATURE_REPOS + ": " + repoUri.toString() + "\n";
+        InputStream manifestIs = new ByteArrayInputStream(manifestSt.getBytes("UTF-8"));
+        Manifest manifest = new Manifest(manifestIs);
+        return manifest;
+    }
+
+    private void closeStream(OutputStream os) {
+        if (os != null) {
+            try {
+                os.close();
+            } catch (IOException e) {
+                LOGGER.warn("Error closing stream", e);
+            }
+        }
+    }
+
+    private void copyFeatureToJar(JarOutputStream jos, Feature feature, Map<URI, Integer> locationMap)
+        throws URISyntaxException {
+        for (BundleInfo bundleInfo : feature.getBundles()) {
+            URI location = new URI(bundleInfo.getLocation());
+            copyResourceToJar(jos, location, locationMap);
+        }
+        for (ConfigFileInfo configFileInfo : feature.getConfigurationFiles()) {
+            URI location = new URI(configFileInfo.getLocation());
+            copyResourceToJar(jos, location, locationMap);
+        }
+    }
+
+    private void copyResourceToJar(JarOutputStream jos, URI location, Map<URI, Integer> locationMap) {
+        if (locationMap.containsKey(location)) {
+            return;
+        }
+        try {
+            String noPrefixLocation = location.toString().substring(location.toString().lastIndexOf(":") + 1);
+            Parser parser = new Parser(noPrefixLocation);
+            InputStream is = location.toURL().openStream();
+            String path = "repository/" + parser.getArtifactPath();
+            jos.putNextEntry(new JarEntry(path));
+            Kar.copyStream(is, jos);
+            is.close();
+            locationMap.put(location, 1);
+        } catch (Exception e) {
+            LOGGER.error("Error adding " + location, e);
+        }
+    }
+
+    /**
+     * Uninstall all features contained in the list of features XML.
+     *
+     * @param featuresRepositories the list of features XML.
+     */
+    private void uninstallFeatures(List<URI> featuresRepositories) throws Exception {
+        for (Repository repository : featuresService.listRepositories()) {
+            for (URI karFeatureRepoUri : featuresRepositories) {
+                if (repository.getURI().equals(karFeatureRepoUri)) {
+                    try {
+                        for (Feature feature : repository.getFeatures()) {
+                            try {
+                                featuresService.uninstallFeature(feature.getName(), feature.getVersion());
+                            } catch (Exception e) {
+                                LOGGER.warn("Unable to uninstall Kar feature {}", feature.getName() + "/" + feature.getVersion(), e);
+                            }
+                        }
+                    } catch (Exception e) {
+                        LOGGER.warn("Can't get features for KAR {}", karFeatureRepoUri, e);
+                    }
+                }
+            }
+        }
+    }
+
+    public boolean isNoAutoRefreshBundles() {
+        return noAutoRefreshBundles;
+    }
+
+    public void setNoAutoRefreshBundles(boolean noAutoRefreshBundles) {
+        this.noAutoRefreshBundles = noAutoRefreshBundles;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/f13d140c/kar/src/main/java/org/apache/karaf/kar/internal/KarsMBeanImpl.java
----------------------------------------------------------------------
diff --git a/kar/src/main/java/org/apache/karaf/kar/internal/KarsMBeanImpl.java b/kar/src/main/java/org/apache/karaf/kar/internal/KarsMBeanImpl.java
new file mode 100644
index 0000000..b274e21
--- /dev/null
+++ b/kar/src/main/java/org/apache/karaf/kar/internal/KarsMBeanImpl.java
@@ -0,0 +1,72 @@
+/*
+ * 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.karaf.kar.internal;
+
+import org.apache.karaf.kar.KarService;
+import org.apache.karaf.kar.KarsMBean;
+
+import javax.management.MBeanException;
+import javax.management.NotCompliantMBeanException;
+import javax.management.StandardMBean;
+import java.net.URI;
+import java.util.List;
+
+public class KarsMBeanImpl extends StandardMBean implements KarsMBean {
+
+    private KarService karService;
+
+    public KarsMBeanImpl() throws NotCompliantMBeanException {
+        super(KarsMBean.class);
+    }
+
+    public List<String> getKars() throws MBeanException {
+        try {
+            return karService.list();
+        } catch (Exception e) {
+            throw new MBeanException(null, e.getMessage());
+        }
+    }
+
+    public void create(String repoName, List<String> features) {
+        karService.create(repoName, features, null);
+    }
+
+    public void install(String url) throws MBeanException {
+        try {
+            karService.install(new URI(url));
+        } catch (Exception e) {
+            throw new MBeanException(null, e.getMessage());
+        }
+    }
+
+    public void uninstall(String name) throws MBeanException {
+        try {
+            karService.uninstall(name);
+        } catch (Exception e) {
+            throw new MBeanException(null, e.getMessage());
+        }
+    }
+
+    public KarService getKarService() {
+        return karService;
+    }
+
+    public void setKarService(KarService karService) {
+        this.karService = karService;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/f13d140c/kar/src/main/java/org/apache/karaf/kar/internal/osgi/Activator.java
----------------------------------------------------------------------
diff --git a/kar/src/main/java/org/apache/karaf/kar/internal/osgi/Activator.java b/kar/src/main/java/org/apache/karaf/kar/internal/osgi/Activator.java
new file mode 100644
index 0000000..05a1b59
--- /dev/null
+++ b/kar/src/main/java/org/apache/karaf/kar/internal/osgi/Activator.java
@@ -0,0 +1,54 @@
+/*
+ * 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.karaf.kar.internal.osgi;
+
+import org.apache.karaf.features.FeaturesService;
+import org.apache.karaf.kar.KarService;
+import org.apache.karaf.kar.internal.KarServiceImpl;
+import org.apache.karaf.kar.internal.KarsMBeanImpl;
+import org.apache.karaf.util.tracker.BaseActivator;
+import org.osgi.service.cm.ManagedService;
+
+public class Activator extends BaseActivator implements ManagedService {
+
+    @Override
+    protected void doOpen() throws Exception {
+        manage("org.apache.karaf.kar");
+        trackService(FeaturesService.class);
+    }
+
+    protected void doStart() throws Exception {
+        FeaturesService featuresService = getTrackedService(FeaturesService.class);
+        if (featuresService == null) {
+            return;
+        }
+
+        boolean noAutoRefreshBundles = getBoolean("noAutoRefreshBundles", false);
+
+        KarServiceImpl karService = new KarServiceImpl(
+                System.getProperty("karaf.base"),
+                featuresService
+        );
+        karService.setNoAutoRefreshBundles(noAutoRefreshBundles);
+        register(KarService.class, karService);
+
+        KarsMBeanImpl mbean = new KarsMBeanImpl();
+        mbean.setKarService(karService);
+        registerMBean(mbean, "type=kar");
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/f13d140c/kar/src/main/resources/OSGI-INF/bundle.info
----------------------------------------------------------------------
diff --git a/kar/src/main/resources/OSGI-INF/bundle.info b/kar/src/main/resources/OSGI-INF/bundle.info
new file mode 100644
index 0000000..7056453
--- /dev/null
+++ b/kar/src/main/resources/OSGI-INF/bundle.info
@@ -0,0 +1,19 @@
+h1. Synopsis
+
+${project.name}
+
+${project.description}
+
+Maven URL:
+[mvn:${project.groupId}/${project.artifactId}/${project.version}]
+
+h1. Description
+
+This bundle is the core implementation of the Karaf kar support.
+
+Karaf Archives (KAR) is an artifact (zip file) shipping a features XML and the associated bundles or configuration
+files.
+
+h1. See also
+
+KAR - section of the Karaf User Guide


[32/59] [abbrv] git commit: [KARAF-2852] Merge diagnostic/core and diagnostic/command

Posted by gn...@apache.org.
[KARAF-2852] Merge diagnostic/core and diagnostic/command

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

Branch: refs/heads/master
Commit: 886863a28a3ed666a149d7566034f8826094037f
Parents: 7c2db06
Author: Guillaume Nodet <gn...@gmail.com>
Authored: Wed Apr 9 23:01:24 2014 +0200
Committer: Guillaume Nodet <gn...@gmail.com>
Committed: Thu Apr 10 16:00:59 2014 +0200

----------------------------------------------------------------------
 .../standard/src/main/feature/feature.xml       |   1 -
 diagnostic/NOTICE                               |  71 +++++
 diagnostic/command/NOTICE                       |  71 -----
 diagnostic/command/pom.xml                      |  90 ------
 .../karaf/diagnostic/command/DumpCommand.java   |  97 -------
 .../src/main/resources/OSGI-INF/bundle.info     |  19 --
 diagnostic/core/NOTICE                          |  71 -----
 diagnostic/core/pom.xml                         | 109 -------
 .../diagnostic/core/DiagnosticDumpMBean.java    |  42 ---
 .../karaf/diagnostic/core/DumpDestination.java  |  42 ---
 .../karaf/diagnostic/core/DumpProvider.java     |  29 --
 .../common/ClosingEntryOutputStreamWrapper.java |  75 -----
 .../core/common/DirectoryDumpDestination.java   |  55 ----
 .../core/common/TextDumpProvider.java           |  66 -----
 .../core/common/ZipDumpDestination.java         |  79 -----
 .../core/internal/BundleDumpProvider.java       |  85 ------
 .../core/internal/DiagnosticDumpMBeanImpl.java  |  89 ------
 .../core/internal/EnvironmentDumpProvider.java  | 291 -------------------
 .../core/internal/FeaturesDumpProvider.java     |  79 -----
 .../core/internal/HeapDumpProvider.java         |  68 -----
 .../core/internal/LogDumpProvider.java          |  98 -------
 .../core/internal/MemoryDumpProvider.java       |  54 ----
 .../core/internal/ThreadDumpProvider.java       | 118 --------
 .../core/internal/osgi/Activator.java           | 131 ---------
 .../src/main/resources/OSGI-INF/bundle.info     |  18 --
 diagnostic/pom.xml                              |  93 +++++-
 .../karaf/diagnostic/command/DumpCommand.java   |  97 +++++++
 .../diagnostic/core/DiagnosticDumpMBean.java    |  42 +++
 .../karaf/diagnostic/core/DumpDestination.java  |  42 +++
 .../karaf/diagnostic/core/DumpProvider.java     |  29 ++
 .../common/ClosingEntryOutputStreamWrapper.java |  75 +++++
 .../core/common/DirectoryDumpDestination.java   |  55 ++++
 .../core/common/TextDumpProvider.java           |  66 +++++
 .../core/common/ZipDumpDestination.java         |  79 +++++
 .../core/internal/BundleDumpProvider.java       |  85 ++++++
 .../core/internal/DiagnosticDumpMBeanImpl.java  |  89 ++++++
 .../core/internal/EnvironmentDumpProvider.java  | 291 +++++++++++++++++++
 .../core/internal/FeaturesDumpProvider.java     |  79 +++++
 .../core/internal/HeapDumpProvider.java         |  68 +++++
 .../core/internal/LogDumpProvider.java          |  98 +++++++
 .../core/internal/MemoryDumpProvider.java       |  54 ++++
 .../core/internal/ThreadDumpProvider.java       | 118 ++++++++
 .../core/internal/osgi/Activator.java           | 131 +++++++++
 .../src/main/resources/OSGI-INF/bundle.info     |  18 ++
 44 files changed, 1672 insertions(+), 1885 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/karaf/blob/886863a2/assemblies/features/standard/src/main/feature/feature.xml
----------------------------------------------------------------------
diff --git a/assemblies/features/standard/src/main/feature/feature.xml b/assemblies/features/standard/src/main/feature/feature.xml
index 830ba9d..af81c40 100644
--- a/assemblies/features/standard/src/main/feature/feature.xml
+++ b/assemblies/features/standard/src/main/feature/feature.xml
@@ -129,7 +129,6 @@
 
     <feature name="diagnostic" description="Provide Diagnostic support" version="${project.version}">
         <bundle start-level="30" start="true">mvn:org.apache.karaf.diagnostic/org.apache.karaf.diagnostic.core/${project.version}</bundle>
-        <bundle start-level="30" start="true">mvn:org.apache.karaf.diagnostic/org.apache.karaf.diagnostic.command/${project.version}</bundle>
     </feature>
 
     <feature name="instance" description="Provide Instance support" version="${project.version}">

http://git-wip-us.apache.org/repos/asf/karaf/blob/886863a2/diagnostic/NOTICE
----------------------------------------------------------------------
diff --git a/diagnostic/NOTICE b/diagnostic/NOTICE
new file mode 100644
index 0000000..b70f1f9
--- /dev/null
+++ b/diagnostic/NOTICE
@@ -0,0 +1,71 @@
+Apache Karaf
+Copyright 2010-2014 The Apache Software Foundation
+
+
+I. Included Software
+
+This product includes software developed at
+The Apache Software Foundation (http://www.apache.org/).
+Licensed under the Apache License 2.0.
+
+This product uses software developed at
+The OSGi Alliance (http://www.osgi.org/).
+Copyright (c) OSGi Alliance (2000, 2010).
+Licensed under the Apache License 2.0.
+
+This product includes software developed at
+OW2 (http://www.ow2.org/).
+Licensed under the BSD License.
+
+This product includes software developed at
+OPS4J (http://www.ops4j.org/).
+Licensed under the Apache License 2.0.
+
+This product includes software developed at
+Eclipse Foundation (http://www.eclipse.org/).
+Licensed under the EPL.
+
+This product includes software written by
+Antony Lesuisse.
+Licensed under Public Domain.
+
+
+II. Used Software
+
+This product uses software developed at
+FUSE Source (http://www.fusesource.org/).
+Licensed under the Apache License 2.0.
+
+This product uses software developed at
+AOP Alliance (http://aopalliance.sourceforge.net/).
+Licensed under the Public Domain.
+
+This product uses software developed at
+Tanuki Software (http://www.tanukisoftware.com/).
+Licensed under the Apache License 2.0.
+
+This product uses software developed at
+Jasypt (http://jasypt.sourceforge.net/).
+Licensed under the Apache License 2.0.
+
+This product uses software developed at
+JLine (http://jline.sourceforge.net).
+Licensed under the BSD License.
+
+This product uses software developed at
+SLF4J (http://www.slf4j.org/).
+Licensed under the MIT License.
+
+This product uses software developed at
+SpringSource (http://www.springsource.org/).
+Licensed under the Apache License 2.0.
+
+This product includes software from http://www.json.org.
+Copyright (c) 2002 JSON.org
+
+
+III. License Summary
+- Apache License 2.0
+- BSD License
+- EPL License
+- MIT License

http://git-wip-us.apache.org/repos/asf/karaf/blob/886863a2/diagnostic/command/NOTICE
----------------------------------------------------------------------
diff --git a/diagnostic/command/NOTICE b/diagnostic/command/NOTICE
deleted file mode 100644
index b70f1f9..0000000
--- a/diagnostic/command/NOTICE
+++ /dev/null
@@ -1,71 +0,0 @@
-Apache Karaf
-Copyright 2010-2014 The Apache Software Foundation
-
-
-I. Included Software
-
-This product includes software developed at
-The Apache Software Foundation (http://www.apache.org/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-The OSGi Alliance (http://www.osgi.org/).
-Copyright (c) OSGi Alliance (2000, 2010).
-Licensed under the Apache License 2.0.
-
-This product includes software developed at
-OW2 (http://www.ow2.org/).
-Licensed under the BSD License.
-
-This product includes software developed at
-OPS4J (http://www.ops4j.org/).
-Licensed under the Apache License 2.0.
-
-This product includes software developed at
-Eclipse Foundation (http://www.eclipse.org/).
-Licensed under the EPL.
-
-This product includes software written by
-Antony Lesuisse.
-Licensed under Public Domain.
-
-
-II. Used Software
-
-This product uses software developed at
-FUSE Source (http://www.fusesource.org/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-AOP Alliance (http://aopalliance.sourceforge.net/).
-Licensed under the Public Domain.
-
-This product uses software developed at
-Tanuki Software (http://www.tanukisoftware.com/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-Jasypt (http://jasypt.sourceforge.net/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-JLine (http://jline.sourceforge.net).
-Licensed under the BSD License.
-
-This product uses software developed at
-SLF4J (http://www.slf4j.org/).
-Licensed under the MIT License.
-
-This product uses software developed at
-SpringSource (http://www.springsource.org/).
-Licensed under the Apache License 2.0.
-
-This product includes software from http://www.json.org.
-Copyright (c) 2002 JSON.org
-
-
-III. License Summary
-- Apache License 2.0
-- BSD License
-- EPL License
-- MIT License

http://git-wip-us.apache.org/repos/asf/karaf/blob/886863a2/diagnostic/command/pom.xml
----------------------------------------------------------------------
diff --git a/diagnostic/command/pom.xml b/diagnostic/command/pom.xml
deleted file mode 100644
index 28502f0..0000000
--- a/diagnostic/command/pom.xml
+++ /dev/null
@@ -1,90 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-
-    <!--
-
-        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.
-    -->
-
-    <modelVersion>4.0.0</modelVersion>
-
-    <parent>
-        <groupId>org.apache.karaf.diagnostic</groupId>
-        <artifactId>diagnostic</artifactId>
-        <version>4.0.0-SNAPSHOT</version>
-        <relativePath>../pom.xml</relativePath>
-    </parent>
-
-    <artifactId>org.apache.karaf.diagnostic.command</artifactId>
-    <packaging>bundle</packaging>
-    <name>Apache Karaf :: Diagnostic :: Command</name>
-    <description>This bundle provides Karaf diagnostic shell commands.</description>
-
-    <properties>
-        <appendedResourcesDirectory>${basedir}/../../etc/appended-resources</appendedResourcesDirectory>
-    </properties>
-
-    <dependencies>
-        <dependency>
-            <groupId>org.osgi</groupId>
-            <artifactId>org.osgi.core</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.osgi</groupId>
-            <artifactId>org.osgi.compendium</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.karaf.diagnostic</groupId>
-            <artifactId>org.apache.karaf.diagnostic.core</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.karaf.shell</groupId>
-            <artifactId>org.apache.karaf.shell.core</artifactId>
-        </dependency>
-    </dependencies>
-
-    <build>
-        <resources>
-            <resource>
-                <directory>${project.basedir}/src/main/resources</directory>
-                <includes>
-                    <include>**/*</include>
-                </includes>
-            </resource>
-            <resource>
-                <directory>${project.basedir}/src/main/resources</directory>
-                <filtering>true</filtering>
-                <includes>
-                    <include>**/*.info</include>
-                </includes>
-            </resource>
-        </resources>
-        <plugins>
-            <plugin>
-                <groupId>org.apache.felix</groupId>
-                <artifactId>maven-bundle-plugin</artifactId>
-                <configuration>
-                    <instructions>
-                        <Karaf-Commands>*</Karaf-Commands>
-                    </instructions>
-                </configuration>
-            </plugin>
-        </plugins>
-    </build>
-
-</project>

http://git-wip-us.apache.org/repos/asf/karaf/blob/886863a2/diagnostic/command/src/main/java/org/apache/karaf/diagnostic/command/DumpCommand.java
----------------------------------------------------------------------
diff --git a/diagnostic/command/src/main/java/org/apache/karaf/diagnostic/command/DumpCommand.java b/diagnostic/command/src/main/java/org/apache/karaf/diagnostic/command/DumpCommand.java
deleted file mode 100644
index 3f6c607..0000000
--- a/diagnostic/command/src/main/java/org/apache/karaf/diagnostic/command/DumpCommand.java
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * 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.karaf.diagnostic.command;
-
-import java.io.File;
-import java.text.SimpleDateFormat;
-import java.util.Date;
-import java.util.LinkedList;
-import java.util.List;
-
-import org.apache.karaf.diagnostic.core.DumpDestination;
-import org.apache.karaf.diagnostic.core.DumpProvider;
-import org.apache.karaf.diagnostic.core.common.DirectoryDumpDestination;
-import org.apache.karaf.diagnostic.core.common.ZipDumpDestination;
-import org.apache.karaf.shell.api.action.Action;
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Option;
-import org.apache.karaf.shell.api.action.lifecycle.Reference;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-
-/**
- * Command to create dump from shell.
- */
-@Command(scope = "dev", name = "dump-create", description = "Creates zip archive with diagnostic info.")
-@Service
-public class DumpCommand implements Action {
-
-    /**
-     * Output format of the filename if not defined otherwise
-     */
-    private SimpleDateFormat dumpFormat = new SimpleDateFormat("yyyy-MM-dd_HHmmss");
-
-    /**
-     * Directory switch.
-     */
-    @Option(name = "-d", aliases = "--directory", description = "Creates dump in a directory in place of a ZIP archive")
-    boolean directory;
-
-    /**
-     * Name of created directory or archive.
-     */
-    @Argument(name = "name", description = "Name of created zip or directory", required = false)
-    String fileName;
-
-    @Reference
-    List<DumpProvider> providers;
-
-    @Override
-    public Object execute() throws Exception {
-        DumpDestination destination;
-
-        if (providers.isEmpty()) {
-            System.out.println("Unable to create dump. No providers were found");
-            return null;
-        }
-
-        // create default file name if none provided
-        if (fileName == null || fileName.trim().length() == 0) {
-            fileName = dumpFormat.format(new Date());
-            if (!directory) {
-                fileName += ".zip";
-            }
-        }
-        File target = new File(fileName);
-
-        // if directory switch is on, create dump in directory
-        if (directory) {
-            destination = new DirectoryDumpDestination(target);
-        } else {
-            destination = new ZipDumpDestination(target);
-        }
-
-        for (DumpProvider provider : providers) {
-            provider.createDump(destination);
-        }
-        destination.save();
-        System.out.println("Diagnostic dump created at " + target.getAbsolutePath() + ".");
-
-        return null;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/886863a2/diagnostic/command/src/main/resources/OSGI-INF/bundle.info
----------------------------------------------------------------------
diff --git a/diagnostic/command/src/main/resources/OSGI-INF/bundle.info b/diagnostic/command/src/main/resources/OSGI-INF/bundle.info
deleted file mode 100644
index 93d0674..0000000
--- a/diagnostic/command/src/main/resources/OSGI-INF/bundle.info
+++ /dev/null
@@ -1,19 +0,0 @@
-h1. Synopsis
-
-${project.name}
-
-${project.description}
-
-Maven URL:
-[mvn:${project.groupId}/${project.artifactId}/${project.version}]
-
-h1. Description
-This bundle provides the Karaf shell commands for the Karaf diagnostic.
-
-The current provided command is:
-
-* dev:create-dump -
-
-h1. See also
-
-Diagnostic - section of the Karaf User Guide.

http://git-wip-us.apache.org/repos/asf/karaf/blob/886863a2/diagnostic/core/NOTICE
----------------------------------------------------------------------
diff --git a/diagnostic/core/NOTICE b/diagnostic/core/NOTICE
deleted file mode 100644
index b70f1f9..0000000
--- a/diagnostic/core/NOTICE
+++ /dev/null
@@ -1,71 +0,0 @@
-Apache Karaf
-Copyright 2010-2014 The Apache Software Foundation
-
-
-I. Included Software
-
-This product includes software developed at
-The Apache Software Foundation (http://www.apache.org/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-The OSGi Alliance (http://www.osgi.org/).
-Copyright (c) OSGi Alliance (2000, 2010).
-Licensed under the Apache License 2.0.
-
-This product includes software developed at
-OW2 (http://www.ow2.org/).
-Licensed under the BSD License.
-
-This product includes software developed at
-OPS4J (http://www.ops4j.org/).
-Licensed under the Apache License 2.0.
-
-This product includes software developed at
-Eclipse Foundation (http://www.eclipse.org/).
-Licensed under the EPL.
-
-This product includes software written by
-Antony Lesuisse.
-Licensed under Public Domain.
-
-
-II. Used Software
-
-This product uses software developed at
-FUSE Source (http://www.fusesource.org/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-AOP Alliance (http://aopalliance.sourceforge.net/).
-Licensed under the Public Domain.
-
-This product uses software developed at
-Tanuki Software (http://www.tanukisoftware.com/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-Jasypt (http://jasypt.sourceforge.net/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-JLine (http://jline.sourceforge.net).
-Licensed under the BSD License.
-
-This product uses software developed at
-SLF4J (http://www.slf4j.org/).
-Licensed under the MIT License.
-
-This product uses software developed at
-SpringSource (http://www.springsource.org/).
-Licensed under the Apache License 2.0.
-
-This product includes software from http://www.json.org.
-Copyright (c) 2002 JSON.org
-
-
-III. License Summary
-- Apache License 2.0
-- BSD License
-- EPL License
-- MIT License

http://git-wip-us.apache.org/repos/asf/karaf/blob/886863a2/diagnostic/core/pom.xml
----------------------------------------------------------------------
diff --git a/diagnostic/core/pom.xml b/diagnostic/core/pom.xml
deleted file mode 100644
index 1dee9cd..0000000
--- a/diagnostic/core/pom.xml
+++ /dev/null
@@ -1,109 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-
-    <!--
-
-        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.
-    -->
-
-    <modelVersion>4.0.0</modelVersion>
-
-    <parent>
-        <groupId>org.apache.karaf.diagnostic</groupId>
-        <artifactId>diagnostic</artifactId>
-        <version>4.0.0-SNAPSHOT</version>
-        <relativePath>../pom.xml</relativePath>
-    </parent>
-
-    <artifactId>org.apache.karaf.diagnostic.core</artifactId>
-    <packaging>bundle</packaging>
-    <name>Apache Karaf :: Diagnostic :: Core</name>
-    <description>Core implementation using Karaf diagnostic using the diagnostic common services</description>
-
-    <properties>
-        <appendedResourcesDirectory>${basedir}/../../etc/appended-resources</appendedResourcesDirectory>
-    </properties>
-
-    <dependencies>
-        <dependency>
-            <groupId>org.osgi</groupId>
-            <artifactId>org.osgi.core</artifactId>
-            <scope>provided</scope>
-        </dependency>
-
-        <dependency>
-            <groupId>org.osgi</groupId>
-            <artifactId>org.osgi.compendium</artifactId>
-            <scope>provided</scope>
-        </dependency>
-
-        <dependency>
-            <groupId>org.apache.karaf</groupId>
-            <artifactId>org.apache.karaf.util</artifactId>
-            <scope>provided</scope>
-        </dependency>
-
-        <dependency>
-            <groupId>org.apache.karaf.features</groupId>
-            <artifactId>org.apache.karaf.features.core</artifactId>
-        </dependency>
-    </dependencies>
-
-    <build>
-        <resources>
-            <resource>
-                <directory>${project.basedir}/src/main/resources</directory>
-                <includes>
-                    <include>**/*</include>
-                </includes>
-            </resource>
-            <resource>
-                <directory>${project.basedir}/src/main/resources</directory>
-                <filtering>true</filtering>
-                <includes>
-                    <include>**/*.info</include>
-                </includes>
-            </resource>
-        </resources>
-        <plugins>
-            <plugin>
-                <groupId>org.apache.felix</groupId>
-                <artifactId>maven-bundle-plugin</artifactId>
-                <configuration>
-                    <instructions>
-                        <Export-Package>
-                        	${project.artifactId},
-                        	${project.artifactId}.common
-                       	</Export-Package>
-                        <Import-Package>
-                            com.sun.management*;resolution:=optional,
-                            *
-                        </Import-Package>
-                        <Private-Package>
-                            org.apache.karaf.diagnostic.core.internal,
-                            org.apache.karaf.diagnostic.core.internal.osgi,
-                            org.apache.karaf.util.tracker
-                        </Private-Package>
-                        <Bundle-Activator>
-                            org.apache.karaf.diagnostic.core.internal.osgi.Activator
-                        </Bundle-Activator>
-                    </instructions>
-                </configuration>
-            </plugin>
-        </plugins>
-    </build>
-
-</project>

http://git-wip-us.apache.org/repos/asf/karaf/blob/886863a2/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/core/DiagnosticDumpMBean.java
----------------------------------------------------------------------
diff --git a/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/core/DiagnosticDumpMBean.java b/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/core/DiagnosticDumpMBean.java
deleted file mode 100644
index f59982a..0000000
--- a/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/core/DiagnosticDumpMBean.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * 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.karaf.diagnostic.core;
-
-import javax.management.MBeanException;
-
-/**
- * Diagnostic MBean which allows to create dumps over JMX.
- */
-public interface DiagnosticDumpMBean {
-
-    /**
-     * Creates dump over JMX.
-     * 
-     * @param name Name of the dump.
-     * @throws Exception In case of any problems.
-     */
-    void createDump(String name) throws MBeanException;
-
-    /**
-     * Create dump with directory switch and name.
-     * 
-     * @param directory Should dump be created in directory.
-     * @param name Name of the dump.
-     * @throws Exception In case of any problems.
-     */
-    void createDump(boolean directory, String name) throws MBeanException;
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/886863a2/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/core/DumpDestination.java
----------------------------------------------------------------------
diff --git a/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/core/DumpDestination.java b/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/core/DumpDestination.java
deleted file mode 100644
index 39c4edc..0000000
--- a/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/core/DumpDestination.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * 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.karaf.diagnostic.core;
-
-import java.io.OutputStream;
-
-/**
- * Destination for created dumps.
- */
-public interface DumpDestination {
-
-    /**
-     * Creates new entry in dump destination.
-     * 
-     * Destination does not close returned output stream by default, dump
-     * provider should do this after completing write operation.
-     * 
-     * @param name Name of file in destination.
-     * @return Output stream ready to write.
-     * @throws Exception When entry cannot be added.
-     */
-    OutputStream add(String name) throws Exception;
-
-    /**
-     * Complete creation of the dump.
-     */
-    void save() throws Exception;
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/886863a2/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/core/DumpProvider.java
----------------------------------------------------------------------
diff --git a/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/core/DumpProvider.java b/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/core/DumpProvider.java
deleted file mode 100644
index ec7724c..0000000
--- a/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/core/DumpProvider.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * 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.karaf.diagnostic.core;
-
-/**
- * Interface which represents instance of tool which can provide dump
- * information.
- */
-public interface DumpProvider {
-
-    /**
-     * Creates dump in given entry.
-     */
-    void createDump(DumpDestination destination) throws Exception;
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/886863a2/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/core/common/ClosingEntryOutputStreamWrapper.java
----------------------------------------------------------------------
diff --git a/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/core/common/ClosingEntryOutputStreamWrapper.java b/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/core/common/ClosingEntryOutputStreamWrapper.java
deleted file mode 100644
index 0c4f9db..0000000
--- a/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/core/common/ClosingEntryOutputStreamWrapper.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * 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.karaf.diagnostic.core.common;
-
-import java.io.IOException;
-import java.io.OutputStream;
-import java.util.zip.ZipOutputStream;
-
-/**
- * Output stream which closes entry instead closing whole stream.
- */
-public class ClosingEntryOutputStreamWrapper extends OutputStream {
-
-    /**
-     * Wrapped ZIP output stream. 
-     */
-    private ZipOutputStream outputStream;
-
-    /**
-     * Creates new OutputStream.
-     * 
-     * @param outputStream Wrapped output stream.
-     */
-    public ClosingEntryOutputStreamWrapper(ZipOutputStream outputStream) {
-        this.outputStream = outputStream;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public void write(int b) throws IOException {
-        outputStream.write(b);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public void write(byte[] b) throws IOException {
-        outputStream.write(b);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public void write(byte[] b, int off, int len)
-        throws IOException {
-        outputStream.write(b, off, len);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public void close() throws IOException {
-        // close entry instead of closing zip stream.
-        outputStream.closeEntry();
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/886863a2/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/core/common/DirectoryDumpDestination.java
----------------------------------------------------------------------
diff --git a/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/core/common/DirectoryDumpDestination.java b/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/core/common/DirectoryDumpDestination.java
deleted file mode 100644
index 37ae72e..0000000
--- a/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/core/common/DirectoryDumpDestination.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * 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.karaf.diagnostic.core.common;
-
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.OutputStream;
-
-import org.apache.karaf.diagnostic.core.DumpDestination;
-
-/**
- * Class which packages dumps to given directory.
- */
-public class DirectoryDumpDestination implements DumpDestination {
-
-	/**
-	 * Directory where dump files will be created.
-	 */
-	private File directory;
-
-	public DirectoryDumpDestination(File file) {
-		this.directory = file;
-
-		if (!file.exists()) {
-			file.mkdirs();
-		} 
-	}
-
-	public OutputStream add(String name) throws Exception {
-		File destination = new File(directory, name);
-		if (name.contains("/") || name.contains("\\")) {
-			// if name contains slashes we need to create sub directory
-			destination.getParentFile().mkdirs();
-		}
-		return new FileOutputStream(destination);
-	}
-
-	public void save() throws Exception {
-		// do nothing, all should be written to output streams
-	}
-	
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/886863a2/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/core/common/TextDumpProvider.java
----------------------------------------------------------------------
diff --git a/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/core/common/TextDumpProvider.java b/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/core/common/TextDumpProvider.java
deleted file mode 100644
index 0b97d6f..0000000
--- a/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/core/common/TextDumpProvider.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * 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.karaf.diagnostic.core.common;
-
-import java.io.OutputStream;
-import java.io.OutputStreamWriter;
-
-import org.apache.karaf.diagnostic.core.DumpDestination;
-import org.apache.karaf.diagnostic.core.DumpProvider;
-
-/**
- * Base class for dump providers which writes text to destination.
- */
-public abstract class TextDumpProvider implements DumpProvider {
-
-    /**
-     * Name of the file.
-     */
-    private final String name;
-
-    /**
-     * Creates new dump provider.
-     * 
-     * @param name Name of the file.
-     */
-    protected TextDumpProvider(String name) {
-        this.name = name;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public final void createDump(DumpDestination destination) throws Exception {
-        OutputStream outputStream = destination.add(name);
-        OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream);
-        try {
-            writeDump(outputStreamWriter);
-        } finally {
-            outputStreamWriter.close();
-            outputStream.close();
-        }
-    }
-
-    /**
-     * This method should create output.
-     * 
-     * @param outputStreamWriter Stream which points to file specified in constructor.
-     * @throws Exception If any problem occur.
-     */
-    protected abstract void writeDump(OutputStreamWriter outputStreamWriter) throws Exception;
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/886863a2/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/core/common/ZipDumpDestination.java
----------------------------------------------------------------------
diff --git a/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/core/common/ZipDumpDestination.java b/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/core/common/ZipDumpDestination.java
deleted file mode 100644
index bafd38d..0000000
--- a/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/core/common/ZipDumpDestination.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * 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.karaf.diagnostic.core.common;
-
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.OutputStream;
-import java.util.zip.ZipEntry;
-import java.util.zip.ZipOutputStream;
-
-import org.apache.karaf.diagnostic.core.DumpDestination;
-
-/**
- * Class which packages dumps to ZIP archive.
- */
-public class ZipDumpDestination implements DumpDestination {
-
-    /**
-     * Destination streem.
-     */
-    private ZipOutputStream outputStream;
-
-    /**
-     * Creates new dump in given directory.
-     * 
-     * @param directory Target directory.
-     * @param name Name of the archive.
-     */
-    public ZipDumpDestination(File directory, String name) {
-        this(new File(directory, name));
-    }
-
-    /**
-     * Creates new dump in given file (zip archive). 
-     * 
-     * @param file Destination file.
-     */
-    public ZipDumpDestination(File file) {
-        try {
-            outputStream = new ZipOutputStream(new FileOutputStream(
-                file));
-        } catch (FileNotFoundException e) {
-            // sometimes this can occur, but we simply re throw and let 
-            // caller handle exception
-            throw new RuntimeException("Unable to create dump destination", e);
-        }
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public OutputStream add(String name) throws Exception {
-        ZipEntry zipEntry = new ZipEntry(name);
-        outputStream.putNextEntry(zipEntry);
-        return new ClosingEntryOutputStreamWrapper(outputStream);
-    }
-
-    /**
-     * Closes archive handle.
-     */
-    public void save() throws Exception {
-        outputStream.close();
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/886863a2/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/core/internal/BundleDumpProvider.java
----------------------------------------------------------------------
diff --git a/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/core/internal/BundleDumpProvider.java b/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/core/internal/BundleDumpProvider.java
deleted file mode 100644
index 774dc1f..0000000
--- a/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/core/internal/BundleDumpProvider.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * 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.karaf.diagnostic.core.internal;
-
-import java.io.IOException;
-import java.io.OutputStreamWriter;
-import java.util.HashMap;
-import java.util.Map;
-
-import org.apache.karaf.diagnostic.core.common.TextDumpProvider;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.BundleContext;
-
-/**
- * Dump provider which produces file named bundles.txt with list of
- * installed bundles and it's state.
- */
-public class BundleDumpProvider extends TextDumpProvider {
-
-    /**
-     * Static map with state mask to string representation.
-     */
-    private static Map<Integer, String> stateMap = new HashMap<Integer, String>();
-
-    /**
-     * Map bundle states to string representation.
-     */
-    static {
-        stateMap.put(0x00000001, "UNINSTALLED");
-        stateMap.put(0x00000002, "INSTALLED");
-        stateMap.put(0x00000004, "RESOLVED");
-        stateMap.put(0x00000008, "STARTING");
-        stateMap.put(0x00000010, "STOPPING");
-        stateMap.put(0x00000020, "ACTIVE");
-    }
-
-    /**
-     * Bundle context.
-     */
-    private BundleContext bundleContext;
-
-    /**
-     * Creates new bundle information file.
-     *  
-     * @param context Bundle context to access framework state.
-     */
-    public BundleDumpProvider(BundleContext context) {
-        super("bundles.txt");
-        this.bundleContext = context;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    protected void writeDump(OutputStreamWriter writer) throws IOException {
-        // get bundle states
-        Bundle[] bundles = bundleContext.getBundles();
-
-        writer.write("Number of installed bundles " + bundles.length + "\n");
-
-        // create file header
-        writer.write("Id\tSymbolic name\tVersion\tState\n");
-        for (Bundle bundle : bundles) {
-            // write row :)
-            writer.write(bundle.getBundleId() + "\t" + bundle.getSymbolicName() + '\t' + bundle.getVersion()
-                + "\t" + stateMap.get(bundle.getState()) + "\n");
-        }
-
-        writer.flush();
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/886863a2/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/core/internal/DiagnosticDumpMBeanImpl.java
----------------------------------------------------------------------
diff --git a/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/core/internal/DiagnosticDumpMBeanImpl.java b/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/core/internal/DiagnosticDumpMBeanImpl.java
deleted file mode 100644
index 22e09c9..0000000
--- a/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/core/internal/DiagnosticDumpMBeanImpl.java
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * 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.diagnostic.core.internal;
-
-import java.io.File;
-import java.util.List;
-import java.util.concurrent.CopyOnWriteArrayList;
-
-import javax.management.MBeanException;
-import javax.management.NotCompliantMBeanException;
-import javax.management.StandardMBean;
-
-import org.apache.karaf.diagnostic.core.DiagnosticDumpMBean;
-import org.apache.karaf.diagnostic.core.DumpDestination;
-import org.apache.karaf.diagnostic.core.DumpProvider;
-import org.apache.karaf.diagnostic.core.common.DirectoryDumpDestination;
-import org.apache.karaf.diagnostic.core.common.ZipDumpDestination;
-
-/**
- * Implementation of diagnostic MBean.
- */
-public class DiagnosticDumpMBeanImpl extends StandardMBean implements DiagnosticDumpMBean {
-
-    /**
-     * Dump providers.
-     */
-    private final List<DumpProvider> providers = new CopyOnWriteArrayList<DumpProvider>();
-
-    /**
-     * Creates new diagnostic mbean.
-     *
-     * @throws NotCompliantMBeanException
-     */
-    public DiagnosticDumpMBeanImpl() throws NotCompliantMBeanException {
-        super(DiagnosticDumpMBean.class);
-    }
-
-    /**
-     * Creates dump witch given name
-     *
-     * @param name Name of the dump.
-     */
-    public void createDump(String name) throws MBeanException {
-        createDump(false, name);
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public void createDump(boolean directory, String name) throws MBeanException {
-        try {
-            File target = new File(name);
-
-            DumpDestination destination;
-            if (directory) {
-                destination = new DirectoryDumpDestination(target);
-            } else {
-                destination = new ZipDumpDestination(target);
-            }
-
-            for (DumpProvider provider : providers) {
-                provider.createDump(destination);
-            }
-
-            destination.save();
-        } catch (Exception e) {
-            throw new MBeanException(null, e.getMessage());
-        }
-    }
-
-    public void registerProvider(DumpProvider provider) {
-        providers.add(provider);
-    }
-
-    public void unregisterProvider(DumpProvider provider) {
-        providers.add(provider);
-    }
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/886863a2/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/core/internal/EnvironmentDumpProvider.java
----------------------------------------------------------------------
diff --git a/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/core/internal/EnvironmentDumpProvider.java b/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/core/internal/EnvironmentDumpProvider.java
deleted file mode 100644
index 3328067..0000000
--- a/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/core/internal/EnvironmentDumpProvider.java
+++ /dev/null
@@ -1,291 +0,0 @@
-/*
- * 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.karaf.diagnostic.core.internal;
-
-import java.io.OutputStreamWriter;
-import java.io.PrintWriter;
-import java.lang.management.ClassLoadingMXBean;
-import java.lang.management.CompilationMXBean;
-import java.lang.management.GarbageCollectorMXBean;
-import java.lang.management.ManagementFactory;
-import java.lang.management.MemoryMXBean;
-import java.lang.management.MemoryUsage;
-import java.lang.management.OperatingSystemMXBean;
-import java.lang.management.RuntimeMXBean;
-import java.lang.management.ThreadMXBean;
-import java.text.DateFormat;
-import java.text.DecimalFormat;
-import java.text.DecimalFormatSymbols;
-import java.text.NumberFormat;
-import java.util.Date;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-import java.util.Map.Entry;
-
-import org.apache.karaf.diagnostic.core.common.TextDumpProvider;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.Version;
-
-/**
- * Provider which dumps runtime environment information to file named environment.txt.
- */
-public class EnvironmentDumpProvider extends TextDumpProvider {
-    
-    private static final String KEY_VALUE_FORMAT = "%1$s\t: %2$s";
-    private static final String INDENT_KEY_VALUE_FORMAT = "    "+KEY_VALUE_FORMAT;
-    private final BundleContext bundleContext;
-
-    /**
-     * Creates new dump entry which contains information about the runtime environment.
-     */
-    public EnvironmentDumpProvider(final BundleContext context) {
-        super("environment.txt");
-        this.bundleContext = context;
-    }
-
-    @Override
-    protected void writeDump(final OutputStreamWriter outputStream) throws Exception {
-    if( null == outputStream) {
-        return;
-    }
-    final PrintWriter outPW = new PrintWriter(outputStream);
-    // current date/time
-    final DateFormat dateTimeFormatInstance = DateFormat.getDateTimeInstance(DateFormat.FULL, DateFormat.FULL, Locale.ENGLISH);
-    outPW.printf(KEY_VALUE_FORMAT,"Dump timestamp", dateTimeFormatInstance.format(new Date(System.currentTimeMillis()))).println();
-    outPW.println();
-    // karaf information
-    dumpKarafInformation(outPW);
-    outPW.println();
-    // OSGi information
-    dumpOSGiInformation(outPW);
-    outPW.println();
-    // OS information
-    dumpOSInformation(outPW);
-    outPW.println();
-    // general information about JVM
-    dumpVMInformation(outPW, dateTimeFormatInstance);
-    outPW.println();
-    // threads
-    dumpThreadsInformation(outPW);
-    outPW.println();
-    // classes
-    dumpClassesInformation(outPW);
-    outPW.println();
-    // memory
-    dumpMemoryInformation(outPW);
-    outPW.println();
-    // garbage collector
-    dumpGCInformation(outPW);
-    }
-
-    private void dumpKarafInformation(final PrintWriter outPW) {
-        outPW.printf(KEY_VALUE_FORMAT, "Karaf", System.getProperty("karaf.name", "root") + ' ' + System.getProperty("karaf.version", "")).println();
-        outPW.printf(INDENT_KEY_VALUE_FORMAT, "home", System.getProperty("karaf.home", "")).println();
-        outPW.printf(INDENT_KEY_VALUE_FORMAT, "base", System.getProperty("karaf.base", "")).println();
-    }
-
-    private void dumpOSGiInformation(final PrintWriter outPW) {
-        if( null == bundleContext ) {
-            return;
-        }
-        outPW.println("OSGi:");
-        final Bundle[] bundles = bundleContext.getBundles();
-        for (final Bundle bundle : bundles) {
-            if( null == bundle || !!!"osgi.core".equals(bundle.getSymbolicName())) {
-                continue;
-            }
-            outPW.printf(INDENT_KEY_VALUE_FORMAT, "version", bundle.getVersion()).println();
-            break;
-        }
-        outPW.printf(INDENT_KEY_VALUE_FORMAT, "framework", bundleContext.getBundle(0).getSymbolicName() + " - " +
-                bundleContext.getBundle(0).getVersion()).println();
-    }
-
-    private void dumpOSInformation(final PrintWriter outPW) {
-        final OperatingSystemMXBean mxBean = ManagementFactory.getOperatingSystemMXBean();
-        if( null == mxBean) {
-            return;
-        }
-        outPW.printf(KEY_VALUE_FORMAT, "Operating System", mxBean.getName() + ' ' + mxBean.getVersion()).println();
-        outPW.printf(INDENT_KEY_VALUE_FORMAT, "architecture", mxBean.getArch()).println();
-        outPW.printf(INDENT_KEY_VALUE_FORMAT, "processors", mxBean.getAvailableProcessors()).println();
-//        outPW.printf(INDENT_KEY_VALUE_FORMAT, "current system load average", mxBean.getSystemLoadAverage()).println();
-    }
-
-    private void dumpVMInformation(final PrintWriter outPW,
-        final DateFormat dateTimeFormatInstance) {
-        final RuntimeMXBean mxBean = ManagementFactory.getRuntimeMXBean();
-        if( mxBean == null ) {
-            return;
-        }
-        outPW.printf(KEY_VALUE_FORMAT,"Instance name", mxBean.getName()).println();
-        outPW.printf(KEY_VALUE_FORMAT,"Start time", dateTimeFormatInstance.format(new Date(mxBean.getStartTime()))).println();
-        outPW.printf(KEY_VALUE_FORMAT,"Uptime", printDuration(mxBean.getUptime())).println();
-        outPW.println();
-        outPW.printf(KEY_VALUE_FORMAT, "Java VM", mxBean.getVmName() + " " + mxBean.getVmVersion()).println();
-        outPW.printf(INDENT_KEY_VALUE_FORMAT, "vendor", mxBean.getVmVendor()).println();
-        outPW.printf(INDENT_KEY_VALUE_FORMAT, "version", System.getProperty("java.version")).println();
-        outPW.println();
-        outPW.println("Input arguments:");
-        final List<String> inputArguments = mxBean.getInputArguments();
-        for (final String argument : inputArguments) {
-            if( argument != null && argument.contains("=")) {
-                final String[] split = argument.split("=");
-                outPW.printf(INDENT_KEY_VALUE_FORMAT, split[0], split[1]).println();
-            } else {
-                outPW.printf(INDENT_KEY_VALUE_FORMAT, argument,"").println();
-            }
-        }
-        outPW.println("Classpath:");
-        outPW.printf(INDENT_KEY_VALUE_FORMAT, "boot classpath", mxBean.getBootClassPath()).println();
-        outPW.printf(INDENT_KEY_VALUE_FORMAT, "library path", mxBean.getLibraryPath()).println();
-        outPW.printf(INDENT_KEY_VALUE_FORMAT, "classpath", mxBean.getClassPath()).println();
-        outPW.println("System properties:");
-        final Map<String, String> systemProperties = mxBean.getSystemProperties();
-        for (final Entry<String, String> property : systemProperties.entrySet()) {
-            outPW.printf(INDENT_KEY_VALUE_FORMAT, property.getKey(), property.getValue()).println();
-        }
-        outPW.println();
-        // JIT information
-        final CompilationMXBean compilationMXBean = ManagementFactory.getCompilationMXBean();
-        if( compilationMXBean != null ) {
-            outPW.printf(KEY_VALUE_FORMAT, "JIT compiler", compilationMXBean.getName()).println();
-            outPW.printf(INDENT_KEY_VALUE_FORMAT, "total compile time", printDuration(compilationMXBean.getTotalCompilationTime())).println();
-        }
-    }
-
-    private void dumpThreadsInformation(final PrintWriter outPW) {
-        final ThreadMXBean mxBean = ManagementFactory.getThreadMXBean();
-        if( null == mxBean) {
-            return;
-        }
-        outPW.println("Threads:");
-        outPW.printf(INDENT_KEY_VALUE_FORMAT, "live", formatLong(mxBean.getThreadCount())).println();
-        outPW.printf(INDENT_KEY_VALUE_FORMAT, "daemon", formatLong(mxBean.getDaemonThreadCount())).println();
-        outPW.printf(INDENT_KEY_VALUE_FORMAT, "peak", formatLong(mxBean.getPeakThreadCount())).println();
-        outPW.printf(INDENT_KEY_VALUE_FORMAT, "total", formatLong(mxBean.getTotalStartedThreadCount())).println();
-    }
-
-    private void dumpClassesInformation(final PrintWriter outPW) {
-        final ClassLoadingMXBean mxBean = ManagementFactory.getClassLoadingMXBean();
-        if( null == mxBean) {
-            return;
-        }
-        outPW.println("Classes:");
-        outPW.printf(INDENT_KEY_VALUE_FORMAT, "loaded", formatLong(mxBean.getLoadedClassCount())).println();
-        outPW.printf(INDENT_KEY_VALUE_FORMAT, "total", formatLong(mxBean.getTotalLoadedClassCount())).println();
-        outPW.printf(INDENT_KEY_VALUE_FORMAT, "unloaded", formatLong(mxBean.getUnloadedClassCount())).println();
-    }
-
-    private void dumpMemoryInformation(final PrintWriter outPW) {
-        final MemoryMXBean mxBean = ManagementFactory.getMemoryMXBean();
-        if( null == mxBean) {
-            return;
-        }
-        final MemoryUsage heapMemoryUsage = mxBean.getHeapMemoryUsage();
-        final MemoryUsage nonHeapMemoryUsage = mxBean.getNonHeapMemoryUsage();
-        if( heapMemoryUsage != null ) {
-            outPW.println("HEAP Memory:");
-            outPW.printf(INDENT_KEY_VALUE_FORMAT, "commited", printMemory(heapMemoryUsage.getCommitted())).println();
-            outPW.printf(INDENT_KEY_VALUE_FORMAT, "init", printMemory(heapMemoryUsage.getInit())).println();
-            outPW.printf(INDENT_KEY_VALUE_FORMAT, "used", printMemory(heapMemoryUsage.getUsed())).println();
-            outPW.printf(INDENT_KEY_VALUE_FORMAT, "maximal", printMemory(heapMemoryUsage.getMax())).println();
-        }
-        if( nonHeapMemoryUsage != null ) {
-            outPW.println("NON-HEAP Memory:");
-            outPW.printf(INDENT_KEY_VALUE_FORMAT, "commited", printMemory(nonHeapMemoryUsage.getCommitted())).println();
-            outPW.printf(INDENT_KEY_VALUE_FORMAT, "init", printMemory(nonHeapMemoryUsage.getInit())).println();
-            outPW.printf(INDENT_KEY_VALUE_FORMAT, "used", printMemory(nonHeapMemoryUsage.getUsed())).println();
-            outPW.printf(INDENT_KEY_VALUE_FORMAT, "maximal", printMemory(nonHeapMemoryUsage.getMax())).println();
-        }
-    }
-
-    private void dumpGCInformation(final PrintWriter outPW) {
-        final List<GarbageCollectorMXBean> mxBeans = ManagementFactory.getGarbageCollectorMXBeans();
-        if( null == mxBeans || mxBeans.isEmpty()) {
-            return;
-        }
-        final MemoryMXBean memoryMxBean = ManagementFactory.getMemoryMXBean();
-        if( memoryMxBean != null ) {
-            outPW.printf(INDENT_KEY_VALUE_FORMAT, "pending objects", formatLong(memoryMxBean.getObjectPendingFinalizationCount())).println();
-        }
-        final String gcFormat ="'%1$s' collections: %2$s\ttime: %3$s";
-        outPW.println();
-        for (final GarbageCollectorMXBean mxBean : mxBeans) {
-            if( null == mxBean) {
-                continue;
-            }
-            outPW.printf(KEY_VALUE_FORMAT, "Garbage Collectors", String.format(gcFormat, mxBean.getName(), formatLong(mxBean.getCollectionCount()), printDuration(mxBean.getCollectionTime()))).println();
-        }
-    }
-
-
-    private String formatLong(final long longValue) {
-        final NumberFormat fmtI = new DecimalFormat("###,###", new DecimalFormatSymbols(Locale.ENGLISH));
-        return fmtI.format(longValue);
-    }
-
-    private String printMemory(final long bytes) {
-        if( bytes <= 1024) {
-            return formatLong(bytes)+" bytes";
-        }
-        return formatLong(bytes/1024)+" kbytes";
-    }
-
-    /**
-     * Prints the duration in a human readable format as X days Y hours Z minutes etc.
-     *
-     * @param uptime the uptime in millis
-     * @return the time used for displaying on screen or in logs
-     */
-    private String printDuration(double uptime) {
-        // Code based on code taken from Karaf
-        // https://svn.apache.org/repos/asf/karaf/trunk/shell/commands/src/main/java/org/apache/karaf/shell/commands/impl/InfoAction.java
-
-        uptime /= 1000;
-        if (uptime < 60) {
-            final NumberFormat fmtD = new DecimalFormat("###,##0.000", new DecimalFormatSymbols(Locale.ENGLISH));
-            return fmtD.format(uptime) + " seconds";
-        }
-        uptime /= 60;
-        if (uptime < 60) {
-            final long minutes = (long) uptime;
-            final String s = formatLong(minutes) + (minutes > 1 ? " minutes" : " minute");
-            return s;
-        }
-        uptime /= 60;
-        if (uptime < 24) {
-            final long hours = (long) uptime;
-            final long minutes = (long) ((uptime - hours) * 60);
-            String s = formatLong(hours) + (hours > 1 ? " hours" : " hour");
-            if (minutes != 0) {
-                s += " " + formatLong(minutes) + (minutes > 1 ? " minutes" : " minute");
-            }
-            return s;
-        }
-        uptime /= 24;
-        final long days = (long) uptime;
-        final long hours = (long) ((uptime - days) * 24);
-        String s = formatLong(days) + (days > 1 ? " days" : " day");
-        if (hours != 0) {
-            s += " " + formatLong(hours) + (hours > 1 ? " hours" : " hour");
-        }
-        return s;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/886863a2/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/core/internal/FeaturesDumpProvider.java
----------------------------------------------------------------------
diff --git a/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/core/internal/FeaturesDumpProvider.java b/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/core/internal/FeaturesDumpProvider.java
deleted file mode 100644
index e5fa55e..0000000
--- a/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/core/internal/FeaturesDumpProvider.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * 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.karaf.diagnostic.core.internal;
-
-import java.io.OutputStreamWriter;
-
-import org.apache.karaf.diagnostic.core.common.TextDumpProvider;
-import org.apache.karaf.features.BundleInfo;
-import org.apache.karaf.features.Feature;
-import org.apache.karaf.features.FeaturesService;
-import org.apache.karaf.features.Repository;
-
-/**
- * Dump provider which add file named features.txt with informations
- * about installed features and repositories.
- */
-public class FeaturesDumpProvider extends TextDumpProvider {
-
-    /**
-     * Feature service.
-     */
-    private final FeaturesService features;
-
-    /**
-     * Creates new dump entry witch contains information about
-     * karaf features.
-     * 
-     * @param features Feature service.
-     */
-    public FeaturesDumpProvider(FeaturesService features) {
-        super("features.txt");
-        this.features = features;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    protected void writeDump(OutputStreamWriter outputStreamWriter) throws Exception {
-        // creates header
-        outputStreamWriter.write("Repositories:\n");
-
-        // list repositories
-        for (Repository repo : features.listRepositories()) {
-            outputStreamWriter.write(repo.getURI() + " (" + repo.getName() + ")\n");
-        }
-
-        // list features
-        outputStreamWriter.write("\nfeatures:\n");
-        for (Feature feature : features.listFeatures()) {
-            outputStreamWriter.write(feature.getName() + " " + feature.getVersion());
-            outputStreamWriter.write(" installed: " + features.isInstalled(feature));
-            outputStreamWriter.write("\nBundles:\n");
-            for (BundleInfo bundle : feature.getBundles()) {
-                outputStreamWriter.write("\t" + bundle.getLocation());
-                if (bundle.getStartLevel() != 0) {
-                    outputStreamWriter.write(" start level " + bundle.getStartLevel());
-                }
-                outputStreamWriter.write("\n\n");
-            }
-        }
-
-        // flush & close stream
-        outputStreamWriter.close();
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/886863a2/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/core/internal/HeapDumpProvider.java
----------------------------------------------------------------------
diff --git a/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/core/internal/HeapDumpProvider.java b/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/core/internal/HeapDumpProvider.java
deleted file mode 100644
index b86f57b..0000000
--- a/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/core/internal/HeapDumpProvider.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * 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.karaf.diagnostic.core.internal;
-
-import com.sun.management.HotSpotDiagnosticMXBean;
-import org.apache.karaf.diagnostic.core.DumpDestination;
-import org.apache.karaf.diagnostic.core.DumpProvider;
-
-import javax.management.MBeanServer;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.OutputStream;
-import java.lang.management.ManagementFactory;
-
-/**
- * Create a heap dump.
- */
-public class HeapDumpProvider implements DumpProvider {
-
-    @Override
-    public void createDump(DumpDestination destination) throws Exception {
-        FileInputStream in = null;
-        OutputStream out = null;
-        try {
-            MBeanServer mBeanServer = ManagementFactory.getPlatformMBeanServer();
-            HotSpotDiagnosticMXBean diagnosticMXBean = ManagementFactory.newPlatformMXBeanProxy(mBeanServer,
-                    "com.sun.management:type=HotSpotDiagnostic", HotSpotDiagnosticMXBean.class);
-            diagnosticMXBean.dumpHeap("heapdump.txt", false);
-            // copy the dump in the destination
-            File heapDumpFile = new File("heapdump.txt");
-            in = new FileInputStream(heapDumpFile);
-            out = destination.add("heapdump.txt");
-            byte[] buffer = new byte[2048];
-            while ((in.read(buffer) != -1)) {
-                out.write(buffer);
-            }
-            // remove the original dump
-            if (heapDumpFile.exists()) {
-                heapDumpFile.delete();
-            }
-        } catch (Exception e) {
-            // nothing to do
-        } finally {
-            if (in != null) {
-                in.close();
-            }
-            if (out != null) {
-                out.flush();
-                out.close();
-            }
-        }
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/886863a2/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/core/internal/LogDumpProvider.java
----------------------------------------------------------------------
diff --git a/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/core/internal/LogDumpProvider.java b/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/core/internal/LogDumpProvider.java
deleted file mode 100644
index 64b45f1..0000000
--- a/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/core/internal/LogDumpProvider.java
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * 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.karaf.diagnostic.core.internal;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.util.Dictionary;
-import java.util.Enumeration;
-
-import org.apache.karaf.diagnostic.core.DumpDestination;
-import org.apache.karaf.diagnostic.core.DumpProvider;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.ServiceReference;
-import org.osgi.service.cm.Configuration;
-import org.osgi.service.cm.ConfigurationAdmin;
-
-/**
- * Dump provider which copies log files from data/log directory to
- * destination.
- */
-public class LogDumpProvider implements DumpProvider {
-
-    private final BundleContext bundleContext;
-
-    public LogDumpProvider(BundleContext bundleContext) {
-        this.bundleContext = bundleContext;
-    }
-
-    /**
-     * Attach log entries from directory.
-     */
-    public void createDump(DumpDestination destination) throws Exception {
-        // get the ConfigAdmin service
-        ServiceReference ref = bundleContext.getServiceReference(ConfigurationAdmin.class.getName());
-        if (ref == null) {
-            return;
-        }
-
-        // get the PAX Logging configuration
-        ConfigurationAdmin configurationAdmin = (ConfigurationAdmin) bundleContext.getService(ref);
-        try {
-            Configuration configuration = configurationAdmin.getConfiguration("org.ops4j.pax.logging");
-
-            // get the ".file" Pax Logging properties
-            Dictionary dictionary = configuration.getProperties();
-            for (Enumeration e = dictionary.keys(); e.hasMoreElements(); ) {
-                String property = (String) e.nextElement();
-                if (property.endsWith(".file")) {
-                    // it's a file appender, get the file location
-                    String location = (String) dictionary.get(property);
-                    File file = new File(location);
-                    if (file.exists()) {
-                        FileInputStream inputStream = new FileInputStream(file);
-                        OutputStream outputStream = destination.add("log/" + file.getName());
-                        copy(inputStream, outputStream);
-                    }
-                }
-            }
-        } catch (Exception e) {
-            throw e;
-        } finally {
-            bundleContext.ungetService(ref);
-        }
-    }
-
-    /**
-     * Rewrites data from input stream to output stream. This code is very common
-     * but we would avoid additional dependencies in diagnostic stuff.
-     *
-     * @param inputStream  Source stream.
-     * @param outputStream Destination stream.
-     * @throws IOException When IO operation fails.
-     */
-    private void copy(InputStream inputStream, OutputStream outputStream) throws IOException {
-        byte[] buffer = new byte[4096];
-        int n = 0;
-        while (-1 != (n = inputStream.read(buffer))) {
-            outputStream.write(buffer, 0, n);
-        }
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/886863a2/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/core/internal/MemoryDumpProvider.java
----------------------------------------------------------------------
diff --git a/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/core/internal/MemoryDumpProvider.java b/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/core/internal/MemoryDumpProvider.java
deleted file mode 100644
index ff23f9d..0000000
--- a/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/core/internal/MemoryDumpProvider.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * 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.karaf.diagnostic.core.internal;
-
-import org.apache.karaf.diagnostic.core.common.TextDumpProvider;
-
-import java.io.OutputStreamWriter;
-import java.lang.management.ManagementFactory;
-import java.lang.management.MemoryMXBean;
-
-/**
- * Provider which dump the memory information in the memory.txt file.
- */
-public class MemoryDumpProvider extends TextDumpProvider {
-
-    public MemoryDumpProvider() {
-        super("memory.txt");
-    }
-
-    @Override
-    protected void writeDump(OutputStreamWriter outputStream) throws Exception {
-        MemoryMXBean memoryMXBean = ManagementFactory.getMemoryMXBean();
-
-        outputStream.write("Number of objects waiting finalization: " + memoryMXBean.getObjectPendingFinalizationCount() + "\n\n");
-
-        outputStream.write("Heap:\n");
-        outputStream.write("\tInit:      " + memoryMXBean.getHeapMemoryUsage().getInit() + "\n");
-        outputStream.write("\tUser:      " + memoryMXBean.getHeapMemoryUsage().getUsed() + "\n");
-        outputStream.write("\tCommitted: " + memoryMXBean.getHeapMemoryUsage().getCommitted() + "\n");
-        outputStream.write("\tMax:       " + memoryMXBean.getHeapMemoryUsage().getMax() + "\n");
-
-        outputStream.write("Non-Heap: \n");
-        outputStream.write("\tInit:      " + memoryMXBean.getNonHeapMemoryUsage().getInit() + "\n");
-        outputStream.write("\tUser:      " + memoryMXBean.getNonHeapMemoryUsage().getUsed() + "\n");
-        outputStream.write("\tCommitted: " + memoryMXBean.getNonHeapMemoryUsage().getCommitted() + "\n");
-        outputStream.write("\tMax:       " + memoryMXBean.getNonHeapMemoryUsage().getMax() + "\n");
-
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/886863a2/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/core/internal/ThreadDumpProvider.java
----------------------------------------------------------------------
diff --git a/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/core/internal/ThreadDumpProvider.java b/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/core/internal/ThreadDumpProvider.java
deleted file mode 100644
index 31edad6..0000000
--- a/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/core/internal/ThreadDumpProvider.java
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * 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.karaf.diagnostic.core.internal;
-
-import java.io.OutputStreamWriter;
-import java.lang.management.LockInfo;
-import java.lang.management.ManagementFactory;
-import java.lang.management.MonitorInfo;
-import java.lang.management.ThreadInfo;
-import java.lang.management.ThreadMXBean;
-
-import org.apache.karaf.diagnostic.core.common.TextDumpProvider;
-
-/**
- * Provider which dumps thread info to file named threads.txt.
- */
-public class ThreadDumpProvider extends TextDumpProvider {
-
-    /**
-     * Creates new dump entry which contains information about threads.
-     */
-    public ThreadDumpProvider() {
-        super("threads.txt");
-    }
-
-    @Override
-    protected void writeDump(OutputStreamWriter outputStream) throws Exception {
-        ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
-
-        outputStream.write("Number of threads: " + threadMXBean.getThreadCount() + "\n");
-
-        for (ThreadInfo threadInfo : threadMXBean.getThreadInfo(threadMXBean.getAllThreadIds(), Integer.MAX_VALUE)) {
-            outputStream.write(getDumpThreadString(threadInfo) + "\n\n");
-        }
-
-    }
-
-    protected String getDumpThreadString(ThreadInfo threadInfo) {
-        StringBuilder sb = new StringBuilder("\"" + threadInfo.getThreadName() + "\"" + " Id=" + threadInfo.getThreadId() + " "
-                                             + threadInfo.getThreadState());
-        if (threadInfo.getLockName() != null) {
-            sb.append(" on " + threadInfo.getLockName());
-        }
-        if (threadInfo.getLockOwnerName() != null) {
-            sb.append(" owned by \"" + threadInfo.getLockOwnerName() + "\" Id=" + threadInfo.getLockOwnerId());
-        }
-        if (threadInfo.isSuspended()) {
-            sb.append(" (suspended)");
-        }
-        if (threadInfo.isInNative()) {
-            sb.append(" (in native)");
-        }
-        sb.append('\n');
-        int i = 0;
-        StackTraceElement[] stackTrace = threadInfo.getStackTrace();
-        for (; i < stackTrace.length; i++) {
-            StackTraceElement ste = stackTrace[i];
-            sb.append("\tat " + ste.toString());
-            sb.append('\n');
-            if (i == 0 && threadInfo.getLockInfo() != null) {
-                Thread.State ts = threadInfo.getThreadState();
-                switch (ts) {
-                case BLOCKED:
-                    sb.append("\t-  blocked on " + threadInfo.getLockInfo());
-                    sb.append('\n');
-                    break;
-                case WAITING:
-                    sb.append("\t-  waiting on " + threadInfo.getLockInfo());
-                    sb.append('\n');
-                    break;
-                case TIMED_WAITING:
-                    sb.append("\t-  waiting on " + threadInfo.getLockInfo());
-                    sb.append('\n');
-                    break;
-                default:
-                }
-            }
-
-            for (MonitorInfo mi : threadInfo.getLockedMonitors()) {
-                if (mi.getLockedStackDepth() == i) {
-                    sb.append("\t-  locked " + mi);
-                    sb.append('\n');
-                }
-            }
-        }
-        if (i < stackTrace.length) {
-            sb.append("\t...");
-            sb.append('\n');
-        }
-
-        LockInfo[] locks = threadInfo.getLockedSynchronizers();
-        if (locks.length > 0) {
-            sb.append("\n\tNumber of locked synchronizers = " + locks.length);
-            sb.append('\n');
-            for (LockInfo li : locks) {
-                sb.append("\t- " + li);
-                sb.append('\n');
-            }
-        }
-        sb.append('\n');
-        return sb.toString();
-    }
-
-
-}


[24/59] [abbrv] git commit: [KARAF-2852] Merge config/core and config/command

Posted by gn...@apache.org.
[KARAF-2852] Merge config/core and config/command

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

Branch: refs/heads/master
Commit: d33e09557ba361f44b469e71959398472ef630b4
Parents: d018093
Author: Guillaume Nodet <gn...@gmail.com>
Authored: Wed Apr 9 22:08:08 2014 +0200
Committer: Guillaume Nodet <gn...@gmail.com>
Committed: Thu Apr 10 15:59:49 2014 +0200

----------------------------------------------------------------------
 .../standard/src/main/feature/feature.xml       |   1 -
 config/NOTICE                                   |  71 +++++++
 config/command/NOTICE                           |  71 -------
 config/command/pom.xml                          | 106 -----------
 .../karaf/config/command/CancelCommand.java     |  32 ----
 .../config/command/ConfigCommandSupport.java    |  63 -------
 .../command/ConfigPropertyCommandSupport.java   |  85 ---------
 .../karaf/config/command/DeleteCommand.java     |  52 ------
 .../karaf/config/command/EditCommand.java       |  70 -------
 .../karaf/config/command/ListCommand.java       |  68 -------
 .../karaf/config/command/PropAppendCommand.java |  50 -----
 .../karaf/config/command/PropDelCommand.java    |  38 ----
 .../karaf/config/command/PropListCommand.java   |  47 -----
 .../karaf/config/command/PropSetCommand.java    |  43 -----
 .../karaf/config/command/UpdateCommand.java     |  48 -----
 .../completers/ConfigurationCompleter.java      | 103 ----------
 .../ConfigurationPropertyCompleter.java         | 136 --------------
 .../src/main/resources/OSGI-INF/bundle.info     |  27 ---
 .../org/apache/karaf/config/command/edit.txt    |  13 --
 .../karaf/config/command/EditCommandTest.java   |  97 ----------
 .../config/command/MockCommandSession.java      |  99 ----------
 .../karaf/config/command/UpdateCommandTest.java |  82 --------
 config/core/NOTICE                              |  71 -------
 config/core/pom.xml                             | 111 -----------
 .../apache/karaf/config/core/ConfigMBean.java   | 107 -----------
 .../karaf/config/core/ConfigRepository.java     |  51 -----
 .../karaf/config/core/impl/ConfigMBeanImpl.java | 186 -------------------
 .../config/core/impl/ConfigRepositoryImpl.java  |  99 ----------
 .../karaf/config/core/impl/osgi/Activator.java  |  46 -----
 .../src/main/resources/OSGI-INF/bundle.info     |  27 ---
 .../OSGI-INF/metatype/metatype.properties       |  28 ---
 .../resources/OSGI-INF/metatype/metatype.xml    |  28 ---
 config/pom.xml                                  |  97 +++++++++-
 .../karaf/config/command/CancelCommand.java     |  32 ++++
 .../config/command/ConfigCommandSupport.java    |  63 +++++++
 .../command/ConfigPropertyCommandSupport.java   |  85 +++++++++
 .../karaf/config/command/DeleteCommand.java     |  52 ++++++
 .../karaf/config/command/EditCommand.java       |  70 +++++++
 .../karaf/config/command/ListCommand.java       |  68 +++++++
 .../karaf/config/command/PropAppendCommand.java |  50 +++++
 .../karaf/config/command/PropDelCommand.java    |  38 ++++
 .../karaf/config/command/PropListCommand.java   |  47 +++++
 .../karaf/config/command/PropSetCommand.java    |  43 +++++
 .../karaf/config/command/UpdateCommand.java     |  48 +++++
 .../completers/ConfigurationCompleter.java      | 103 ++++++++++
 .../ConfigurationPropertyCompleter.java         | 136 ++++++++++++++
 .../apache/karaf/config/core/ConfigMBean.java   | 107 +++++++++++
 .../karaf/config/core/ConfigRepository.java     |  51 +++++
 .../karaf/config/core/impl/ConfigMBeanImpl.java | 186 +++++++++++++++++++
 .../config/core/impl/ConfigRepositoryImpl.java  |  99 ++++++++++
 .../karaf/config/core/impl/osgi/Activator.java  |  46 +++++
 config/src/main/resources/OSGI-INF/bundle.info  |  27 +++
 .../OSGI-INF/metatype/metatype.properties       |  28 +++
 .../resources/OSGI-INF/metatype/metatype.xml    |  28 +++
 .../org/apache/karaf/config/command/edit.txt    |  13 ++
 .../karaf/config/command/EditCommandTest.java   |  97 ++++++++++
 .../config/command/MockCommandSession.java      |  99 ++++++++++
 .../karaf/config/command/UpdateCommandTest.java |  82 ++++++++
 58 files changed, 1857 insertions(+), 2094 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/karaf/blob/d33e0955/assemblies/features/standard/src/main/feature/feature.xml
----------------------------------------------------------------------
diff --git a/assemblies/features/standard/src/main/feature/feature.xml b/assemblies/features/standard/src/main/feature/feature.xml
index 2bc3ec4..1c67ca7 100644
--- a/assemblies/features/standard/src/main/feature/feature.xml
+++ b/assemblies/features/standard/src/main/feature/feature.xml
@@ -125,7 +125,6 @@
 
     <feature name="config" description="Provide OSGi ConfigAdmin support" version="${project.version}">
         <bundle start-level="30" start="true">mvn:org.apache.karaf.config/org.apache.karaf.config.core/${project.version}</bundle>
-        <bundle start-level="30" start="true">mvn:org.apache.karaf.config/org.apache.karaf.config.command/${project.version}</bundle>
     </feature>
 
     <feature name="diagnostic" description="Provide Diagnostic support" version="${project.version}">

http://git-wip-us.apache.org/repos/asf/karaf/blob/d33e0955/config/NOTICE
----------------------------------------------------------------------
diff --git a/config/NOTICE b/config/NOTICE
new file mode 100644
index 0000000..b70f1f9
--- /dev/null
+++ b/config/NOTICE
@@ -0,0 +1,71 @@
+Apache Karaf
+Copyright 2010-2014 The Apache Software Foundation
+
+
+I. Included Software
+
+This product includes software developed at
+The Apache Software Foundation (http://www.apache.org/).
+Licensed under the Apache License 2.0.
+
+This product uses software developed at
+The OSGi Alliance (http://www.osgi.org/).
+Copyright (c) OSGi Alliance (2000, 2010).
+Licensed under the Apache License 2.0.
+
+This product includes software developed at
+OW2 (http://www.ow2.org/).
+Licensed under the BSD License.
+
+This product includes software developed at
+OPS4J (http://www.ops4j.org/).
+Licensed under the Apache License 2.0.
+
+This product includes software developed at
+Eclipse Foundation (http://www.eclipse.org/).
+Licensed under the EPL.
+
+This product includes software written by
+Antony Lesuisse.
+Licensed under Public Domain.
+
+
+II. Used Software
+
+This product uses software developed at
+FUSE Source (http://www.fusesource.org/).
+Licensed under the Apache License 2.0.
+
+This product uses software developed at
+AOP Alliance (http://aopalliance.sourceforge.net/).
+Licensed under the Public Domain.
+
+This product uses software developed at
+Tanuki Software (http://www.tanukisoftware.com/).
+Licensed under the Apache License 2.0.
+
+This product uses software developed at
+Jasypt (http://jasypt.sourceforge.net/).
+Licensed under the Apache License 2.0.
+
+This product uses software developed at
+JLine (http://jline.sourceforge.net).
+Licensed under the BSD License.
+
+This product uses software developed at
+SLF4J (http://www.slf4j.org/).
+Licensed under the MIT License.
+
+This product uses software developed at
+SpringSource (http://www.springsource.org/).
+Licensed under the Apache License 2.0.
+
+This product includes software from http://www.json.org.
+Copyright (c) 2002 JSON.org
+
+
+III. License Summary
+- Apache License 2.0
+- BSD License
+- EPL License
+- MIT License

http://git-wip-us.apache.org/repos/asf/karaf/blob/d33e0955/config/command/NOTICE
----------------------------------------------------------------------
diff --git a/config/command/NOTICE b/config/command/NOTICE
deleted file mode 100644
index b70f1f9..0000000
--- a/config/command/NOTICE
+++ /dev/null
@@ -1,71 +0,0 @@
-Apache Karaf
-Copyright 2010-2014 The Apache Software Foundation
-
-
-I. Included Software
-
-This product includes software developed at
-The Apache Software Foundation (http://www.apache.org/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-The OSGi Alliance (http://www.osgi.org/).
-Copyright (c) OSGi Alliance (2000, 2010).
-Licensed under the Apache License 2.0.
-
-This product includes software developed at
-OW2 (http://www.ow2.org/).
-Licensed under the BSD License.
-
-This product includes software developed at
-OPS4J (http://www.ops4j.org/).
-Licensed under the Apache License 2.0.
-
-This product includes software developed at
-Eclipse Foundation (http://www.eclipse.org/).
-Licensed under the EPL.
-
-This product includes software written by
-Antony Lesuisse.
-Licensed under Public Domain.
-
-
-II. Used Software
-
-This product uses software developed at
-FUSE Source (http://www.fusesource.org/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-AOP Alliance (http://aopalliance.sourceforge.net/).
-Licensed under the Public Domain.
-
-This product uses software developed at
-Tanuki Software (http://www.tanukisoftware.com/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-Jasypt (http://jasypt.sourceforge.net/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-JLine (http://jline.sourceforge.net).
-Licensed under the BSD License.
-
-This product uses software developed at
-SLF4J (http://www.slf4j.org/).
-Licensed under the MIT License.
-
-This product uses software developed at
-SpringSource (http://www.springsource.org/).
-Licensed under the Apache License 2.0.
-
-This product includes software from http://www.json.org.
-Copyright (c) 2002 JSON.org
-
-
-III. License Summary
-- Apache License 2.0
-- BSD License
-- EPL License
-- MIT License

http://git-wip-us.apache.org/repos/asf/karaf/blob/d33e0955/config/command/pom.xml
----------------------------------------------------------------------
diff --git a/config/command/pom.xml b/config/command/pom.xml
deleted file mode 100644
index de81567..0000000
--- a/config/command/pom.xml
+++ /dev/null
@@ -1,106 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-
-    <!--
-
-        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.
-    -->
-
-    <modelVersion>4.0.0</modelVersion>
-
-    <parent>
-        <groupId>org.apache.karaf.config</groupId>
-        <artifactId>config</artifactId>
-        <version>4.0.0-SNAPSHOT</version>
-        <relativePath>../pom.xml</relativePath>
-    </parent>
-
-    <artifactId>org.apache.karaf.config.command</artifactId>
-    <packaging>bundle</packaging>
-    <name>Apache Karaf :: ConfigAdmin :: Commands</name>
-    <description>This bundle provides Karaf shell commands to manipulate the ConfigAdmin service.</description>
-
-    <properties>
-        <appendedResourcesDirectory>${basedir}/../../etc/appended-resources</appendedResourcesDirectory>
-    </properties>
-
-    <dependencies>
-        <dependency>
-            <groupId>org.apache.karaf.config</groupId>
-            <artifactId>org.apache.karaf.config.core</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.karaf.shell</groupId>
-            <artifactId>org.apache.karaf.shell.core</artifactId>
-        </dependency>
-
-        <dependency>
-            <groupId>org.osgi</groupId>
-            <artifactId>org.osgi.core</artifactId>
-            <scope>provided</scope>
-        </dependency>
-
-        <dependency>
-            <groupId>org.osgi</groupId>
-            <artifactId>org.osgi.compendium</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        
-        <dependency>
-            <groupId>org.slf4j</groupId>
-            <artifactId>slf4j-api</artifactId>
-        </dependency>
-        
-        <dependency>
-            <groupId>org.slf4j</groupId>
-            <artifactId>slf4j-jdk14</artifactId>
-            <scope>test</scope>
-        </dependency>
-    </dependencies>
-
-    <build>
-        <resources>
-            <resource>
-                <directory>${project.basedir}/src/main/resources</directory>
-                <includes>
-                    <include>**/*</include>
-                </includes>
-            </resource>
-            <resource>
-                <directory>${project.basedir}/src/main/resources</directory>
-                <filtering>true</filtering>
-                <includes>
-                    <include>**/*.info</include>
-                </includes>
-            </resource>
-        </resources>
-        <plugins>
-            <plugin>
-                <groupId>org.apache.felix</groupId>
-                <artifactId>maven-bundle-plugin</artifactId>
-                <configuration>
-                    <instructions>
-                        <Private-Package>
-                            org.apache.felix.utils.properties
-                        </Private-Package>
-                        <Karaf-Commands>*</Karaf-Commands>
-                    </instructions>
-                </configuration>
-            </plugin>
-        </plugins>
-    </build>
-
-</project>

http://git-wip-us.apache.org/repos/asf/karaf/blob/d33e0955/config/command/src/main/java/org/apache/karaf/config/command/CancelCommand.java
----------------------------------------------------------------------
diff --git a/config/command/src/main/java/org/apache/karaf/config/command/CancelCommand.java b/config/command/src/main/java/org/apache/karaf/config/command/CancelCommand.java
deleted file mode 100644
index dff43fa..0000000
--- a/config/command/src/main/java/org/apache/karaf/config/command/CancelCommand.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * 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.karaf.config.command;
-
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-
-@Command(scope = "config", name = "cancel", description = "Cancels the changes to the configuration being edited.")
-@Service
-public class CancelCommand extends ConfigCommandSupport {
-
-    protected Object doExecute() throws Exception {
-        session.put(PROPERTY_CONFIG_PID, null);
-        session.put(PROPERTY_CONFIG_PROPS, null);
-        return null;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d33e0955/config/command/src/main/java/org/apache/karaf/config/command/ConfigCommandSupport.java
----------------------------------------------------------------------
diff --git a/config/command/src/main/java/org/apache/karaf/config/command/ConfigCommandSupport.java b/config/command/src/main/java/org/apache/karaf/config/command/ConfigCommandSupport.java
deleted file mode 100644
index fe0ca93..0000000
--- a/config/command/src/main/java/org/apache/karaf/config/command/ConfigCommandSupport.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * 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.karaf.config.command;
-
-import java.util.Dictionary;
-
-import org.apache.karaf.config.core.ConfigRepository;
-import org.apache.karaf.shell.api.action.Action;
-import org.apache.karaf.shell.api.action.lifecycle.Reference;
-import org.apache.karaf.shell.api.console.Session;
-
-/**
- * Abstract class from which all commands related to the ConfigurationAdmin
- * service should derive.
- * This command retrieves a reference to the ConfigurationAdmin service before
- * calling another method to actually process the command.
- */
-public abstract class ConfigCommandSupport implements Action {
-
-    public static final String PROPERTY_CONFIG_PID = "ConfigCommand.PID";
-    public static final String PROPERTY_CONFIG_PROPS = "ConfigCommand.Props";
-    public static final String PROPERTY_FACTORY = "ConfigCommand.Factory";
-
-    @Reference
-    protected ConfigRepository configRepository;
-
-    @Reference
-    protected Session session;
-
-    @Override
-    public Object execute() throws Exception {
-        return doExecute();
-    }
-
-    protected abstract Object doExecute() throws Exception;
-
-    @SuppressWarnings("rawtypes")
-    protected Dictionary getEditedProps() throws Exception {
-        return (Dictionary) this.session.get(PROPERTY_CONFIG_PROPS);
-    }
-    
-    public void setConfigRepository(ConfigRepository configRepository) {
-        this.configRepository = configRepository;
-    }
-
-    public void setSession(Session session) {
-        this.session = session;
-    }
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d33e0955/config/command/src/main/java/org/apache/karaf/config/command/ConfigPropertyCommandSupport.java
----------------------------------------------------------------------
diff --git a/config/command/src/main/java/org/apache/karaf/config/command/ConfigPropertyCommandSupport.java b/config/command/src/main/java/org/apache/karaf/config/command/ConfigPropertyCommandSupport.java
deleted file mode 100644
index 619c224..0000000
--- a/config/command/src/main/java/org/apache/karaf/config/command/ConfigPropertyCommandSupport.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * 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.karaf.config.command;
-
-import java.util.Dictionary;
-import java.util.Properties;
-
-import org.apache.karaf.config.command.completers.ConfigurationCompleter;
-import org.apache.karaf.shell.api.action.Completion;
-import org.apache.karaf.shell.api.action.Option;
-
-/**
- * Abstract class which commands that are related to property processing should extend.
- */
-public abstract class ConfigPropertyCommandSupport extends ConfigCommandSupport {
-
-    @Option(name = "-p", aliases = "--pid", description = "The configuration pid", required = false, multiValued = false)
-    @Completion(ConfigurationCompleter.class)
-    protected String pid;
-
-    @SuppressWarnings("rawtypes")
-    protected Object doExecute() throws Exception {
-        Dictionary props = getEditedProps();
-        if (props == null && pid == null) {
-            System.err.println("No configuration is being edited--run the edit command first");
-        } else {
-            if (props == null) {
-                props = new Properties();
-            }
-            propertyAction(props);
-            if(requiresUpdate(pid)) {
-                this.configRepository.update(pid, props);
-            }
-        }
-        return null;
-    }
-
-    /**
-     * Perform an action on the properties.
-     * @param props
-     */
-    @SuppressWarnings("rawtypes")
-    protected abstract void propertyAction(Dictionary props);
-
-    /**
-     * Checks if the configuration requires to be updated.
-     * The default behavior is to update if a valid pid has been passed to the method.
-     * @param pid
-     * @return
-     */
-    protected boolean requiresUpdate(String pid) {
-        if (pid != null) {
-            return true;
-        } else {
-            return false;
-        }
-    }
-
-
-    /**
-     * Retrieves confguration from the pid, if used or delegates to session from getting the configuration.
-     * @return
-     * @throws Exception
-     */
-    @SuppressWarnings("rawtypes")
-    @Override
-    protected Dictionary getEditedProps() throws Exception {
-        Dictionary props = this.configRepository.getConfigProperties(pid);
-        return (props != null) ? props : super.getEditedProps();
-    }
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d33e0955/config/command/src/main/java/org/apache/karaf/config/command/DeleteCommand.java
----------------------------------------------------------------------
diff --git a/config/command/src/main/java/org/apache/karaf/config/command/DeleteCommand.java b/config/command/src/main/java/org/apache/karaf/config/command/DeleteCommand.java
deleted file mode 100644
index 6953ef0..0000000
--- a/config/command/src/main/java/org/apache/karaf/config/command/DeleteCommand.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * 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.karaf.config.command;
-
-import org.apache.karaf.config.command.completers.ConfigurationCompleter;
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Completion;
-import org.apache.karaf.shell.api.action.Option;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-
-@Command(scope = "config", name = "delete", description = "Delete a configuration.")
-@Service
-public class DeleteCommand extends ConfigCommandSupport {
-
-    @Argument(index = 0, name = "pid", description = "PID of the configuration", required = true, multiValued = false)
-    @Completion(ConfigurationCompleter.class)
-    String pid;
-
-    @Option(name = "--force", aliases = {}, description = "Force the edition of this config, even if another one was under edition", required = false, multiValued = false)
-    boolean force;
-
-    protected Object doExecute() throws Exception {
-        String oldPid = (String) this.session.get(PROPERTY_CONFIG_PID);
-        if (oldPid != null && oldPid.equals(pid) && !force) {
-            System.err.println("This config is being edited.  Cancel / update first, or use the --force option");
-            return null;
-        }
-
-        this.configRepository.delete(pid);
-        if (oldPid != null && oldPid.equals(pid) && !force) {
-            this.session.put(PROPERTY_CONFIG_PID, null);
-            this.session.put(PROPERTY_CONFIG_PROPS, null);
-        }
-        return null;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d33e0955/config/command/src/main/java/org/apache/karaf/config/command/EditCommand.java
----------------------------------------------------------------------
diff --git a/config/command/src/main/java/org/apache/karaf/config/command/EditCommand.java b/config/command/src/main/java/org/apache/karaf/config/command/EditCommand.java
deleted file mode 100644
index 8c48b83..0000000
--- a/config/command/src/main/java/org/apache/karaf/config/command/EditCommand.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * 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.karaf.config.command;
-
-import java.util.Dictionary;
-
-import org.apache.karaf.config.command.completers.ConfigurationCompleter;
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Completion;
-import org.apache.karaf.shell.api.action.Option;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.osgi.service.cm.Configuration;
-
-@Command(scope = "config", name = "edit", description = "Creates or edits a configuration.", detailedDescription="classpath:edit.txt")
-@Service
-public class EditCommand extends ConfigCommandSupport {
-
-    @Argument(index = 0, name = "pid", description = "PID of the configuration or of the factory if --factory is given. Pid can also be specified as ldap query", required = true, multiValued = false)
-    @Completion(ConfigurationCompleter.class)
-    String pid;
-
-    @Option(name = "--force", aliases = {}, description = "Force the edition of this config, even if another one was under edition", required = false, multiValued = false)
-    boolean force;
-    
-    @Option(name = "--factory", aliases = {}, description = "Define this config as a factory config. Will be crearted on calling update", required = false, multiValued = false)
-    boolean factory;
-
-    @SuppressWarnings("rawtypes")
-    protected Object doExecute() throws Exception {
-        String oldPid = (String) this.session.get(PROPERTY_CONFIG_PID);
-        if (oldPid != null && !oldPid.equals(pid) && !force) {
-            System.err.println("Another config is being edited.  Cancel / update first, or use the --force option");
-            return null;
-        }
-        
-        if (pid.startsWith("(")) {
-        	Configuration[] configs = this.configRepository.getConfigAdmin().listConfigurations(pid);
-        	if (configs.length == 0) {
-        		throw new RuntimeException("Filter matches no config");
-        	}
-        	if (configs.length > 1) {
-        		throw new RuntimeException("Filter matches more than one config");
-        	}
-        	pid = configs[0].getPid();
-        	System.out.println("Editing config " + pid);
-        }
-
-        Dictionary props = this.configRepository.getConfigProperties(pid);
-        this.session.put(PROPERTY_CONFIG_PID, pid);
-        this.session.put(PROPERTY_FACTORY, factory);
-        this.session.put(PROPERTY_CONFIG_PROPS, props);
-        return null;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d33e0955/config/command/src/main/java/org/apache/karaf/config/command/ListCommand.java
----------------------------------------------------------------------
diff --git a/config/command/src/main/java/org/apache/karaf/config/command/ListCommand.java b/config/command/src/main/java/org/apache/karaf/config/command/ListCommand.java
deleted file mode 100644
index bce8410..0000000
--- a/config/command/src/main/java/org/apache/karaf/config/command/ListCommand.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * 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.karaf.config.command;
-
-import java.util.Dictionary;
-import java.util.Enumeration;
-import java.util.Map;
-import java.util.TreeMap;
-
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.osgi.service.cm.Configuration;
-
-@Command(scope = "config", name = "list", description = "Lists existing configurations.")
-@Service
-public class ListCommand extends ConfigCommandSupport {
-
-    @Argument(index = 0, name = "query", description = "Query in LDAP syntax. Example: \"(service.pid=org.apache.karaf.log)\"", required = false, multiValued = false)
-    String query;
-
-    @SuppressWarnings("rawtypes")
-    protected Object doExecute() throws Exception {
-        Configuration[] configs = configRepository.getConfigAdmin().listConfigurations(query);
-        if (configs != null) {
-            Map<String, Configuration> sortedConfigs = new TreeMap<String, Configuration>();
-            for (Configuration config : configs) {
-                sortedConfigs.put(config.getPid(), config);
-            }
-            for (String pid : sortedConfigs.keySet()) {
-                Configuration config = sortedConfigs.get(pid);
-                System.out.println("----------------------------------------------------------------");
-                System.out.println("Pid:            " + config.getPid());
-                if (config.getFactoryPid() != null) {
-                    System.out.println("FactoryPid:     " + config.getFactoryPid());
-                }
-                System.out.println("BundleLocation: " + config.getBundleLocation());
-                if (config.getProperties() != null) {
-                    System.out.println("Properties:");
-                    Dictionary props = config.getProperties();
-                    Map<String, Object> sortedProps = new TreeMap<String, Object>();
-                    for (Enumeration e = props.keys(); e.hasMoreElements();) {
-                        Object key = e.nextElement();
-                        sortedProps.put(key.toString(), props.get(key));
-                    }
-                    for (String key : sortedProps.keySet()) {
-                        System.out.println("   " + key + " = " + sortedProps.get(key));
-                    }
-                }
-            }
-        }
-        return null;
-    }
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d33e0955/config/command/src/main/java/org/apache/karaf/config/command/PropAppendCommand.java
----------------------------------------------------------------------
diff --git a/config/command/src/main/java/org/apache/karaf/config/command/PropAppendCommand.java b/config/command/src/main/java/org/apache/karaf/config/command/PropAppendCommand.java
deleted file mode 100644
index f021146..0000000
--- a/config/command/src/main/java/org/apache/karaf/config/command/PropAppendCommand.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * 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.karaf.config.command;
-
-import java.util.Dictionary;
-
-import org.apache.karaf.config.command.completers.ConfigurationPropertyCompleter;
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Completion;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-
-@Command(scope = "config", name = "property-append", description = "Appends the given value to an existing property or creates the property with the specified name and value.")
-@Service
-public class PropAppendCommand extends ConfigPropertyCommandSupport {
-
-    @Argument(index = 0, name = "name", description = "The name of the property", required = true, multiValued = false)
-    @Completion(ConfigurationPropertyCompleter.class)
-    String prop;
-
-    @Argument(index = 1, name = "value", description = "The value to append to the property", required = true, multiValued = false)
-    String value;
-
-    @SuppressWarnings({"unchecked", "rawtypes"})
-    @Override
-    public void propertyAction(Dictionary props) {
-        final Object currentValue = props.get(prop);
-        if (currentValue == null) {
-            props.put(prop, value);
-        } else if (currentValue instanceof String) {
-            props.put(prop, currentValue + value);
-        } else {
-            System.err.println("Append Failed: current value is not a String.");
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d33e0955/config/command/src/main/java/org/apache/karaf/config/command/PropDelCommand.java
----------------------------------------------------------------------
diff --git a/config/command/src/main/java/org/apache/karaf/config/command/PropDelCommand.java b/config/command/src/main/java/org/apache/karaf/config/command/PropDelCommand.java
deleted file mode 100644
index e416cf6..0000000
--- a/config/command/src/main/java/org/apache/karaf/config/command/PropDelCommand.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * 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.karaf.config.command;
-
-import java.util.Dictionary;
-
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-
-
-@Command(scope = "config", name = "property-delete", description = "Deletes a property from the configuration being edited.")
-@Service
-public class PropDelCommand extends ConfigPropertyCommandSupport {
-
-    @Argument(index = 0, name = "property", description = "The name of the property to delete", required = true, multiValued = false)
-    String prop;
-
-    @SuppressWarnings("rawtypes")
-    @Override
-    public void propertyAction(Dictionary props) {
-        props.remove(prop);
-    }
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d33e0955/config/command/src/main/java/org/apache/karaf/config/command/PropListCommand.java
----------------------------------------------------------------------
diff --git a/config/command/src/main/java/org/apache/karaf/config/command/PropListCommand.java b/config/command/src/main/java/org/apache/karaf/config/command/PropListCommand.java
deleted file mode 100644
index a0d3a61..0000000
--- a/config/command/src/main/java/org/apache/karaf/config/command/PropListCommand.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * 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.karaf.config.command;
-
-import java.util.Dictionary;
-import java.util.Enumeration;
-
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-
-@Command(scope = "config", name = "property-list", description = "Lists properties from the currently edited configuration.")
-@Service
-public class PropListCommand extends ConfigPropertyCommandSupport {
-
-    @SuppressWarnings("rawtypes")
-    @Override
-    public void propertyAction(Dictionary props) {
-        for (Enumeration e = props.keys(); e.hasMoreElements(); ) {
-            Object key = e.nextElement();
-            System.out.println("   " + key + " = " + props.get(key));
-        }
-    }
-
-    /**
-     * List commands never requires an update, so it always returns false.
-     * @param pid
-     * @return
-     */
-    @Override
-    protected boolean requiresUpdate(String pid) {
-        return false;
-    }
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d33e0955/config/command/src/main/java/org/apache/karaf/config/command/PropSetCommand.java
----------------------------------------------------------------------
diff --git a/config/command/src/main/java/org/apache/karaf/config/command/PropSetCommand.java b/config/command/src/main/java/org/apache/karaf/config/command/PropSetCommand.java
deleted file mode 100644
index 8337f6a..0000000
--- a/config/command/src/main/java/org/apache/karaf/config/command/PropSetCommand.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * 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.karaf.config.command;
-
-import java.util.Dictionary;
-
-import org.apache.karaf.config.command.completers.ConfigurationPropertyCompleter;
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Completion;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-
-@Command(scope = "config", name = "property-set", description = "Sets a property in the currently edited configuration.")
-@Service
-public class PropSetCommand extends ConfigPropertyCommandSupport {
-
-    @Argument(index = 0, name = "property", description = "The name of the property to set", required = true, multiValued = false)
-    @Completion(ConfigurationPropertyCompleter.class)
-    String prop;
-
-    @Argument(index = 1, name = "value", description = "The value of the property", required = true, multiValued = false)
-    String value;
-
-    @SuppressWarnings({"unchecked", "rawtypes"})
-    @Override
-    public void propertyAction(Dictionary props) {
-        props.put(prop, value);
-    }
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d33e0955/config/command/src/main/java/org/apache/karaf/config/command/UpdateCommand.java
----------------------------------------------------------------------
diff --git a/config/command/src/main/java/org/apache/karaf/config/command/UpdateCommand.java b/config/command/src/main/java/org/apache/karaf/config/command/UpdateCommand.java
deleted file mode 100644
index cc368b8..0000000
--- a/config/command/src/main/java/org/apache/karaf/config/command/UpdateCommand.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * 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.karaf.config.command;
-
-import java.util.Dictionary;
-
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-
-@Command(scope = "config", name = "update", description = "Saves and propagates changes from the configuration being edited.")
-@Service
-public class UpdateCommand extends ConfigCommandSupport {
-
-    @SuppressWarnings({ "rawtypes", "unchecked" })
-    protected Object doExecute() throws Exception {
-        Dictionary props = getEditedProps();
-        if (props == null) {
-            System.err.println("No configuration is being edited--run the edit command first");
-            return null;
-        }
-
-        String pid = (String) this.session.get(PROPERTY_CONFIG_PID);
-        boolean isFactory = this.session.get(PROPERTY_FACTORY) != null && (Boolean) this.session.get(PROPERTY_FACTORY);
-        if (isFactory) {
-        	this.configRepository.createFactoryConfiguration(pid, props);
-        } else {
-        	this.configRepository.update(pid, props);
-        }
-        this.session.put(PROPERTY_CONFIG_PID, null);
-        this.session.put(PROPERTY_FACTORY, null);
-        this.session.put(PROPERTY_CONFIG_PROPS, null);
-        return null;
-    }
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d33e0955/config/command/src/main/java/org/apache/karaf/config/command/completers/ConfigurationCompleter.java
----------------------------------------------------------------------
diff --git a/config/command/src/main/java/org/apache/karaf/config/command/completers/ConfigurationCompleter.java b/config/command/src/main/java/org/apache/karaf/config/command/completers/ConfigurationCompleter.java
deleted file mode 100644
index fe60c56..0000000
--- a/config/command/src/main/java/org/apache/karaf/config/command/completers/ConfigurationCompleter.java
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * 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.karaf.config.command.completers;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-
-import org.apache.karaf.shell.api.action.lifecycle.Destroy;
-import org.apache.karaf.shell.api.action.lifecycle.Init;
-import org.apache.karaf.shell.api.action.lifecycle.Reference;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.apache.karaf.shell.api.console.CommandLine;
-import org.apache.karaf.shell.api.console.Completer;
-import org.apache.karaf.shell.api.console.Session;
-import org.apache.karaf.shell.support.completers.StringsCompleter;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.ServiceRegistration;
-import org.osgi.service.cm.Configuration;
-import org.osgi.service.cm.ConfigurationAdmin;
-import org.osgi.service.cm.ConfigurationEvent;
-import org.osgi.service.cm.ConfigurationListener;
-
-/**
- * {@link Completer} for Configuration Admin configurations.
- *
- * Displays a list of existing config instance configurations for completion.
- *
- */
-@Service
-public class ConfigurationCompleter implements Completer, ConfigurationListener {
-
-    private final StringsCompleter delegate = new StringsCompleter();
-
-    @Reference
-    private ConfigurationAdmin admin;
-
-    @Reference
-    private BundleContext bundleContext;
-
-    private ServiceRegistration<ConfigurationListener> registration;
-
-    public void setAdmin(ConfigurationAdmin admin) {
-        this.admin = admin;
-    }
-
-    @Init
-    public void init() {
-        registration = bundleContext.registerService(ConfigurationListener.class, this, null);
-
-        Configuration[] configs;
-        try {
-            configs = admin.listConfigurations(null);
-            if (configs == null) {
-                return;
-            }
-        } catch (Exception e) {
-            return;
-        }
-
-        Collection<String> pids = new ArrayList<String>();
-        for (Configuration config : configs) {
-            pids.add(config.getPid());
-        }
-
-        delegate.getStrings().addAll(pids);
-    }
-
-    @Destroy
-    public void destroy() {
-        registration.unregister();
-    }
-
-    public int complete(final Session session, final CommandLine commandLine, final List<String> candidates) {
-        return delegate.complete(session, commandLine, candidates);
-    }
-
-    public void configurationEvent(ConfigurationEvent configurationEvent) {
-        String pid = configurationEvent.getPid();
-        if (configurationEvent.getType() == ConfigurationEvent.CM_DELETED) {
-            delegate.getStrings().remove(pid);
-        } else if (configurationEvent.getType() == ConfigurationEvent.CM_UPDATED) {
-            delegate.getStrings().add(pid);
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d33e0955/config/command/src/main/java/org/apache/karaf/config/command/completers/ConfigurationPropertyCompleter.java
----------------------------------------------------------------------
diff --git a/config/command/src/main/java/org/apache/karaf/config/command/completers/ConfigurationPropertyCompleter.java b/config/command/src/main/java/org/apache/karaf/config/command/completers/ConfigurationPropertyCompleter.java
deleted file mode 100644
index 2b43fec..0000000
--- a/config/command/src/main/java/org/apache/karaf/config/command/completers/ConfigurationPropertyCompleter.java
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * 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.karaf.config.command.completers;
-
-import java.io.IOException;
-import java.util.Arrays;
-import java.util.Dictionary;
-import java.util.Enumeration;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-import org.apache.karaf.config.command.ConfigCommandSupport;
-import org.apache.karaf.shell.api.action.lifecycle.Reference;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.apache.karaf.shell.api.console.CommandLine;
-import org.apache.karaf.shell.api.console.Completer;
-import org.apache.karaf.shell.api.console.Session;
-import org.apache.karaf.shell.support.completers.StringsCompleter;
-import org.osgi.framework.InvalidSyntaxException;
-import org.osgi.service.cm.Configuration;
-import org.osgi.service.cm.ConfigurationAdmin;
-
-/**
- * {@link Completer} for Configuration Admin properties.
- *
- * Displays a list of existing properties based on the current configuration being edited.
- *
- */
-@Service
-public class ConfigurationPropertyCompleter implements Completer {
-
-    private final StringsCompleter delegate = new StringsCompleter();
-
-    private static final String OPTION = "-p";
-    private static final String ALIAS = "--pid";
-
-    @Reference
-    private ConfigurationAdmin configAdmin;
-
-    @SuppressWarnings("rawtypes")
-    public int complete(final Session session, final CommandLine commandLine, final List<String> candidates) {
-        if (session != null) {
-            String pid = getPid(session, commandLine);
-            Set<String> propertyNames = getPropertyNames(pid);
-            delegate.getStrings().clear();
-            if (propertyNames != null && !propertyNames.isEmpty()) {
-                delegate.getStrings().addAll(propertyNames);
-            }
-        }
-        return delegate.complete(session, commandLine, candidates);
-    }
-
-    /**
-     * Retrieves the pid stored in the {@link Session} or passed as an argument.
-     * Argument takes precedence from pid stored in the {@link Session}.
-     */
-    private String getPid(Session session, CommandLine commandLine) {
-        String pid = (String) session.get(ConfigCommandSupport.PROPERTY_CONFIG_PID);
-        if (commandLine.getArguments().length > 0) {
-            List<String> arguments = Arrays.asList(commandLine.getArguments());
-            if (arguments.contains(OPTION)) {
-                int index = arguments.indexOf(OPTION);
-                if (arguments.size() > index) {
-                    return arguments.get(index + 1);
-                }
-            }
-
-            if (arguments.contains(ALIAS)) {
-                int index = arguments.indexOf(ALIAS);
-                if (arguments.size() > index) {
-                    return arguments.get(index + 1);
-                }
-            }
-        }
-        return pid;
-    }
-
-    /**
-     * Returns the property names for the given pid.
-     * @param pid
-     * @return
-     */
-    @SuppressWarnings("rawtypes")
-    private Set<String> getPropertyNames(String pid) {
-        Set<String> propertyNames = new HashSet<String>();
-        if (pid != null) {
-            Configuration configuration = null;
-            try {
-                Configuration[] configs = configAdmin.listConfigurations("(service.pid="+pid+")");
-                if (configs != null && configs.length > 0) {
-                    configuration = configs[0];
-                    if (configuration != null) {
-                        Dictionary properties = configuration.getProperties();
-                        if (properties != null) {
-                            Enumeration keys = properties.keys();
-                            while (keys.hasMoreElements()) {
-                                propertyNames.add(String.valueOf(keys.nextElement()));
-                            }
-                        }
-                    }
-                }
-            } catch (IOException e) {
-              //Ignore
-            } catch (InvalidSyntaxException e) {
-                //Ignore
-            }
-        }
-        return propertyNames;
-    }
-
-    public ConfigurationAdmin getConfigAdmin() {
-        return configAdmin;
-    }
-
-    public void setConfigAdmin(ConfigurationAdmin configAdmin) {
-        this.configAdmin = configAdmin;
-    }
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d33e0955/config/command/src/main/resources/OSGI-INF/bundle.info
----------------------------------------------------------------------
diff --git a/config/command/src/main/resources/OSGI-INF/bundle.info b/config/command/src/main/resources/OSGI-INF/bundle.info
deleted file mode 100644
index 3cd35da..0000000
--- a/config/command/src/main/resources/OSGI-INF/bundle.info
+++ /dev/null
@@ -1,27 +0,0 @@
-h1. Synopsis
-
-${project.name}
-
-${project.description}
-
-Maven URL:
-[mvn:${project.groupId}/${project.artifactId}/${project.version}]
-
-h1. Description
-
-This bundle provides Karaf shell commands to manipulate the ConfigAdmin OSGi service.
-
-The following commands are available:
-* config:cancel - Cancels the changes to the configuration being edited.
-* config:edit - Creates or edits a configuration.
-* config:list - Lists existing configurations.
-* config:propappend - Appends the given value to an existing property or creates
- the property with the specified name and value.
-* config:propdel - Deletes a property from the edited configuration.
-* config:proplist - Lists properties from the currently edited configuration.
-* config:propset - Sets a property in the currently edited configuration.
-* config:update - Saves and propagates changes from the configuration being edited.
-
-h1. See also
-
-Commands - section of the Karaf User Guide.
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/karaf/blob/d33e0955/config/command/src/main/resources/org/apache/karaf/config/command/edit.txt
----------------------------------------------------------------------
diff --git a/config/command/src/main/resources/org/apache/karaf/config/command/edit.txt b/config/command/src/main/resources/org/apache/karaf/config/command/edit.txt
deleted file mode 100644
index 88fa6d5..0000000
--- a/config/command/src/main/resources/org/apache/karaf/config/command/edit.txt
+++ /dev/null
@@ -1,13 +0,0 @@
-The edit command can be used to create or edit a configuration in three ways.
-
-Edit or create a config by pid:
-  > config:edit org.apache.karaf.sample.pid
-The command above will also create a file etc/org.apache.karaf.sample.pid which corresponds to a configuration object with pid org.apache.karaf.sample.pid.
-  
-Create a factory config by factory pid:
-  > config:edit --factory myfactorypid
-In this case the config is created with a pid like myfactorypid.<generated id>. This config is not written to a file.
-
-Edit a config specified by an ldap query
-  > config:edit '(myattribute=myvalue)'
-This executes an ldap query like in config:list. If the result is exactly one config then it is edited.

http://git-wip-us.apache.org/repos/asf/karaf/blob/d33e0955/config/command/src/test/java/org/apache/karaf/config/command/EditCommandTest.java
----------------------------------------------------------------------
diff --git a/config/command/src/test/java/org/apache/karaf/config/command/EditCommandTest.java b/config/command/src/test/java/org/apache/karaf/config/command/EditCommandTest.java
deleted file mode 100644
index 09dc000..0000000
--- a/config/command/src/test/java/org/apache/karaf/config/command/EditCommandTest.java
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * 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.karaf.config.command;
-
-import java.util.Dictionary;
-import java.util.Properties;
-
-import junit.framework.TestCase;
-import org.apache.karaf.config.core.impl.ConfigRepositoryImpl;
-import org.apache.karaf.shell.api.console.Session;
-import org.osgi.framework.BundleContext;
-import org.osgi.service.cm.Configuration;
-import org.osgi.service.cm.ConfigurationAdmin;
-
-import static org.easymock.EasyMock.createMock;
-import static org.easymock.EasyMock.expect;
-import static org.easymock.EasyMock.replay;
-
-/**
- * Test cases for {@link EditCommand}
- */
-public class EditCommandTest extends TestCase {
-
-    private static final String PID = "my.test.persistent.id";
-
-    private EditCommand command;
-    private BundleContext context;
-    private ConfigurationAdmin admin;
-    private Session session;
-
-    @Override
-    protected void setUp() throws Exception {
-        command = new EditCommand();
-
-        admin = createMock(ConfigurationAdmin.class);
-        command.setConfigRepository(new ConfigRepositoryImpl(admin));
-
-        session = new MockCommandSession();
-        command.setSession(session);
-    }
-    
-    public void testExecuteOnExistingPid() throws Exception {        
-        Configuration config = createMock(Configuration.class);
-        expect(admin.getConfiguration(PID)).andReturn(config);
-        replay(admin);
-        
-        // the ConfigAdmin service returns a Dictionary for an existing PID
-        Dictionary props = new Properties();
-        expect(config.getProperties()).andReturn(props);
-        replay(config);
-        
-        command.pid = PID; 
-        command.execute();
-        
-        // the PID and Dictionary should have been set on the session
-        assertEquals("The PID should be set on the session",
-                     PID, session.get(ConfigCommandSupport.PROPERTY_CONFIG_PID));
-        assertSame("The Dictionary returned by the ConfigAdmin service should be set on the session",
-                   props, session.get(ConfigCommandSupport.PROPERTY_CONFIG_PROPS));
-    }
-    
-    @SuppressWarnings("rawtypes")
-    public void testExecuteOnNewPid() throws Exception {        
-        Configuration config = createMock(Configuration.class);
-        expect(admin.getConfiguration(PID)).andReturn(config);
-        replay(admin);
-        
-        // the ConfigAdmin service does not return a Dictionary for a new PID
-        expect(config.getProperties()).andReturn(null);
-        replay(config);
-        
-        command.pid = PID; 
-        command.execute();
-
-        // the PID and an empty Dictionary should have been set on the session        
-        assertEquals("The PID should be set on the session",
-                     PID, session.get(ConfigCommandSupport.PROPERTY_CONFIG_PID));
-        Dictionary props = (Dictionary) session.get(ConfigCommandSupport.PROPERTY_CONFIG_PROPS);
-        assertNotNull("Should have a Dictionary on the session", props);
-        assertTrue("Should have an empty Dictionary on the session", props.isEmpty());
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d33e0955/config/command/src/test/java/org/apache/karaf/config/command/MockCommandSession.java
----------------------------------------------------------------------
diff --git a/config/command/src/test/java/org/apache/karaf/config/command/MockCommandSession.java b/config/command/src/test/java/org/apache/karaf/config/command/MockCommandSession.java
deleted file mode 100644
index 7fa430b..0000000
--- a/config/command/src/test/java/org/apache/karaf/config/command/MockCommandSession.java
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * 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.karaf.config.command;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.PrintStream;
-import java.util.HashMap;
-import java.util.Map;
-
-import org.apache.karaf.shell.api.console.History;
-import org.apache.karaf.shell.api.console.Registry;
-import org.apache.karaf.shell.api.console.Session;
-import org.apache.karaf.shell.api.console.SessionFactory;
-import org.apache.karaf.shell.api.console.Terminal;
-
-/*
- * A mock CommandSession implementation that only cares about the properties set on the session
- */
-class MockCommandSession implements Session {
-
-    private Map<String, Object> properties = new HashMap<String, Object>();
-
-    public void close() {
-        // not implemented
-    }
-
-    public Object execute(CharSequence commandline) throws Exception {
-        // not implemented
-        return null;
-    }
-
-    public Object get(String name) {
-        return properties.get(name);
-    }
-
-    public PrintStream getConsole() {
-        // not implemented
-        return null;
-    }
-
-    public InputStream getKeyboard() {
-        // not implemented
-        return null;
-    }
-
-    public void put(String name, Object value) {
-        properties.put(name, value);
-    }
-
-    @Override
-    public String readLine(String prompt, Character mask) throws IOException {
-        return null;
-    }
-
-    @Override
-    public Terminal getTerminal() {
-        return null;
-    }
-
-    @Override
-    public History getHistory() {
-        return null;
-    }
-
-    @Override
-    public Registry getRegistry() {
-        return null;
-    }
-
-    @Override
-    public SessionFactory getFactory() {
-        return null;
-    }
-
-    @Override
-    public String resolveCommand(String name) {
-        return null;
-    }
-
-    @Override
-    public void run() {
-
-    }
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d33e0955/config/command/src/test/java/org/apache/karaf/config/command/UpdateCommandTest.java
----------------------------------------------------------------------
diff --git a/config/command/src/test/java/org/apache/karaf/config/command/UpdateCommandTest.java b/config/command/src/test/java/org/apache/karaf/config/command/UpdateCommandTest.java
deleted file mode 100644
index e3f58b5..0000000
--- a/config/command/src/test/java/org/apache/karaf/config/command/UpdateCommandTest.java
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * 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.karaf.config.command;
-
-
-import static org.easymock.EasyMock.expect;
-import static org.easymock.EasyMock.replay;
-
-import java.util.Dictionary;
-import java.util.Hashtable;
-
-import junit.framework.TestCase;
-
-import org.apache.karaf.config.core.ConfigRepository;
-import org.easymock.EasyMock;
-
-/**
- * Test cases for {@link EditCommand}
- */
-public class UpdateCommandTest extends TestCase {
-
-    private static final String FACTORY_PID = "myFactoryPid";
-    private static final String PID = "myPid";
-
-    public void testupdateRegularConfig() throws Exception {
-		Dictionary<String, Object> props = new Hashtable<String, Object>();
-
-        UpdateCommand command = new UpdateCommand();
-        ConfigRepository configRepo = EasyMock.createMock(ConfigRepository.class);
-        configRepo.update(EasyMock.eq(PID), EasyMock.eq(props));
-        EasyMock.expectLastCall();
-		command.setConfigRepository(configRepo);
-
-        MockCommandSession session = createMockSessionForFactoryEdit(PID, false, props);
-        command.setSession(session);
-        replay(configRepo);
-
-        command.execute();
-        EasyMock.verify(configRepo);
-    }
-    
-    public void testupdateOnNewFactoryPid() throws Exception {
-		Dictionary<String, Object> props = new Hashtable<String, Object>();
-
-        UpdateCommand command = new UpdateCommand();
-        ConfigRepository configRepo = EasyMock.createMock(ConfigRepository.class);
-        expect(configRepo.createFactoryConfiguration(EasyMock.eq(FACTORY_PID), EasyMock.eq(props)))
-        	.andReturn(PID + ".35326647");
-		command.setConfigRepository(configRepo);
-
-        MockCommandSession session = createMockSessionForFactoryEdit(FACTORY_PID, true, props);
-        command.setSession(session);
-        replay(configRepo);
-
-        command.execute();
-        EasyMock.verify(configRepo);
-    }
-
-	private MockCommandSession createMockSessionForFactoryEdit(String pid, boolean isFactory, 
-			Dictionary<String, Object> props) {
-		MockCommandSession session = new MockCommandSession();
-        session.put(ConfigCommandSupport.PROPERTY_CONFIG_PID, pid);
-        session.put(ConfigCommandSupport.PROPERTY_FACTORY, isFactory);
-        session.put(ConfigCommandSupport.PROPERTY_CONFIG_PROPS, props);
-		return session;
-	}
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d33e0955/config/core/NOTICE
----------------------------------------------------------------------
diff --git a/config/core/NOTICE b/config/core/NOTICE
deleted file mode 100644
index b70f1f9..0000000
--- a/config/core/NOTICE
+++ /dev/null
@@ -1,71 +0,0 @@
-Apache Karaf
-Copyright 2010-2014 The Apache Software Foundation
-
-
-I. Included Software
-
-This product includes software developed at
-The Apache Software Foundation (http://www.apache.org/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-The OSGi Alliance (http://www.osgi.org/).
-Copyright (c) OSGi Alliance (2000, 2010).
-Licensed under the Apache License 2.0.
-
-This product includes software developed at
-OW2 (http://www.ow2.org/).
-Licensed under the BSD License.
-
-This product includes software developed at
-OPS4J (http://www.ops4j.org/).
-Licensed under the Apache License 2.0.
-
-This product includes software developed at
-Eclipse Foundation (http://www.eclipse.org/).
-Licensed under the EPL.
-
-This product includes software written by
-Antony Lesuisse.
-Licensed under Public Domain.
-
-
-II. Used Software
-
-This product uses software developed at
-FUSE Source (http://www.fusesource.org/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-AOP Alliance (http://aopalliance.sourceforge.net/).
-Licensed under the Public Domain.
-
-This product uses software developed at
-Tanuki Software (http://www.tanukisoftware.com/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-Jasypt (http://jasypt.sourceforge.net/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-JLine (http://jline.sourceforge.net).
-Licensed under the BSD License.
-
-This product uses software developed at
-SLF4J (http://www.slf4j.org/).
-Licensed under the MIT License.
-
-This product uses software developed at
-SpringSource (http://www.springsource.org/).
-Licensed under the Apache License 2.0.
-
-This product includes software from http://www.json.org.
-Copyright (c) 2002 JSON.org
-
-
-III. License Summary
-- Apache License 2.0
-- BSD License
-- EPL License
-- MIT License

http://git-wip-us.apache.org/repos/asf/karaf/blob/d33e0955/config/core/pom.xml
----------------------------------------------------------------------
diff --git a/config/core/pom.xml b/config/core/pom.xml
deleted file mode 100644
index a1a646b..0000000
--- a/config/core/pom.xml
+++ /dev/null
@@ -1,111 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-
-    <!--
-
-        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.
-    -->
-
-    <modelVersion>4.0.0</modelVersion>
-
-    <parent>
-        <groupId>org.apache.karaf.config</groupId>
-        <artifactId>config</artifactId>
-        <version>4.0.0-SNAPSHOT</version>
-        <relativePath>../pom.xml</relativePath>
-    </parent>
-
-    <artifactId>org.apache.karaf.config.core</artifactId>
-    <packaging>bundle</packaging>
-    <name>Apache Karaf :: ConfigAdmin :: Core</name>
-    <description>This bundle provides Karaf services</description>
-
-    <properties>
-        <appendedResourcesDirectory>${basedir}/../etc/appended-resources</appendedResourcesDirectory>
-    </properties>
-
-    <dependencies>
-        <dependency>
-            <groupId>org.osgi</groupId>
-            <artifactId>org.osgi.core</artifactId>
-        </dependency>
-
-        <dependency>
-            <groupId>org.osgi</groupId>
-            <artifactId>org.osgi.compendium</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        
-        <dependency>
-            <groupId>org.slf4j</groupId>
-            <artifactId>slf4j-api</artifactId>
-        </dependency>
-
-        <dependency>
-            <groupId>org.apache.karaf</groupId>
-            <artifactId>org.apache.karaf.util</artifactId>
-        </dependency>
-        
-        <dependency>
-            <groupId>org.slf4j</groupId>
-            <artifactId>slf4j-jdk14</artifactId>
-            <scope>test</scope>
-        </dependency>
-    </dependencies>
-
-    <build>
-        <resources>
-            <resource>
-                <directory>${project.basedir}/src/main/resources</directory>
-                <includes>
-                    <include>**/*</include>
-                </includes>
-            </resource>
-            <resource>
-                <directory>${project.basedir}/src/main/resources</directory>
-                <filtering>true</filtering>
-                <includes>
-                    <include>**/*.info</include>
-                </includes>
-            </resource>
-        </resources>
-        <plugins>
-            <plugin>
-                <groupId>org.apache.felix</groupId>
-                <artifactId>maven-bundle-plugin</artifactId>
-                <configuration>
-                    <instructions>
-                        <Export-Package>
-                            org.apache.karaf.config.core
-                        </Export-Package>
-                        <Import-Package>
-                            *
-                        </Import-Package>
-                        <Private-Package>
-                            org.apache.karaf.config.core.impl,
-                            org.apache.karaf.config.core.impl.osgi,
-                            org.apache.karaf.util.tracker
-                        </Private-Package>
-                        <Bundle-Activator>
-                            org.apache.karaf.config.core.impl.osgi.Activator
-                        </Bundle-Activator>
-                    </instructions>
-                </configuration>
-            </plugin>
-        </plugins>
-    </build>
-
-</project>

http://git-wip-us.apache.org/repos/asf/karaf/blob/d33e0955/config/core/src/main/java/org/apache/karaf/config/core/ConfigMBean.java
----------------------------------------------------------------------
diff --git a/config/core/src/main/java/org/apache/karaf/config/core/ConfigMBean.java b/config/core/src/main/java/org/apache/karaf/config/core/ConfigMBean.java
deleted file mode 100644
index 9cb9f7f..0000000
--- a/config/core/src/main/java/org/apache/karaf/config/core/ConfigMBean.java
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * 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.config.core;
-
-import javax.management.MBeanException;
-import java.util.List;
-import java.util.Map;
-
-/**
- * MBean to manipulate the Config layer.
- */
-public interface ConfigMBean {
-
-    /**
-     * Get the list of all configuration PIDs.
-     *
-     * @return the list of all configuration PIDs.
-     * @throws Exception
-     */
-    List<String> getConfigs() throws MBeanException;
-
-    /**
-     * Create a new configuration for the given PID.
-     *
-     * @param pid the configuration PID.
-     * @throws Exception
-     */
-    void create(String pid) throws MBeanException;
-
-    /**
-     * Delete a configuration identified by the given PID.
-     *
-     * @param pid the configuration PID to delete.
-     * @throws Exception
-     */
-    void delete(String pid) throws MBeanException;
-
-    /**
-     * Get the list of properties for a configuration PID.
-     *
-     * @param pid the configuration PID.
-     * @return the list of properties.
-     * @throws Exception
-     */
-    Map<String, String> listProperties(String pid) throws MBeanException;
-
-    /**
-     * Remove the configuration property identified by the given key.
-     *
-     * @param pid the configuration PID.
-     * @param key the property key.
-     * @throws Exception
-     */
-    void deleteProperty(String pid, String key) throws MBeanException;
-
-    /**
-     * Append (or add) a value for the given configuration key.
-     *
-     * @param pid the configuration PID.
-     * @param key the property key.
-     * @param value the value to append to the current property value.
-     * @throws Exception
-     */
-    void appendProperty(String pid, String key, String value) throws MBeanException;
-
-    /**
-     * Set a configuration property.
-     *
-     * @param pid the configuration PID.
-     * @param key the property key.
-     * @param value the property value.
-     * @throws Exception
-     */
-    void setProperty(String pid, String key, String value) throws MBeanException;
-
-    /**
-     * Update a complete configuration.
-     *
-     * @param pid the configuration PID.
-     * @param properties the new properties to set in the configuration.
-     * @throws MBeanException
-     */
-    void update(String pid, Map<String, String> properties) throws MBeanException;
-    
-    /**
-     * Create a factory based configuration.
-     *
-     * @param factoryPid
-     * @param properties the new properties to set in the configuration.
-     * @return created pid
-     * @throws MBeanException
-     */
-    String createFactoryConfiguration(String factoryPid, Map<String, String> properties) throws MBeanException;
-
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d33e0955/config/core/src/main/java/org/apache/karaf/config/core/ConfigRepository.java
----------------------------------------------------------------------
diff --git a/config/core/src/main/java/org/apache/karaf/config/core/ConfigRepository.java b/config/core/src/main/java/org/apache/karaf/config/core/ConfigRepository.java
deleted file mode 100644
index 8121679..0000000
--- a/config/core/src/main/java/org/apache/karaf/config/core/ConfigRepository.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * 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.karaf.config.core;
-
-import java.io.IOException;
-import java.util.Dictionary;
-
-import org.osgi.framework.InvalidSyntaxException;
-import org.osgi.service.cm.ConfigurationAdmin;
-
-public interface ConfigRepository {
-
-    /**
-     * Saves config to storage or ConfigurationAdmin.
-     * @param pid
-     * @param props
-     * @throws IOException
-     */
-    @SuppressWarnings("rawtypes")
-    void update(String pid, Dictionary props) throws IOException;
-
-    void delete(String pid) throws Exception;
-
-    @SuppressWarnings("rawtypes")
-    Dictionary getConfigProperties(String pid) throws IOException, InvalidSyntaxException;
-
-    ConfigurationAdmin getConfigAdmin();
-
-    /**
-     * Create a factory based configuration.
-     *
-     * @param factoryPid
-     * @param properties the new properties to set in the configuration.
-     * @return created pid
-     */
-	String createFactoryConfiguration(String factoryPid, Dictionary<String, ?> properties);
-}


[26/59] [abbrv] [KARAF-2852] Merge instance/core and instance/command

Posted by gn...@apache.org.
http://git-wip-us.apache.org/repos/asf/karaf/blob/7c2db062/instance/src/main/java/org/apache/karaf/instance/core/internal/InstanceServiceImpl.java
----------------------------------------------------------------------
diff --git a/instance/src/main/java/org/apache/karaf/instance/core/internal/InstanceServiceImpl.java b/instance/src/main/java/org/apache/karaf/instance/core/internal/InstanceServiceImpl.java
new file mode 100644
index 0000000..535c2a0
--- /dev/null
+++ b/instance/src/main/java/org/apache/karaf/instance/core/internal/InstanceServiceImpl.java
@@ -0,0 +1,1166 @@
+/*
+ * 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.karaf.instance.core.internal;
+
+import org.apache.karaf.instance.core.Instance;
+import org.apache.karaf.instance.core.InstanceService;
+import org.apache.karaf.instance.core.InstanceSettings;
+import org.apache.karaf.jpm.Process;
+import org.apache.karaf.jpm.impl.ProcessBuilderFactoryImpl;
+import org.apache.karaf.jpm.impl.ScriptUtils;
+import org.apache.karaf.util.locks.FileLockUtils;
+import org.fusesource.jansi.Ansi;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.FilenameFilter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.InterruptedIOException;
+import java.io.OutputStream;
+import java.io.PrintStream;
+import java.net.Socket;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Scanner;
+
+public class InstanceServiceImpl implements InstanceService {
+
+    public static final String STORAGE_FILE = "instance.properties";
+    public static final String BACKUP_EXTENSION = ".bak";
+    private static final String FEATURES_CFG = "etc/org.apache.karaf.features.cfg";
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(InstanceServiceImpl.class);
+
+    private static final String CONFIG_PROPERTIES_FILE_NAME = "config.properties";
+
+    private static final String KARAF_SHUTDOWN_PORT = "karaf.shutdown.port";
+
+    private static final String KARAF_SHUTDOWN_HOST = "karaf.shutdown.host";
+
+    private static final String KARAF_SHUTDOWN_PORT_FILE = "karaf.shutdown.port.file";
+
+    private static final String KARAF_SHUTDOWN_COMMAND = "karaf.shutdown.command";
+
+    private static final String KARAF_SHUTDOWN_PID_FILE = "karaf.shutdown.pid.file";
+
+    private static final String DEFAULT_SHUTDOWN_COMMAND = "SHUTDOWN";
+
+    public static final String DEFAULT_JAVA_OPTS = "-server -Xmx512M -Dcom.sun.management.jmxremote -XX:+UnlockDiagnosticVMOptions -XX:+UnsyncloadClass";
+
+    private LinkedHashMap<String, InstanceImpl> proxies = new LinkedHashMap<String, InstanceImpl>();
+
+    private File storageLocation;
+
+    private long stopTimeout = 30000;
+
+    static class InstanceState {
+        String name;
+        String loc;
+        String opts;
+        int pid;
+        boolean root;
+    }
+
+    static class State {
+        int defaultSshPortStart = 8101;
+        int defaultRmiRegistryPortStart = 1099;
+        int defaultRmiServerPortStart = 44444;
+        Map<String, InstanceState> instances;
+    }
+
+    public InstanceServiceImpl() {
+        String prop = System.getProperty("karaf.instances");
+        if (prop != null) {
+            storageLocation = new File(prop);
+        }
+    }
+
+    public File getStorageLocation() {
+        return storageLocation;
+    }
+
+    public void setStorageLocation(File storage) {
+        this.storageLocation = storage;
+    }
+
+    public long getStopTimeout() {
+        return stopTimeout;
+    }
+
+    public void setStopTimeout(long stopTimeout) {
+        this.stopTimeout = stopTimeout;
+    }
+
+    private State loadData(org.apache.felix.utils.properties.Properties storage) {
+        State state = new State();
+        int count = getInt(storage, "count", 0);
+        state.defaultSshPortStart = getInt(storage, "ssh.port", state.defaultSshPortStart);
+        state.defaultRmiRegistryPortStart = getInt(storage, "rmi.registry.port", state.defaultRmiRegistryPortStart);
+        state.defaultRmiServerPortStart = getInt(storage, "rmi.server.port", state.defaultRmiServerPortStart);
+        state.instances = new LinkedHashMap<String, InstanceState>();
+
+        for (int i = 0; i < count; i++) {
+            InstanceState instance = new InstanceState();
+            instance.name = getString(storage, "item." + i + ".name", null);
+            instance.loc = getString(storage, "item." + i + ".loc", null);
+            instance.opts = getString(storage, "item." + i + ".opts", null);
+            instance.pid = getInt(storage, "item." + i + ".pid", 0);
+            instance.root = getBool(storage, "item." + i + ".root", false);
+            state.instances.put(instance.name, instance);
+        }
+        // Update proxies list
+        for (InstanceState instance : state.instances.values()) {
+            if (!this.proxies.containsKey(instance.name)) {
+                proxies.put(instance.name, new InstanceImpl(this, instance.name));
+            }
+        }
+        List<String> names = new ArrayList<String>(this.proxies.keySet());
+        for (String name : names) {
+            if (!state.instances.containsKey(name)) {
+                this.proxies.remove(name);
+            }
+        }
+        return state;
+    }
+
+    private void saveData(State state, org.apache.felix.utils.properties.Properties storage) {
+        storage.put("ssh.port", Integer.toString(state.defaultSshPortStart));
+        storage.put("rmi.registry.port", Integer.toString(state.defaultRmiRegistryPortStart));
+        storage.put("rmi.server.port", Integer.toString(state.defaultRmiServerPortStart));
+        storage.put("count", Integer.toString(state.instances.size()));
+        int i = 0;
+        for (InstanceState instance : state.instances.values()) {
+            storage.put("item." + i + ".name", instance.name);
+            storage.put("item." + i + ".root", Boolean.toString(instance.root));
+            storage.put("item." + i + ".loc", instance.loc);
+            storage.put("item." + i + ".pid", Integer.toString(instance.pid));
+            storage.put("item." + i + ".opts", instance.opts != null ? instance.opts : "");
+            i++;
+        }
+        while (storage.containsKey("item." + i + ".name")) {
+            storage.remove("item." + i + ".name");
+            storage.remove("item." + i + ".root");
+            storage.remove("item." + i + ".loc");
+            storage.remove("item." + i + ".pid");
+            storage.remove("item." + i + ".opts");
+            i++;
+        }
+    }
+
+    private boolean getBool(org.apache.felix.utils.properties.Properties storage, String name, boolean def) {
+        Object value = storage.get(name);
+        if (value != null) {
+            return Boolean.parseBoolean(value.toString());
+        } else {
+            return def;
+        }
+    }
+
+    private int getInt(org.apache.felix.utils.properties.Properties storage, String name, int def) {
+        Object value = storage.get(name);
+        if (value != null) {
+            return Integer.parseInt(value.toString());
+        } else {
+            return def;
+        }
+    }
+
+    private String getString(org.apache.felix.utils.properties.Properties storage, String name, String def) {
+        Object value = storage.get(name);
+        return value != null ? value.toString() : def;
+    }
+
+    interface Task<T> {
+        T call(State state) throws IOException;
+    }
+
+    synchronized <T> T execute(final Task<T> callback) {
+        final File storageFile = new File(storageLocation, STORAGE_FILE);
+        if (!storageFile.exists()) {
+            storageFile.getParentFile().mkdirs();
+            try {
+                storageFile.createNewFile();
+            } catch (IOException e) {
+                // Ignore
+            }
+        }
+        if (storageFile.exists()) {
+            if (!storageFile.isFile()) {
+                throw new IllegalStateException("Instance storage location should be a file: " + storageFile);
+            }
+            try {
+                return FileLockUtils.execute(storageFile, new FileLockUtils.CallableWithProperties<T>() {
+                    public T call(org.apache.felix.utils.properties.Properties properties) throws IOException {
+                        State state = loadData(properties);
+                        T t = callback.call(state);
+                        saveData(state, properties);
+                        return t;
+                    }
+                });
+            } catch (IOException e) {
+                throw new RuntimeException(e);
+            }
+        } else {
+            throw new IllegalStateException("Instance storage location does not exist: " + storageFile);
+        }
+    }
+
+    public synchronized void refreshInstance() throws Exception {
+    }
+
+    private void logInfo(String message, boolean printOutput, Object... args) {
+        if (LOGGER.isInfoEnabled() || printOutput) {
+            String formatted = String.format(message, args);
+            LOGGER.info(formatted);
+            if (printOutput) {
+                println(formatted);
+            }
+        }
+    }
+
+    public synchronized Instance createInstance(final String name, final InstanceSettings settings, final boolean printOutput) throws Exception {
+        return execute(new Task<Instance>() {
+            public Instance call(State state) throws IOException {
+                if (state.instances.get(name) != null) {
+                    throw new IllegalArgumentException("Instance '" + name + "' already exists");
+                }
+                String loc = settings.getLocation() != null ? settings.getLocation() : name;
+                File karafBase = new File(loc);
+                if (!karafBase.isAbsolute()) {
+                    karafBase = new File(storageLocation, loc);
+                }
+                int sshPort = settings.getSshPort();
+                if (sshPort <= 0) {
+                    sshPort = ++state.defaultSshPortStart;
+                }
+                int rmiRegistryPort = settings.getRmiRegistryPort();
+                if (rmiRegistryPort <= 0) {
+                    rmiRegistryPort = ++state.defaultRmiRegistryPortStart;
+                }
+                int rmiServerPort = settings.getRmiServerPort();
+                if (rmiServerPort <= 0) {
+                    rmiServerPort = ++state.defaultRmiServerPortStart;
+                }
+                logInfo("Creating new instance on SSH port %d and registry port %d / RMI server port %d at: %s",
+                        printOutput, sshPort, rmiRegistryPort, rmiServerPort, karafBase);
+
+                mkdir(karafBase, "bin", printOutput);
+                mkdir(karafBase, "etc", printOutput);
+                mkdir(karafBase, "system", printOutput);
+                mkdir(karafBase, "deploy", printOutput);
+                mkdir(karafBase, "data", printOutput);
+
+                copyResourceToDir(karafBase, "etc/all.policy", printOutput);
+                copyResourceToDir(karafBase, "etc/config.properties", printOutput);
+                copyResourceToDir(karafBase, "etc/custom.properties", printOutput);
+                copyResourceToDir(karafBase, "etc/distribution.info", printOutput);
+                copyResourceToDir(karafBase, "etc/equinox-debug.properties", printOutput);
+                copyResourceToDir(karafBase, "etc/java.util.logging.properties", printOutput);
+                copyResourceToDir(karafBase, "etc/jmx.acl.cfg", printOutput);
+                copyResourceToDir(karafBase, "etc/jmx.acl.java.lang.Memory.cfg", printOutput);
+                copyResourceToDir(karafBase, "etc/jmx.acl.org.apache.karaf.bundle.cfg", printOutput);
+                copyResourceToDir(karafBase, "etc/jmx.acl.org.apache.karaf.config.cfg", printOutput);
+                copyResourceToDir(karafBase, "etc/jmx.acl.org.apache.karaf.security.jmx.cfg", printOutput);
+                copyResourceToDir(karafBase, "etc/jmx.acl.osgi.compendium.cm.cfg", printOutput);
+                copyResourceToDir(karafBase, "etc/jre.properties", printOutput);
+                copyResourceToDir(karafBase, "etc/keys.properties", printOutput);
+                copyResourceToDir(karafBase, "etc/org.apache.felix.fileinstall-deploy.cfg", printOutput);
+                copyResourceToDir(karafBase, "etc/org.apache.karaf.command.acl.bundle.cfg", printOutput);
+                copyResourceToDir(karafBase, "etc/org.apache.karaf.command.acl.config.cfg", printOutput);
+                copyResourceToDir(karafBase, "etc/org.apache.karaf.command.acl.feature.cfg", printOutput);
+                copyResourceToDir(karafBase, "etc/org.apache.karaf.command.acl.jaas.cfg", printOutput);
+                copyResourceToDir(karafBase, "etc/org.apache.karaf.command.acl.kar.cfg", printOutput);
+                copyResourceToDir(karafBase, "etc/org.apache.karaf.command.acl.shell.cfg", printOutput);
+                copyResourceToDir(karafBase, "etc/org.apache.karaf.command.acl.system.cfg", printOutput);
+                copyResourceToDir(karafBase, "etc/org.apache.karaf.features.obr.cfg", printOutput);
+                copyResourceToDir(karafBase, "etc/org.apache.karaf.features.repos.cfg", printOutput);
+                copyResourceToDir(karafBase, "etc/org.apache.karaf.jaas.cfg", printOutput);
+                copyResourceToDir(karafBase, "etc/org.apache.karaf.kar.cfg", printOutput);
+                copyResourceToDir(karafBase, "etc/org.apache.karaf.log.cfg", printOutput);
+                copyResourceToDir(karafBase, "etc/org.ops4j.pax.logging.cfg", printOutput);
+                copyResourceToDir(karafBase, "etc/org.ops4j.pax.url.mvn.cfg", printOutput);
+                copyResourceToDir(karafBase, "etc/regions-config.xml", printOutput);
+                copyResourceToDir(karafBase, "etc/shell.init.script", printOutput);
+                copyResourceToDir(karafBase, "etc/users.properties", printOutput);
+
+                copyResourceToDir(karafBase, FEATURES_CFG, printOutput);
+                addFeaturesFromSettings(new File(karafBase, FEATURES_CFG), settings);
+
+                // The startup.properties is now generated by the karaf maven plugin, so
+                // we use the one from the root instance instead of embedding it
+                File rootEtc = new File(System.getProperty("karaf.etc"));
+                copy(new File(rootEtc, "startup.properties"), new File(karafBase, "etc/startup.properties"));
+
+                HashMap<String, String> props = new HashMap<String, String>();
+                props.put("${SUBST-KARAF-NAME}", name);
+                props.put("${SUBST-KARAF-HOME}", System.getProperty("karaf.home"));
+                props.put("${SUBST-KARAF-BASE}", karafBase.getPath());
+                props.put("${SUBST-SSH-PORT}", Integer.toString(sshPort));
+                props.put("${SUBST-RMI-REGISTRY-PORT}", Integer.toString(rmiRegistryPort));
+                props.put("${SUBST-RMI-SERVER-PORT}", Integer.toString(rmiServerPort));
+                copyFilteredResourceToDir(karafBase, "etc/system.properties", props, printOutput);
+                copyFilteredResourceToDir(karafBase, "etc/org.apache.karaf.shell.cfg", props, printOutput);
+                copyFilteredResourceToDir(karafBase, "etc/org.apache.karaf.management.cfg", props, printOutput);
+               
+                copyFilteredResourceToDir(karafBase, "bin/karaf", props, printOutput);
+                copyFilteredResourceToDir(karafBase, "bin/start", props, printOutput);
+                copyFilteredResourceToDir(karafBase, "bin/stop", props, printOutput);
+
+                copyFilteredResourceToDir(karafBase, "bin/karaf.bat", props, printOutput);
+                copyFilteredResourceToDir(karafBase, "bin/start.bat", props, printOutput);
+                copyFilteredResourceToDir(karafBase, "bin/stop.bat", props, printOutput);
+
+                try {
+                    chmod(new File(karafBase, "bin/karaf"), "a+x");
+                    chmod(new File(karafBase, "bin/start"), "a+x");
+                    chmod(new File(karafBase, "bin/stop"), "a+x");
+                } catch (IOException e) {
+                    LOGGER.debug("Could not set file mode on scripts.", e);
+                }
+
+                String javaOpts = settings.getJavaOpts();
+                if (javaOpts == null || javaOpts.length() == 0) {
+                    javaOpts = DEFAULT_JAVA_OPTS;
+                }
+                InstanceState is = new InstanceState();
+                is.name = name;
+                is.loc = karafBase.toString();
+                is.opts = javaOpts;
+                state.instances.put(name, is);
+                InstanceImpl instance = new InstanceImpl(InstanceServiceImpl.this, name);
+                InstanceServiceImpl.this.proxies.put(name, instance);
+                return instance;
+            }
+        });
+    }
+
+    void addFeaturesFromSettings(File featuresCfg, final InstanceSettings settings) throws IOException {
+        FileLockUtils.execute(featuresCfg, new FileLockUtils.RunnableWithProperties() {
+            public void run(org.apache.felix.utils.properties.Properties properties) throws IOException {
+                appendToPropList(properties, "featuresBoot", settings.getFeatures());
+                appendToPropList(properties, "featuresRepositories", settings.getFeatureURLs());
+            }
+        });
+    }
+
+    private void appendToPropList(org.apache.felix.utils.properties.Properties p, String key, List<String> elements) {
+        if (elements == null) {
+            return;
+        }
+        StringBuilder sb = new StringBuilder(p.get(key).toString().trim());
+        for (String f : elements) {
+            if (sb.length() > 0) {
+                sb.append(',');
+            }
+            sb.append(f);
+        }
+        p.put(key, sb.toString());
+    }
+
+    public Instance[] getInstances() {
+        return execute(new Task<Instance[]>() {
+            public Instance[] call(State state) throws IOException {
+                return proxies.values().toArray(new Instance[proxies.size()]);
+            }
+        });
+    }
+
+    public Instance getInstance(final String name) {
+        return execute(new Task<Instance>() {
+            public Instance call(State state) throws IOException {
+                return proxies.get(name);
+            }
+        });
+    }
+
+    public void startInstance(final String name, final String javaOpts) {
+        execute(new Task<Object>() {
+            public Object call(State state) throws IOException {
+                InstanceState instance = state.instances.get(name);
+                if (instance == null) {
+                    throw new IllegalArgumentException("Instance " + name + " not found");
+                }
+                checkPid(instance);
+                if (instance.pid != 0) {
+                    throw new IllegalStateException("Instance already started");
+                }
+                String opts = javaOpts;
+                if (opts == null || opts.length() == 0) {
+                    opts = instance.opts;
+                }
+                if (opts == null || opts.length() == 0) {
+                    opts = DEFAULT_JAVA_OPTS;
+                }
+
+                // fallback and read karafOpts from KARAF_OPTS environment if no System property present
+                String karafOptsEnv = System.getenv("KARAF_OPTS");
+                String karafOpts = System.getProperty("karaf.opts", karafOptsEnv != null ? karafOptsEnv : "");
+                
+                String location = instance.loc;
+
+                File libDir = new File(System.getProperty("karaf.home"), "lib");
+                File childLibDir = new File(location, "lib");
+                
+                StringBuilder classpath = classpathFromLibDir(libDir);
+                StringBuilder childClasspath = classpathFromLibDir(childLibDir);
+                if (childClasspath.length() > 0 && !libDir.equals(childLibDir)) {
+                    classpath.append(System.getProperty("path.separator"));
+                    classpath.append(childClasspath);
+                }    
+
+                String command = "\""
+                        + new File(System.getProperty("java.home"), ScriptUtils.isWindows() ? "bin\\java.exe" : "bin/java").getCanonicalPath()
+                        + "\" " + opts
+                        + " " + karafOpts
+                        + " -Djava.util.logging.config.file=\"" + new File(location, "etc/java.util.logging.properties").getCanonicalPath() + "\""
+                        + " -Djava.endorsed.dirs=\"" + new File(new File(new File(System.getProperty("java.home"), "jre"), "lib"), "endorsed") + System.getProperty("path.separator") + new File(new File(System.getProperty("java.home"), "lib"), "endorsed") + System.getProperty("path.separator") + new File(libDir, "endorsed").getCanonicalPath() + "\""
+                        + " -Djava.ext.dirs=\"" + new File(new File(new File(System.getProperty("java.home"), "jre"), "lib"), "ext") + System.getProperty("path.separator") + new File(new File(System.getProperty("java.home"), "lib"), "ext") + System.getProperty("path.separator") + new File(libDir, "ext").getCanonicalPath() + "\""
+                        + " -Dkaraf.home=\"" + System.getProperty("karaf.home") + "\""
+                        + " -Dkaraf.base=\"" + new File(location).getCanonicalPath() + "\""
+                        + " -Dkaraf.data=\"" + new File(new File(location).getCanonicalPath(), "data") + "\""
+                        + " -Dkaraf.etc=\"" + new File(new File(location).getCanonicalPath(), "etc") + "\""
+                        + " -Djavax.management.builder.initial=org.apache.karaf.management.boot.KarafMBeanServerBuilder"
+                        + " -Dkaraf.startLocalConsole=false"
+                        + " -Dkaraf.startRemoteShell=true"
+                        + " -classpath \"" + classpath.toString() + "\""
+                        + " org.apache.karaf.main.Main";
+                LOGGER.debug("Starting instance " + name + " with command: " + command);
+                org.apache.karaf.jpm.Process process = new ProcessBuilderFactoryImpl().newBuilder()
+                        .directory(new File(location))
+                        .command(command)
+                        .start();
+                instance.pid = process.getPid();
+                return null;
+            }
+
+            private StringBuilder classpathFromLibDir(File libDir) throws IOException {
+                File[] jars = libDir.listFiles(new FilenameFilter() {
+                    public boolean accept(File dir, String name) {
+                        return name.endsWith(".jar");
+                    }
+                });
+                StringBuilder classpath = new StringBuilder();
+                if (jars != null) {
+                    for (File jar : jars) {
+                        if (classpath.length() > 0) {
+                            classpath.append(System.getProperty("path.separator"));
+                        }
+                        classpath.append(jar.getCanonicalPath());
+                    }
+                }
+                return classpath;
+            }
+        });
+    }
+
+    public void stopInstance(final String name) {
+        execute(new Task<Object>() {
+            public Object call(State state) throws IOException {
+                InstanceState instance = state.instances.get(name);
+                if (instance == null) {
+                    throw new IllegalArgumentException("Instance " + name + " not found");
+                }
+                checkPid(instance);
+                if (instance.pid == 0) {
+                    throw new IllegalStateException("Instance already stopped");
+                }
+                cleanShutdown(instance);
+                if (instance.pid > 0) {
+                    Process process = new ProcessBuilderFactoryImpl().newBuilder().attach(instance.pid);
+                    process.destroy();
+                }
+                return null;
+            }
+        });
+    }
+
+    public void destroyInstance(final String name) {
+        execute(new Task<Object>() {
+            public Object call(State state) throws IOException {
+                InstanceState instance = state.instances.get(name);
+                if (instance == null) {
+                    throw new IllegalArgumentException("Instance " + name + " not found");
+                }
+                checkPid(instance);
+                if (instance.pid != 0) {
+                    throw new IllegalStateException("Instance not stopped");
+                }
+                deleteFile(new File(instance.loc));
+                state.instances.remove(name);
+                InstanceServiceImpl.this.proxies.remove(name);
+                return null;
+            }
+        });
+    }
+
+    public void renameInstance(final String oldName, final String newName, final boolean printOutput) throws Exception {
+        execute(new Task<Object>() {
+            public Object call(State state) throws IOException {
+                if (state.instances.get(newName) != null) {
+                    throw new IllegalArgumentException("Instance " + newName + " already exists");
+                }
+                InstanceState instance = state.instances.get(oldName);
+                if (instance == null) {
+                    throw new IllegalArgumentException("Instance " + oldName + " not found");
+                }
+                if (instance.root) {
+                    throw new IllegalArgumentException("Root instance cannot be renamed");
+                }
+                checkPid(instance);
+                if (instance.pid != 0) {
+                    throw new IllegalStateException("Instance not stopped");
+                }
+
+                println(Ansi.ansi().a("Renaming instance ")
+                        .a(Ansi.Attribute.INTENSITY_BOLD).a(oldName).a(Ansi.Attribute.RESET)
+                        .a(" to ")
+                        .a(Ansi.Attribute.INTENSITY_BOLD).a(newName).a(Ansi.Attribute.RESET).toString());
+                // rename directory
+                String oldLocationPath = instance.loc;
+                File oldLocation = new File(oldLocationPath);
+                String basedir = oldLocation.getParent();
+                File newLocation = new File(basedir, newName);
+                oldLocation.renameTo(newLocation);
+                // create the properties map including the instance name and instance location
+                // TODO: replacing is bad, we should re-extract the needed files
+                HashMap<String, String> props = new HashMap<String, String>();
+                props.put(oldName, newName);
+                props.put(oldLocationPath, newLocation.getPath());
+                // replace all references to the "old" name by the new one in etc/system.properties
+                // NB: it's replacement to avoid to override the user's changes
+                filterResource(newLocation, "etc/system.properties", props);
+                // replace all references to the "old" name by the new one in bin/karaf
+                filterResource(newLocation, "bin/karaf", props);
+                filterResource(newLocation, "bin/start", props);
+                filterResource(newLocation, "bin/stop", props);
+                filterResource(newLocation, "bin/karaf.bat", props);
+                filterResource(newLocation, "bin/start.bat", props);
+                filterResource(newLocation, "bin/stop.bat", props);
+                // update instance
+                instance.name = newName;
+                instance.loc = newLocation.getPath();
+                state.instances.put(newName, instance);
+                state.instances.remove(oldName);
+                InstanceImpl proxy = InstanceServiceImpl.this.proxies.remove(oldName);
+                if (proxy == null) {
+                    proxy = new InstanceImpl(InstanceServiceImpl.this, newName);
+                } else {
+                    proxy.doSetName(newName);
+                }
+                InstanceServiceImpl.this.proxies.put(newName, proxy);
+                return null;
+            }
+        });
+    }
+
+    public synchronized Instance cloneInstance(final String name, final String cloneName, final InstanceSettings settings, final boolean printOutput) throws Exception {
+        final int instanceSshPort = getInstanceSshPort(name);
+        final int instanceRmiRegistryPort = getInstanceRmiRegistryPort(name);
+        final int instanceRmiServerPort = getInstanceRmiServerPort(name);
+
+        return execute(new Task<Instance>() {
+            public Instance call(State state) throws IOException {
+                if (state.instances.get(cloneName) != null) {
+                    throw new IllegalArgumentException("Instance " + cloneName + " already exists");
+                }
+                InstanceState instance = state.instances.get(name);
+                if (instance == null) {
+                    throw new IllegalArgumentException("Instance " + name + " not found");
+                }
+
+                // define the clone instance location
+                String cloneLocationPath = settings.getLocation() != null ? settings.getLocation() : cloneName;
+                File cloneLocation = new File(cloneLocationPath);
+                if (!cloneLocation.isAbsolute()) {
+                    cloneLocation = new File(storageLocation, cloneLocationPath);
+                }
+                // copy instance directory
+                String locationPath = instance.loc;
+                File location = new File(locationPath);
+                copy(location, cloneLocation);
+                // create the properties map including the instance name, location, ssh and rmi port numbers
+                // TODO: replacing stuff anywhere is not really good, we might end up replacing unwanted stuff
+                // TODO: if no ports are overriden, shouldn't we choose new ports ?
+                HashMap<String, String> props = new HashMap<String, String>();
+                props.put(name, cloneName);
+                props.put(locationPath, cloneLocationPath);
+                if (settings.getSshPort() > 0)
+                    props.put(Integer.toString(instanceSshPort), Integer.toString(settings.getSshPort()));
+                if (settings.getRmiRegistryPort() > 0)
+                    props.put(Integer.toString(instanceRmiRegistryPort), Integer.toString(settings.getRmiRegistryPort()));
+                if (settings.getRmiServerPort() > 0)
+                    props.put(Integer.toString(instanceRmiServerPort), Integer.toString(settings.getRmiServerPort()));
+
+                // filtering clone files
+                filterResource(cloneLocation, "etc/custom.properties", props);
+                filterResource(cloneLocation, "etc/org.apache.karaf.management.cfg", props);
+                filterResource(cloneLocation, "etc/org.apache.karaf.shell.cfg", props);
+                filterResource(cloneLocation, "etc/system.properties", props);
+                filterResource(cloneLocation, "bin/karaf", props);
+                filterResource(cloneLocation, "bin/start", props);
+                filterResource(cloneLocation, "bin/stop", props);
+                filterResource(cloneLocation, "bin/karaf.bat", props);
+                filterResource(cloneLocation, "bin/start.bat", props);
+                filterResource(cloneLocation, "bin/stop.bat", props);
+                // create and add the clone instance in the registry
+                String javaOpts = settings.getJavaOpts();
+                if (javaOpts == null || javaOpts.length() == 0) {
+                    javaOpts = DEFAULT_JAVA_OPTS;
+                }
+                InstanceState is = new InstanceState();
+                is.name = cloneName;
+                is.loc = cloneLocation.toString();
+                is.opts = javaOpts;
+                state.instances.put(cloneName, is);
+                InstanceImpl cloneInstance = new InstanceImpl(InstanceServiceImpl.this, cloneName);
+                InstanceServiceImpl.this.proxies.put(cloneName, cloneInstance);
+                return cloneInstance;
+            }
+        });
+    }
+
+    private void checkPid(InstanceState instance) throws IOException {
+        if (instance.pid != 0) {
+            Process process = new ProcessBuilderFactoryImpl().newBuilder().attach(instance.pid);
+            if (!process.isRunning()) {
+                instance.pid = 0;
+            }
+        }
+    }
+
+    protected void cleanShutdown(InstanceState instance) {
+        try {
+            File file = new File(new File(instance.loc, "etc"), CONFIG_PROPERTIES_FILE_NAME);
+            URL configPropURL = file.toURI().toURL();
+            Properties props = loadPropertiesFile(configPropURL);
+            props.put("karaf.base", new File(instance.loc).getCanonicalPath());
+            props.put("karaf.home", System.getProperty("karaf.home"));
+            props.put("karaf.data", new File(new File(instance.loc), "data").getCanonicalPath());
+            props.put("karaf.etc", new File(new File(instance.loc), "etc").getCanonicalPath());
+            for (Enumeration e = props.propertyNames(); e.hasMoreElements();) {
+                String key = (String) e.nextElement();
+                props.setProperty(key,
+                        substVars(props.getProperty(key), key, null, props));
+            }
+            int port = Integer.parseInt(props.getProperty(KARAF_SHUTDOWN_PORT, "0"));
+            String host = props.getProperty(KARAF_SHUTDOWN_HOST, "localhost");
+            String portFile = props.getProperty(KARAF_SHUTDOWN_PORT_FILE);
+            String shutdown = props.getProperty(KARAF_SHUTDOWN_COMMAND, DEFAULT_SHUTDOWN_COMMAND);
+            if (port == 0 && portFile != null) {
+                BufferedReader r = new BufferedReader(new InputStreamReader(new FileInputStream(portFile)));
+                String portStr = r.readLine();
+                port = Integer.parseInt(portStr);
+                r.close();
+            }
+            // We found the port, try to send the command
+            if (port > 0) {
+                Socket s = new Socket(host, port);
+                s.getOutputStream().write(shutdown.getBytes());
+                s.close();
+                long t = System.currentTimeMillis() + getStopTimeout();
+                do {
+                    Thread.sleep(100);
+                    checkPid(instance);
+                } while (System.currentTimeMillis() < t && instance.pid > 0);
+            }
+        } catch (Exception e) {
+            LOGGER.debug("Unable to cleanly shutdown instance " + instance.name, e);
+        }
+    }
+
+    int getInstanceSshPort(String name) {
+        return getKarafPort(name, "etc/org.apache.karaf.shell.cfg", "sshPort");
+    }
+
+    void changeInstanceSshPort(String name, final int port) throws Exception {
+        setKarafPort(name, "etc/org.apache.karaf.shell.cfg", "sshPort", port);
+    }
+
+    int getInstanceRmiRegistryPort(String name) {
+        return getKarafPort(name, "etc/org.apache.karaf.management.cfg", "rmiRegistryPort");
+    }
+
+    void changeInstanceRmiRegistryPort(String name, final int port) throws Exception {
+        setKarafPort(name, "etc/org.apache.karaf.management.cfg", "rmiRegistryPort", port);
+    }
+
+    int getInstanceRmiServerPort(String name) {
+        return getKarafPort(name, "etc/org.apache.karaf.management.cfg", "rmiServerPort");
+    }
+
+    void changeInstanceRmiServerPort(String name, int port) throws Exception {
+        setKarafPort(name, "etc/org.apache.karaf.management.cfg", "rmiServerPort", port);
+    }
+
+    private int getKarafPort(final String name, final String path, final String key) {
+        return execute(new Task<Integer>() {
+            public Integer call(State state) throws IOException {
+                return InstanceServiceImpl.this.getKarafPort(state, name, path, key);
+            }
+        });
+    }
+
+    private Integer getKarafPort(State state, String name, String path, final String key) {
+        InstanceState instance = state.instances.get(name);
+        if (instance == null) {
+            throw new IllegalArgumentException("Instance " + name + " not found");
+        }
+        File f = new File(instance.loc, path);
+        try {
+            return FileLockUtils.execute(f, new FileLockUtils.CallableWithProperties<Integer>() {
+                public Integer call(org.apache.felix.utils.properties.Properties properties) throws IOException {
+                    return Integer.parseInt(properties.get(key).toString());
+                }
+            });
+        } catch (IOException e) {
+            return 0;
+        }
+    }
+
+    private void setKarafPort(final String name, final String path, final String key, final int port) throws IOException {
+        execute(new Task<Object>() {
+            public Object call(State state) throws IOException {
+                InstanceState instance = state.instances.get(name);
+                if (instance == null) {
+                    throw new IllegalArgumentException("Instance " + name + " not found");
+                }
+                checkPid(instance);
+                if (instance.pid != 0) {
+                    throw new IllegalStateException("Instance is not stopped");
+                }
+                File f = new File(instance.loc, path);
+                FileLockUtils.execute(f, new FileLockUtils.RunnableWithProperties() {
+                    public void run(org.apache.felix.utils.properties.Properties properties) throws IOException {
+                        properties.put(key, Integer.toString(port));
+                    }
+                });
+                return null;
+            }
+        });
+    }
+
+    boolean isInstanceRoot(final String name) {
+        return execute(new Task<Boolean>() {
+            public Boolean call(State state) throws IOException {
+                InstanceState instance = state.instances.get(name);
+                if (instance == null) {
+                    throw new IllegalArgumentException("Instance " + name + " not found");
+                }
+                return instance.root;
+            }
+        });
+    }
+
+    String getInstanceLocation(final String name) {
+        return execute(new Task<String>() {
+            public String call(State state) throws IOException {
+                InstanceState instance = state.instances.get(name);
+                if (instance == null) {
+                    throw new IllegalArgumentException("Instance " + name + " not found");
+                }
+                return instance.loc;
+            }
+        });
+    }
+
+    int getInstancePid(final String name) {
+        return execute(new Task<Integer>() {
+            public Integer call(State state) throws IOException {
+                InstanceState instance = state.instances.get(name);
+                if (instance == null) {
+                    throw new IllegalArgumentException("Instance " + name + " not found");
+                }
+                checkPid(instance);
+                return instance.pid;
+            }
+        });
+    }
+
+    String getInstanceJavaOpts(final String name) {
+        return execute(new Task<String>() {
+            public String call(State state) throws IOException {
+                InstanceState instance = state.instances.get(name);
+                if (instance == null) {
+                    throw new IllegalArgumentException("Instance " + name + " not found");
+                }
+                return instance.opts;
+            }
+        });
+    }
+
+    void changeInstanceJavaOpts(final String name, final String opts) {
+        execute(new Task<String>() {
+            public String call(State state) throws IOException {
+                InstanceState instance = state.instances.get(name);
+                if (instance == null) {
+                    throw new IllegalArgumentException("Instance " + name + " not found");
+                }
+                instance.opts = opts;
+                return null;
+            }
+        });
+    }
+
+    String getInstanceState(final String name) {
+        return execute(new Task<String>() {
+            public String call(State state) throws IOException {
+                InstanceState instance = state.instances.get(name);
+                if (instance == null) {
+                    throw new IllegalArgumentException("Instance " + name + " not found");
+                }
+                int port = getKarafPort(state, name, "etc/org.apache.karaf.shell.cfg", "sshPort");
+                if (!new File(instance.loc).isDirectory() || port <= 0) {
+                    return Instance.ERROR;
+                }
+                checkPid(instance);
+                if (instance.pid == 0) {
+                    return Instance.STOPPED;
+                } else {
+                    try {
+                        Socket s = new Socket("localhost", port);
+                        s.close();
+                        return Instance.STARTED;
+                    } catch (Exception e) {
+                        // ignore
+                    }
+                    return Instance.STARTING;
+                }
+            }
+        });
+    }
+
+    private boolean deleteFile(File fileToDelete) {
+        if (fileToDelete == null || !fileToDelete.exists()) {
+            return true;
+        }
+        boolean result = true;
+        if (fileToDelete.isDirectory()) {
+            File[] files = fileToDelete.listFiles();
+            if (files == null) {
+                result = false;
+            } else {
+                for (int i = 0; i < files.length; i++) {
+                    File file = files[i];
+                    if (file.getName().equals(".") || file.getName().equals("..")) {
+                        continue;
+                    }
+                    if (file.isDirectory()) {
+                        result &= deleteFile(file);
+                    } else {
+                        result &= file.delete();
+                    }
+                }
+            }
+        }
+        result &= fileToDelete.delete();
+        return result;
+    }
+
+    private void copyResourceToDir(File target, String resource, boolean printOutput) throws IOException {
+        File outFile = new File(target, resource);
+        if( !outFile.exists() ) {
+            logInfo("Creating file: %s", printOutput, outFile.getPath());
+            InputStream is = getClass().getClassLoader().getResourceAsStream("org/apache/karaf/instance/resources/" + resource);
+            try {
+                // Read it line at a time so that we can use the platform line ending when we write it out.
+                PrintStream out = new PrintStream(new FileOutputStream(outFile));
+                try {
+                    Scanner scanner = new Scanner(is);
+                    while (scanner.hasNextLine() ) {
+                        String line = scanner.nextLine();
+                        out.println(line);
+                    }
+                } finally {
+                    safeClose(out);
+                }
+            } finally {
+                safeClose(is);
+            }
+        }
+    }
+
+    private void println(String st) {
+        System.out.println(st);
+    }
+
+    protected static Properties loadPropertiesFile(URL configPropURL) throws Exception {
+        // Read the properties file.
+        Properties configProps = new Properties();
+        InputStream is = null;
+        try {
+            is = configPropURL.openConnection().getInputStream();
+            configProps.load(is);
+            is.close();
+        }
+        catch (Exception ex) {
+            System.err.println(
+                    "Error loading config properties from " + configPropURL);
+            System.err.println("Main: " + ex);
+            try {
+                if (is != null) is.close();
+            }
+            catch (IOException ex2) {
+                // Nothing we can do.
+            }
+            return null;
+        }
+        return configProps;
+    }
+
+    private void filterResource(File basedir, String path, HashMap<String, String> props) throws IOException {
+        File file = new File(basedir, path);
+        File bak = new File(basedir, path + BACKUP_EXTENSION);
+        if (!file.exists()) {
+            return;
+        }
+        // rename the file to the backup one
+        file.renameTo(bak);
+        // copy and filter the bak file back to the original name
+        copyAndFilterResource(new FileInputStream(bak), new FileOutputStream(file), props);
+        // remove the bak file
+        bak.delete();
+    }
+
+    private void copyFilteredResourceToDir(File target, String resource, HashMap<String, String> props, boolean printOutput) throws IOException {
+        File outFile = new File(target, resource);
+        if( !outFile.exists() ) {
+            logInfo("Creating file: %s", printOutput, outFile.getPath());
+            InputStream is = getClass().getClassLoader().getResourceAsStream("org/apache/karaf/instance/resources/" + resource);
+            copyAndFilterResource(is, new FileOutputStream(outFile), props);
+        }
+    }
+
+    private void copyAndFilterResource(InputStream source, OutputStream target, HashMap<String, String> props) throws IOException {
+        try {
+            // read it line at a time so that we can use the platform line ending when we write it out.
+            PrintStream out = new PrintStream(target);
+            try {
+                Scanner scanner = new Scanner(source);
+                while (scanner.hasNextLine()) {
+                    String line = scanner.nextLine();
+                    line = filter(line, props);
+                    out.println(line);
+                }
+            } finally {
+                safeClose(out);
+            }
+        } finally {
+            safeClose(source);
+        }
+    }
+
+    private void safeClose(InputStream is) throws IOException {
+        if (is == null) {
+            return;
+        }
+        try {
+            is.close();
+        } catch (Throwable ignore) {
+        }
+    }
+
+    private void safeClose(OutputStream is) throws IOException {
+        if (is == null) {
+            return;
+        }
+        try {
+            is.close();
+        } catch (Throwable ignore) {
+        }
+    }
+
+    private String filter(String line, HashMap<String, String> props) {
+        for (Map.Entry<String, String> i : props.entrySet()) {
+            int p1 = line.indexOf(i.getKey());
+            if( p1 >= 0 ) {
+                String l1 = line.substring(0, p1);
+                String l2 = line.substring(p1+i.getKey().length());
+                line = l1+i.getValue()+l2;
+            }
+        }
+        return line;
+    }
+
+    private void mkdir(File karafBase, String path, boolean printOutput) {
+        File file = new File(karafBase, path);
+        if( !file.exists() ) {
+            logInfo("Creating dir: %s", printOutput, file.getPath());
+            file.mkdirs();
+        }
+    }
+
+    private int chmod(File serviceFile, String mode) throws IOException {
+        java.lang.ProcessBuilder builder = new java.lang.ProcessBuilder();
+        builder.command("chmod", mode, serviceFile.getCanonicalPath());
+        java.lang.Process p = builder.start();
+
+        // gnodet: Fix SMX4KNL-46: cpu goes to 100% after running the 'admin create' command
+        // Not sure exactly what happens, but commenting the process io redirection seems
+        // to work around the problem.
+        //
+        //PumpStreamHandler handler = new PumpStreamHandler(io.inputStream, io.outputStream, io.errorStream);
+        //handler.attach(p);
+        //handler.start();
+        try {
+            return p.waitFor();
+        } catch (InterruptedException e) {
+            throw (IOException) new InterruptedIOException().initCause(e);
+        }
+        //handler.stop();
+    }
+
+    private void copy(File source, File destination) throws IOException {
+        if (source.getName().equals("cache.lock")) {
+            // ignore cache.lock file
+            return;
+        }
+        if (source.getName().equals("lock")) {
+            // ignore lock file
+            return;
+        }
+        if (source.getName().matches("transaction_\\d+\\.log")) {
+            // ignore active txlog files
+            return;
+        }
+        if (source.isDirectory()) {
+            if (!destination.exists()) {
+                destination.mkdirs();
+            }
+            String[] children = source.list();
+            for (String child : children) {
+                if (!child.contains("instances") && !child.contains("lib"))
+                    copy(new File(source, child), new File(destination, child));
+            }
+        } else {
+            InputStream in = new FileInputStream(source);
+            OutputStream out = new FileOutputStream(destination);
+            byte[] buffer = new byte[1024];
+            int length;
+            while ((length = in.read(buffer)) > 0) {
+                out.write(buffer, 0, length);
+            }
+            in.close();
+            out.close();
+        }
+    }
+
+    private static final String DELIM_START = "${";
+    private static final String DELIM_STOP = "}";
+
+    protected static String substVars(String val, String currentKey,
+                                      Map<String, String> cycleMap, Properties configProps)
+            throws IllegalArgumentException {
+        // If there is currently no cycle map, then create
+        // one for detecting cycles for this invocation.
+        if (cycleMap == null) {
+            cycleMap = new HashMap<String, String>();
+        }
+
+        // Put the current key in the cycle map.
+        cycleMap.put(currentKey, currentKey);
+
+        // Assume we have a value that is something like:
+        // "leading ${foo.${bar}} middle ${baz} trailing"
+
+        // Find the first ending '}' variable delimiter, which
+        // will correspond to the first deepest nested variable
+        // placeholder.
+        int stopDelim = val.indexOf(DELIM_STOP);
+
+        // Find the matching starting "${" variable delimiter
+        // by looping until we find a start delimiter that is
+        // greater than the stop delimiter we have found.
+        int startDelim = val.indexOf(DELIM_START);
+        while (stopDelim >= 0) {
+            int idx = val.indexOf(DELIM_START, startDelim + DELIM_START.length());
+            if ((idx < 0) || (idx > stopDelim)) {
+                break;
+            } else if (idx < stopDelim) {
+                startDelim = idx;
+            }
+        }
+
+        // If we do not have a start or stop delimiter, then just
+        // return the existing value.
+        if ((startDelim < 0) && (stopDelim < 0)) {
+            return val;
+        }
+        // At this point, we found a stop delimiter without a start,
+        // so throw an exception.
+        else if (((startDelim < 0) || (startDelim > stopDelim))
+                && (stopDelim >= 0)) {
+            throw new IllegalArgumentException(
+                    "stop delimiter with no start delimiter: "
+                            + val);
+        }
+
+        // At this point, we have found a variable placeholder so
+        // we must perform a variable substitution on it.
+        // Using the start and stop delimiter indices, extract
+        // the first, deepest nested variable placeholder.
+        String variable =
+                val.substring(startDelim + DELIM_START.length(), stopDelim);
+
+        // Verify that this is not a recursive variable reference.
+        if (cycleMap.get(variable) != null) {
+            throw new IllegalArgumentException(
+                    "recursive variable reference: " + variable);
+        }
+
+        // Get the value of the deepest nested variable placeholder.
+        // Try to configuration properties first.
+        String substValue = (configProps != null)
+                ? configProps.getProperty(variable, null)
+                : null;
+        if (substValue == null) {
+            // Ignore unknown property values.
+            substValue = System.getProperty(variable, "");
+        }
+
+        // Remove the found variable from the cycle map, since
+        // it may appear more than once in the value and we don't
+        // want such situations to appear as a recursive reference.
+        cycleMap.remove(variable);
+
+        // Append the leading characters, the substituted value of
+        // the variable, and the trailing characters to get the new
+        // value.
+        val = val.substring(0, startDelim)
+                + substValue
+                + val.substring(stopDelim + DELIM_STOP.length(), val.length());
+
+        // Now perform substitution again, since there could still
+        // be substitutions to make.
+        val = substVars(val, currentKey, cycleMap, configProps);
+
+        // Return the value.
+        return val;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/7c2db062/instance/src/main/java/org/apache/karaf/instance/core/internal/InstanceToTableMapper.java
----------------------------------------------------------------------
diff --git a/instance/src/main/java/org/apache/karaf/instance/core/internal/InstanceToTableMapper.java b/instance/src/main/java/org/apache/karaf/instance/core/internal/InstanceToTableMapper.java
new file mode 100644
index 0000000..baaedaf
--- /dev/null
+++ b/instance/src/main/java/org/apache/karaf/instance/core/internal/InstanceToTableMapper.java
@@ -0,0 +1,83 @@
+/*
+ * 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.karaf.instance.core.internal;
+
+import java.util.List;
+
+import javax.management.openmbean.CompositeDataSupport;
+import javax.management.openmbean.CompositeType;
+import javax.management.openmbean.OpenDataException;
+import javax.management.openmbean.OpenType;
+import javax.management.openmbean.SimpleType;
+import javax.management.openmbean.TabularData;
+import javax.management.openmbean.TabularDataSupport;
+import javax.management.openmbean.TabularType;
+
+import org.apache.karaf.instance.core.Instance;
+import org.apache.karaf.instance.core.InstancesMBean;
+
+public class InstanceToTableMapper {
+    
+    private InstanceToTableMapper() {
+    }
+
+    private static CompositeDataSupport mapInstance(Instance instance, CompositeType comp) throws OpenDataException {
+        String state;
+        try {
+            state = instance.getState();
+        } catch (Exception e) {
+            state = "Error";
+        }
+        Object[] itemValues = new Object[] {instance.getPid(), instance.getName(), instance.isRoot(),
+                                            instance.getSshPort(), instance.getRmiRegistryPort(),
+                                            instance.getRmiServerPort(), state, instance.getLocation(),
+                                            instance.getJavaOpts()};
+        return new CompositeDataSupport(comp, InstancesMBean.INSTANCE, itemValues);
+    }
+
+    private static CompositeType createRowType() throws OpenDataException {
+        String desc = "This type describes Karaf instance";
+        OpenType<?>[] itemTypes = new OpenType[] {SimpleType.INTEGER, SimpleType.STRING, SimpleType.BOOLEAN,
+                                                  SimpleType.INTEGER, SimpleType.INTEGER, SimpleType.INTEGER,
+                                                  SimpleType.STRING, SimpleType.STRING, SimpleType.STRING};
+        String[] descriptions = new String[] {"The Process ID of the instance or 0 if not running",
+                                              "The name of the instance", "Whether the instance is root",
+                                              "The SSH port that can be used to connect to the instance",
+                                              "The RMI registry port that can be used to manage the instance",
+                                              "The RMI server port that can be used to manage the instance",
+                                              "The state of the instance", "The location of the instance",
+                                              "The Java options of the instance"};
+        CompositeType comp = new CompositeType("Instances", desc, InstancesMBean.INSTANCE, descriptions, itemTypes);
+        return comp;
+    }
+
+    public static TabularData tableFrom(List<Instance> instances) {
+        try {
+            CompositeType rowType = createRowType();
+            TabularType tableType = new TabularType("Instances", "Table of all Karaf instances", rowType,
+                                                    new String[] {InstancesMBean.INSTANCE_NAME});
+            TabularDataSupport table = new TabularDataSupport(tableType);
+            for (Instance instance : instances) {
+                CompositeDataSupport row = mapInstance(instance, rowType);
+                table.put(row);
+            }
+            return table;
+        } catch (OpenDataException e) {
+            throw new IllegalStateException("Error building instance table", e);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/7c2db062/instance/src/main/java/org/apache/karaf/instance/core/internal/InstancesMBeanImpl.java
----------------------------------------------------------------------
diff --git a/instance/src/main/java/org/apache/karaf/instance/core/internal/InstancesMBeanImpl.java b/instance/src/main/java/org/apache/karaf/instance/core/internal/InstancesMBeanImpl.java
new file mode 100644
index 0000000..b95e4dc
--- /dev/null
+++ b/instance/src/main/java/org/apache/karaf/instance/core/internal/InstancesMBeanImpl.java
@@ -0,0 +1,224 @@
+/*
+ * 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.karaf.instance.core.internal;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import javax.management.MBeanException;
+import javax.management.NotCompliantMBeanException;
+import javax.management.StandardMBean;
+import javax.management.openmbean.TabularData;
+
+import org.apache.karaf.instance.core.Instance;
+import org.apache.karaf.instance.core.InstanceSettings;
+import org.apache.karaf.instance.core.InstancesMBean;
+
+public class InstancesMBeanImpl extends StandardMBean implements InstancesMBean {
+
+    static final String DEBUG_OPTS = " -Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005";
+    static final String DEFAULT_OPTS = "-server -Xmx512M -Dcom.sun.management.jmxremote";
+
+    private org.apache.karaf.instance.core.InstanceService instanceService;
+
+    public InstancesMBeanImpl(org.apache.karaf.instance.core.InstanceService instanceService) throws NotCompliantMBeanException {
+        super(InstancesMBean.class);
+        this.instanceService = instanceService;
+    }
+
+    public int createInstance(String name, int sshPort, int rmiRegistryPort, int rmiServerPort, String location, String javaOpts, String features, String featureURLs)
+            throws MBeanException {
+        try {
+            if ("".equals(location)) {
+                location = null;
+            }
+            if ("".equals(javaOpts)) {
+                javaOpts = null;
+            }
+
+            InstanceSettings settings = new InstanceSettings(sshPort, rmiRegistryPort, rmiServerPort, location, javaOpts,
+                    parseStringList(featureURLs), parseStringList(features));
+
+            Instance inst = instanceService.createInstance(name, settings, false);
+            if (inst != null) {
+                return inst.getPid();
+            } else {
+                return -1;
+            }
+        } catch (Exception e) {
+            throw new MBeanException(null, e.getMessage());
+        }
+    }
+
+    public void changeSshPort(String name, int port) throws MBeanException {
+        try {
+            getExistingInstance(name).changeSshPort(port);
+        } catch (Exception e) {
+            throw new MBeanException(null, e.getMessage());
+        }
+    }
+
+    public void changeRmiRegistryPort(String name, int port) throws MBeanException {
+        try {
+            getExistingInstance(name).changeRmiRegistryPort(port);
+        } catch (Exception e) {
+            throw new MBeanException(null, e.getMessage());
+        }
+    }
+
+    public void changeRmiServerPort(String name, int port) throws MBeanException {
+        try {
+            getExistingInstance(name).changeRmiServerPort(port);
+        } catch (Exception e) {
+            throw new MBeanException(null, e.getMessage());
+        }
+    }
+
+    public void changeJavaOpts(String name, String javaOpts) throws MBeanException {
+        try {
+            getExistingInstance(name).changeJavaOpts(javaOpts);
+        } catch (Exception e) {
+            throw new MBeanException(null, e.getMessage());
+        }
+    }
+
+    public void destroyInstance(String name) throws MBeanException {
+        try {
+            getExistingInstance(name).destroy();
+        } catch (Exception e) {
+            throw new MBeanException(null, e.getMessage());
+        }
+    }
+
+    public void startInstance(String name) throws MBeanException {
+        try {
+            getExistingInstance(name).start(null);
+        } catch (Exception e) {
+            throw new MBeanException(null, e.getMessage());
+        }
+    }
+
+    public void startInstance(String name, String opts) throws MBeanException {
+        try {
+            getExistingInstance(name).start(opts);
+        } catch (Exception e) {
+            throw new MBeanException(null, e.getMessage());
+        }
+    }
+
+    public void startInstance(String name, String opts, boolean wait, boolean debug) throws MBeanException {
+        try {
+            Instance child = getExistingInstance(name);
+            String options = opts;
+            if (options == null) {
+                options = child.getJavaOpts();
+            }
+            if (options == null) {
+                options = DEFAULT_OPTS;
+            }
+            if (debug) {
+                options += DEBUG_OPTS;
+            }
+            if (wait) {
+                String state = child.getState();
+                if (Instance.STOPPED.equals(state)) {
+                    child.start(opts);
+                }
+                if (!Instance.STARTED.equals(state)) {
+                    do {
+                        Thread.sleep(500);
+                        state = child.getState();
+                    } while (Instance.STARTING.equals(state));
+                }
+            } else {
+                child.start(opts);
+            }
+        } catch (Exception e) {
+            throw new MBeanException(null, e.getMessage());
+        }
+    }
+
+    public void stopInstance(String name) throws MBeanException {
+        try {
+            getExistingInstance(name).stop();
+        } catch (Exception e) {
+            throw new MBeanException(null, e.getMessage());
+        }
+    }
+
+    public void renameInstance(String originalName, String newName) throws MBeanException {
+        try {
+            instanceService.renameInstance(originalName, newName, false);
+        } catch (Exception e) {
+            throw new MBeanException(null, e.getMessage());
+        }
+    }
+
+    public void renameInstance(String originalName, String newName, boolean verbose) throws MBeanException {
+        try {
+            instanceService.renameInstance(originalName, newName, verbose);
+        } catch (Exception e) {
+            throw new MBeanException(null, e.getMessage());
+        }
+    }
+
+    public void cloneInstance(String name, String cloneName, int sshPort, int rmiRegistryPort, int rmiServerPort, String location, String javaOpts) throws MBeanException {
+        try {
+            if ("".equals(location)) {
+                location = null;
+            }
+            if ("".equals(javaOpts)) {
+                javaOpts = null;
+            }
+
+            InstanceSettings settings = new InstanceSettings(sshPort, rmiRegistryPort, rmiServerPort, location, javaOpts, null, null);
+
+            instanceService.cloneInstance(name, cloneName, settings, false);
+        } catch (Exception e) {
+            throw new MBeanException(null, e.getMessage());
+        }
+    }
+
+    public TabularData getInstances() throws MBeanException {
+        List<Instance> instances = Arrays.asList(instanceService.getInstances());
+        TabularData table = InstanceToTableMapper.tableFrom(instances);
+        return table;
+    }
+
+    private Instance getExistingInstance(String name) {
+        Instance i = instanceService.getInstance(name);
+        if (i == null) {
+            throw new IllegalArgumentException("Instance '" + name + "' does not exist");
+        }
+        return i;
+    }
+
+    private List<String> parseStringList(String value) {
+        List<String> list = new ArrayList<String>();
+        if (value != null) {
+            for (String el : value.split(",")) {
+                String trimmed = el.trim();
+                if (trimmed.length() == 0) {
+                    continue;
+                }
+                list.add(trimmed);
+            }
+        }
+        return list;
+    }
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/7c2db062/instance/src/main/java/org/apache/karaf/instance/core/internal/osgi/Activator.java
----------------------------------------------------------------------
diff --git a/instance/src/main/java/org/apache/karaf/instance/core/internal/osgi/Activator.java b/instance/src/main/java/org/apache/karaf/instance/core/internal/osgi/Activator.java
new file mode 100644
index 0000000..a50db46
--- /dev/null
+++ b/instance/src/main/java/org/apache/karaf/instance/core/internal/osgi/Activator.java
@@ -0,0 +1,35 @@
+/*
+ * 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.karaf.instance.core.internal.osgi;
+
+import org.apache.karaf.instance.core.InstanceService;
+import org.apache.karaf.instance.core.internal.InstanceServiceImpl;
+import org.apache.karaf.instance.core.internal.InstancesMBeanImpl;
+import org.apache.karaf.util.tracker.BaseActivator;
+
+public class Activator extends BaseActivator {
+
+    @Override
+    protected void doStart() throws Exception {
+        InstanceService instanceService = new InstanceServiceImpl();
+        register(InstanceService.class, instanceService);
+
+        InstancesMBeanImpl mbean = new InstancesMBeanImpl(instanceService);
+        registerMBean(mbean, "type=instance");
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/7c2db062/instance/src/main/java/org/apache/karaf/instance/main/Execute.java
----------------------------------------------------------------------
diff --git a/instance/src/main/java/org/apache/karaf/instance/main/Execute.java b/instance/src/main/java/org/apache/karaf/instance/main/Execute.java
new file mode 100644
index 0000000..591873e
--- /dev/null
+++ b/instance/src/main/java/org/apache/karaf/instance/main/Execute.java
@@ -0,0 +1,171 @@
+/*
+ * 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.karaf.instance.main;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+
+import org.apache.karaf.instance.command.ChangeOptsCommand;
+import org.apache.karaf.instance.command.ChangeRmiRegistryPortCommand;
+import org.apache.karaf.instance.command.ChangeRmiServerPortCommand;
+import org.apache.karaf.instance.command.ChangeSshPortCommand;
+import org.apache.karaf.instance.command.CloneCommand;
+import org.apache.karaf.instance.command.CreateCommand;
+import org.apache.karaf.instance.command.DestroyCommand;
+import org.apache.karaf.instance.command.InstanceCommandSupport;
+import org.apache.karaf.instance.command.ListCommand;
+import org.apache.karaf.instance.command.RenameCommand;
+import org.apache.karaf.instance.command.StartCommand;
+import org.apache.karaf.instance.command.StatusCommand;
+import org.apache.karaf.instance.command.StopCommand;
+import org.apache.karaf.instance.core.internal.InstanceServiceImpl;
+import org.apache.karaf.shell.api.action.Action;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.impl.action.command.DefaultActionPreparator;
+import org.fusesource.jansi.AnsiConsole;
+
+public class Execute {
+    static Class<? extends Action> x = CreateCommand.class;
+    private static final Class<?>[] COMMAND_CLASSES = new Class[]{
+            ChangeOptsCommand.class,
+            ChangeRmiRegistryPortCommand.class,
+            ChangeRmiServerPortCommand.class,
+            ChangeSshPortCommand.class,
+            CloneCommand.class,
+            CreateCommand.class,
+            DestroyCommand.class,
+            ListCommand.class,
+            RenameCommand.class,
+            StartCommand.class,
+            StatusCommand.class,
+            StopCommand.class};
+    private static final Map<String, Class<?>> COMMANDS = new TreeMap<String, Class<?>>();
+
+    static {
+        for (Class<?> c : COMMAND_CLASSES) {
+            Command ann = c.getAnnotation(Command.class);
+            if (ann == null) {
+                continue;
+            }
+            COMMANDS.put(ann.name(), c);
+        }
+    }
+
+    // For testing
+    static boolean exitAllowed = true;
+
+    /**
+     * Environment variable for specifying extra options to the Karaf instance
+     * process kicked off from this Java process.
+     */
+    private static final String ENV_KARAF_OPTS = "KARAF_OPTS";
+
+    /**
+     * System property for specifying extra options to the Karaf instance
+     * process kicked off from this Java process.
+     */
+    private static final String PROP_KARAF_OPTS = "karaf.opts";
+
+    public static void main(String[] args) throws Exception {
+        AnsiConsole.systemInstall();
+
+        if (args.length == 0) {
+            listCommands();
+            exit(0);
+        }
+        String commandName = args[0];
+        Class<?> cls = COMMANDS.get(commandName);
+        if (cls == null) {
+            System.err.println("Command not found: " + commandName);
+            exit(-1);
+        }
+
+        String storage = System.getProperty("karaf.instances");
+        if (storage == null) {
+            System.err.println("System property 'karaf.instances' is not set. \n" +
+                    "This property needs to be set to the full path of the instance.properties file.");
+            exit(-2);
+        }
+        File storageFile = new File(storage);
+        System.setProperty("user.dir", storageFile.getParentFile().getParentFile().getCanonicalPath());
+
+        try {
+            String karafOpts = System.getenv(ENV_KARAF_OPTS);
+            if (karafOpts != null) {
+                System.setProperty(PROP_KARAF_OPTS, karafOpts);
+            }
+        } catch (Exception e) {
+            System.err.println("Could not read KARAF_OPTS environment variable: " + e.getMessage());
+            if (System.getProperty("karaf.showStackTrace") != null) {
+                throw e;
+            }
+        }
+
+        Object command = cls.newInstance();
+        if (command instanceof InstanceCommandSupport) {
+            try {
+                execute((InstanceCommandSupport) command, storageFile, args);
+            } catch (Exception e) {
+                System.err.println("Error execution command '" + commandName + "': " + e.getMessage());
+                if (System.getProperty("karaf.showStackTrace") != null) {
+                    throw e;
+                }
+            }
+        } else {
+            System.err.println("Not an instance command: " + commandName);
+            exit(-3);
+        }
+    }
+
+    static void execute(InstanceCommandSupport command, File storageFile, String[] args) throws Exception {
+        DefaultActionPreparator dap = new DefaultActionPreparator();
+        List<Object> params = new ArrayList<Object>(Arrays.asList(args));
+        params.remove(0); // this is the actual command name
+
+        if (!dap.prepare(command, null, params)) {
+            return;
+        }
+
+        InstanceServiceImpl instanceService = new InstanceServiceImpl();
+        instanceService.setStorageLocation(storageFile);
+        command.setInstanceService(instanceService);
+        command.execute();
+    }
+
+    private static void listCommands() {
+        System.out.println("Available commands:");
+        for (Map.Entry<String, Class<?>> entry : COMMANDS.entrySet()) {
+            Command ann = entry.getValue().getAnnotation(Command.class);
+            System.out.printf("  %s - %s\n", entry.getKey(), ann.description());
+        }
+
+        System.out.println("Type 'command --help' for more help on the specified command.");
+    }
+
+    private static void exit(int rc) {
+        if (exitAllowed) {
+            System.exit(rc);
+        } else {
+            throw new RuntimeException("" + rc);
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/7c2db062/instance/src/main/java/org/apache/karaf/jpm/Process.java
----------------------------------------------------------------------
diff --git a/instance/src/main/java/org/apache/karaf/jpm/Process.java b/instance/src/main/java/org/apache/karaf/jpm/Process.java
new file mode 100644
index 0000000..2bd3b36
--- /dev/null
+++ b/instance/src/main/java/org/apache/karaf/jpm/Process.java
@@ -0,0 +1,47 @@
+/*
+ * 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.karaf.jpm;
+
+import java.io.IOException;
+import java.io.Serializable;
+
+/**
+ * Interface representing a process
+ */
+public interface Process extends Serializable {
+
+    /**
+     * Retrieves the PID of the process
+     * @return the pid
+     */
+    int getPid();
+
+    /**
+     * Check if this process is still running
+     * @return <code>true</code> if the process is running
+     * @throws IOException if an error occurs
+     */
+    boolean isRunning() throws IOException;
+
+    /**
+     * Destroy the process.
+     *
+     * @throws IOException
+     */
+    void destroy() throws IOException;
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/7c2db062/instance/src/main/java/org/apache/karaf/jpm/ProcessBuilder.java
----------------------------------------------------------------------
diff --git a/instance/src/main/java/org/apache/karaf/jpm/ProcessBuilder.java b/instance/src/main/java/org/apache/karaf/jpm/ProcessBuilder.java
new file mode 100644
index 0000000..2b6c612
--- /dev/null
+++ b/instance/src/main/java/org/apache/karaf/jpm/ProcessBuilder.java
@@ -0,0 +1,59 @@
+/*
+ * 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.karaf.jpm;
+
+import java.io.File;
+import java.io.IOException;
+
+/**
+ * Interface used to create new processes.
+ */
+public interface ProcessBuilder {
+
+    /**
+     * Specified the current directory to run the command from
+     *
+     * @param dir the directory to run the command from
+     * @return the ProcessBuilder instance
+     */
+    ProcessBuilder directory(File dir);
+
+    /**
+     * Set the command to execute
+     *
+     * @param command the command to execute
+     * @return the ProcessBuilder instance
+     */
+    ProcessBuilder command(String command);
+
+    /**
+     * Create and start the process
+     *
+     * @return the process that has been started
+     * @throws IOException if the process can not be created
+     */
+    org.apache.karaf.jpm.Process start() throws IOException;
+
+    /**
+     * Attach to an existing process
+     *
+     * @return the process that has been attached
+     * @throws IOException if the process can not be attached to
+     */
+    org.apache.karaf.jpm.Process attach(int pid) throws IOException;
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/7c2db062/instance/src/main/java/org/apache/karaf/jpm/ProcessBuilderFactory.java
----------------------------------------------------------------------
diff --git a/instance/src/main/java/org/apache/karaf/jpm/ProcessBuilderFactory.java b/instance/src/main/java/org/apache/karaf/jpm/ProcessBuilderFactory.java
new file mode 100644
index 0000000..baa563b
--- /dev/null
+++ b/instance/src/main/java/org/apache/karaf/jpm/ProcessBuilderFactory.java
@@ -0,0 +1,25 @@
+/*
+ * 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.karaf.jpm;
+
+
+/**
+ * Factory for process builders.
+ */
+public interface ProcessBuilderFactory {
+    ProcessBuilder newBuilder();
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/7c2db062/instance/src/main/java/org/apache/karaf/jpm/impl/ProcessBuilderFactoryImpl.java
----------------------------------------------------------------------
diff --git a/instance/src/main/java/org/apache/karaf/jpm/impl/ProcessBuilderFactoryImpl.java b/instance/src/main/java/org/apache/karaf/jpm/impl/ProcessBuilderFactoryImpl.java
new file mode 100644
index 0000000..12a6905
--- /dev/null
+++ b/instance/src/main/java/org/apache/karaf/jpm/impl/ProcessBuilderFactoryImpl.java
@@ -0,0 +1,27 @@
+/*
+ * 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.karaf.jpm.impl;
+
+import org.apache.karaf.jpm.ProcessBuilder;
+import org.apache.karaf.jpm.ProcessBuilderFactory;
+
+public class ProcessBuilderFactoryImpl implements ProcessBuilderFactory {
+
+    public ProcessBuilder newBuilder() {
+        return new ProcessBuilderImpl();
+    }
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/7c2db062/instance/src/main/java/org/apache/karaf/jpm/impl/ProcessBuilderImpl.java
----------------------------------------------------------------------
diff --git a/instance/src/main/java/org/apache/karaf/jpm/impl/ProcessBuilderImpl.java b/instance/src/main/java/org/apache/karaf/jpm/impl/ProcessBuilderImpl.java
new file mode 100644
index 0000000..08f4407
--- /dev/null
+++ b/instance/src/main/java/org/apache/karaf/jpm/impl/ProcessBuilderImpl.java
@@ -0,0 +1,48 @@
+/*
+ * 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.karaf.jpm.impl;
+
+import java.io.File;
+import java.io.IOException;
+
+import org.apache.karaf.jpm.Process;
+import org.apache.karaf.jpm.ProcessBuilder;
+
+
+public class ProcessBuilderImpl implements ProcessBuilder {
+
+    private File dir;
+    private String command;
+
+    public ProcessBuilder directory(File dir) {
+        this.dir = dir;
+        return this;
+    }
+
+    public ProcessBuilder command(String command) {
+        this.command = command;
+        return this;
+    }
+
+    public Process start() throws IOException {
+        return ProcessImpl.create(dir, command);
+    }
+
+    public Process attach(int pid) throws IOException {
+        return ProcessImpl.attach(pid);
+    }
+}


[14/59] [abbrv] [KARAF-2852] Merge features/core and features/command

Posted by gn...@apache.org.
http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/core/src/main/java/org/apache/karaf/features/internal/resolver/CandidateComparator.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/resolver/CandidateComparator.java b/features/core/src/main/java/org/apache/karaf/features/internal/resolver/CandidateComparator.java
deleted file mode 100644
index ad4cc85..0000000
--- a/features/core/src/main/java/org/apache/karaf/features/internal/resolver/CandidateComparator.java
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * 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.karaf.features.internal.resolver;
-
-import java.util.Comparator;
-
-import org.osgi.framework.Version;
-import org.osgi.framework.namespace.BundleNamespace;
-import org.osgi.framework.namespace.PackageNamespace;
-import org.osgi.framework.wiring.BundleCapability;
-import org.osgi.resource.Capability;
-
-public class CandidateComparator implements Comparator<Capability>
-{
-    public int compare(Capability cap1, Capability cap2)
-    {
-        int c = 0;
-        // Always prefer system bundle
-        if (cap1 instanceof BundleCapability && !(cap2 instanceof BundleCapability)) {
-            c = -1;
-        } else if (!(cap1 instanceof BundleCapability) && cap2 instanceof BundleCapability) {
-            c = 1;
-        }
-        // Compare revision capabilities.
-        if ((c == 0) && cap1.getNamespace().equals(BundleNamespace.BUNDLE_NAMESPACE))
-        {
-            c = ((Comparable) cap1.getAttributes().get(BundleNamespace.BUNDLE_NAMESPACE))
-                    .compareTo(cap2.getAttributes().get(BundleNamespace.BUNDLE_NAMESPACE));
-            if (c == 0)
-            {
-                Version v1 = (!cap1.getAttributes().containsKey(BundleNamespace.CAPABILITY_BUNDLE_VERSION_ATTRIBUTE))
-                        ? Version.emptyVersion
-                        : (Version) cap1.getAttributes().get(BundleNamespace.CAPABILITY_BUNDLE_VERSION_ATTRIBUTE);
-                Version v2 = (!cap2.getAttributes().containsKey(BundleNamespace.CAPABILITY_BUNDLE_VERSION_ATTRIBUTE))
-                        ? Version.emptyVersion
-                        : (Version) cap2.getAttributes().get(BundleNamespace.CAPABILITY_BUNDLE_VERSION_ATTRIBUTE);
-                // Compare these in reverse order, since we want
-                // highest version to have priority.
-                c = compareVersions(v2, v1);
-            }
-        }
-        // Compare package capabilities.
-        else if ((c == 0) && cap1.getNamespace().equals(PackageNamespace.PACKAGE_NAMESPACE))
-        {
-            c = ((Comparable) cap1.getAttributes().get(PackageNamespace.PACKAGE_NAMESPACE))
-                    .compareTo(cap2.getAttributes().get(PackageNamespace.PACKAGE_NAMESPACE));
-            if (c == 0)
-            {
-                Version v1 = (!cap1.getAttributes().containsKey(PackageNamespace.CAPABILITY_VERSION_ATTRIBUTE))
-                        ? Version.emptyVersion
-                        : (Version) cap1.getAttributes().get(PackageNamespace.CAPABILITY_VERSION_ATTRIBUTE);
-                Version v2 = (!cap2.getAttributes().containsKey(PackageNamespace.CAPABILITY_VERSION_ATTRIBUTE))
-                        ? Version.emptyVersion
-                        : (Version) cap2.getAttributes().get(PackageNamespace.CAPABILITY_VERSION_ATTRIBUTE);
-                // Compare these in reverse order, since we want
-                // highest version to have priority.
-                c = compareVersions(v2, v1);
-                // if same version, rather compare on the bundle version
-                if (c == 0)
-                {
-                    v1 = (!cap1.getAttributes().containsKey(BundleNamespace.CAPABILITY_BUNDLE_VERSION_ATTRIBUTE))
-                            ? Version.emptyVersion
-                            : (Version) cap1.getAttributes().get(BundleNamespace.CAPABILITY_BUNDLE_VERSION_ATTRIBUTE);
-                    v2 = (!cap2.getAttributes().containsKey(BundleNamespace.CAPABILITY_BUNDLE_VERSION_ATTRIBUTE))
-                            ? Version.emptyVersion
-                            : (Version) cap2.getAttributes().get(BundleNamespace.CAPABILITY_BUNDLE_VERSION_ATTRIBUTE);
-                    // Compare these in reverse order, since we want
-                    // highest version to have priority.
-                    c = compareVersions(v2, v1);
-                }
-            }
-        }
-        // Compare feature capabilities
-        else if ((c == 0) && cap1.getNamespace().equals(FeatureNamespace.FEATURE_NAMESPACE))
-        {
-            c = ((Comparable) cap1.getAttributes().get(FeatureNamespace.FEATURE_NAMESPACE))
-                    .compareTo(cap2.getAttributes().get(FeatureNamespace.FEATURE_NAMESPACE));
-            if (c == 0)
-            {
-                Version v1 = (!cap1.getAttributes().containsKey(FeatureNamespace.CAPABILITY_VERSION_ATTRIBUTE))
-                        ? Version.emptyVersion
-                        : (Version) cap1.getAttributes().get(FeatureNamespace.CAPABILITY_VERSION_ATTRIBUTE);
-                Version v2 = (!cap2.getAttributes().containsKey(FeatureNamespace.CAPABILITY_VERSION_ATTRIBUTE))
-                        ? Version.emptyVersion
-                        : (Version) cap2.getAttributes().get(FeatureNamespace.CAPABILITY_VERSION_ATTRIBUTE);
-                // Compare these in reverse order, since we want
-                // highest version to have priority.
-                c = compareVersions(v2, v1);
-            }
-        }
-        return c;
-    }
-
-    private int compareVersions(Version v1, Version v2) {
-        int c = v1.getMajor() - v2.getMajor();
-        if (c != 0) {
-            return c;
-        }
-        c = v1.getMinor() - v2.getMinor();
-        if (c != 0) {
-            return c;
-        }
-        c = v1.getMicro() - v2.getMicro();
-        if (c != 0) {
-            return c;
-        }
-        String q1 = cleanQualifierForComparison(v1.getQualifier());
-        String q2 = cleanQualifierForComparison(v2.getQualifier());
-        return q1.compareTo(q2);
-    }
-
-    private String cleanQualifierForComparison(String qualifier) {
-        return qualifier.replaceAll("(redhat-[0-9]{3})([0-9]{3})", "$1-$2");
-    }
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/core/src/main/java/org/apache/karaf/features/internal/resolver/CapabilityImpl.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/resolver/CapabilityImpl.java b/features/core/src/main/java/org/apache/karaf/features/internal/resolver/CapabilityImpl.java
deleted file mode 100644
index bfe9b40..0000000
--- a/features/core/src/main/java/org/apache/karaf/features/internal/resolver/CapabilityImpl.java
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- * 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.karaf.features.internal.resolver;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.StringTokenizer;
-
-import org.osgi.framework.Constants;
-import org.osgi.resource.Capability;
-import org.osgi.resource.Resource;
-
-public class CapabilityImpl extends BaseClause implements Capability {
-
-    private final Resource m_resource;
-    private final String m_namespace;
-    private final Map<String, String> m_dirs;
-    private final Map<String, Object> m_attrs;
-    private final List<String> m_uses;
-    private final List<List<String>> m_includeFilter;
-    private final List<List<String>> m_excludeFilter;
-    private final Set<String> m_mandatory;
-
-    public CapabilityImpl(Capability capability) {
-        this(null, capability.getNamespace(), capability.getDirectives(), capability.getAttributes());
-    }
-
-    public CapabilityImpl(Resource resource, String namespace,
-                          Map<String, String> dirs, Map<String, Object> attrs) {
-        m_namespace = namespace;
-        m_resource = resource;
-        m_dirs = dirs;
-        m_attrs = attrs;
-
-        // Find all export directives: uses, mandatory, include, and exclude.
-
-        List<String> uses = Collections.emptyList();
-        String value = m_dirs.get(Constants.USES_DIRECTIVE);
-        if (value != null) {
-            // Parse these uses directive.
-            StringTokenizer tok = new StringTokenizer(value, ",");
-            uses = new ArrayList<String>(tok.countTokens());
-            while (tok.hasMoreTokens()) {
-                uses.add(tok.nextToken().trim());
-            }
-        }
-        m_uses = uses;
-
-        value = m_dirs.get(Constants.INCLUDE_DIRECTIVE);
-        if (value != null) {
-            List<String> filters = ResourceBuilder.parseDelimitedString(value, ",");
-            m_includeFilter = new ArrayList<List<String>>(filters.size());
-            for (String filter : filters) {
-                List<String> substrings = SimpleFilter.parseSubstring(filter);
-                m_includeFilter.add(substrings);
-            }
-        } else {
-            m_includeFilter = null;
-        }
-
-        value = m_dirs.get(Constants.EXCLUDE_DIRECTIVE);
-        if (value != null) {
-            List<String> filters = ResourceBuilder.parseDelimitedString(value, ",");
-            m_excludeFilter = new ArrayList<List<String>>(filters.size());
-            for (String filter : filters) {
-                List<String> substrings = SimpleFilter.parseSubstring(filter);
-                m_excludeFilter.add(substrings);
-            }
-        } else {
-            m_excludeFilter = null;
-        }
-
-        Set<String> mandatory = Collections.emptySet();
-        value = m_dirs.get(Constants.MANDATORY_DIRECTIVE);
-        if (value != null) {
-            List<String> names = ResourceBuilder.parseDelimitedString(value, ",");
-            mandatory = new HashSet<String>(names.size());
-            for (String name : names) {
-                // If attribute exists, then record it as mandatory.
-                if (m_attrs.containsKey(name)) {
-                    mandatory.add(name);
-                }
-                // Otherwise, report an error.
-                else {
-                    throw new IllegalArgumentException("Mandatory attribute '" + name + "' does not exist.");
-                }
-            }
-        }
-        m_mandatory = mandatory;
-    }
-
-    public Resource getResource() {
-        return m_resource;
-    }
-
-    public String getNamespace() {
-        return m_namespace;
-    }
-
-    public Map<String, String> getDirectives() {
-        return m_dirs;
-    }
-
-    public Map<String, Object> getAttributes() {
-        return m_attrs;
-    }
-
-    public boolean isAttributeMandatory(String name) {
-        return !m_mandatory.isEmpty() && m_mandatory.contains(name);
-    }
-
-    public List<String> getUses() {
-        return m_uses;
-    }
-
-    public boolean isIncluded(String name) {
-        if ((m_includeFilter == null) && (m_excludeFilter == null)) {
-            return true;
-        }
-
-        // Get the class name portion of the target class.
-        String className = getClassName(name);
-
-        // If there are no include filters then all classes are included
-        // by default, otherwise try to find one match.
-        boolean included = (m_includeFilter == null);
-        for (int i = 0; !included && m_includeFilter != null && i < m_includeFilter.size(); i++) {
-            included = SimpleFilter.compareSubstring(m_includeFilter.get(i), className);
-        }
-
-        // If there are no exclude filters then no classes are excluded
-        // by default, otherwise try to find one match.
-        boolean excluded = false;
-        for (int i = 0; (!excluded) && (m_excludeFilter != null) && (i < m_excludeFilter.size()); i++) {
-            excluded = SimpleFilter.compareSubstring(m_excludeFilter.get(i), className);
-        }
-        return included && !excluded;
-    }
-
-    private static String getClassName(String className) {
-        if (className == null) {
-            className = "";
-        }
-        return (className.lastIndexOf('.') < 0) ? "" : className.substring(className.lastIndexOf('.') + 1);
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/core/src/main/java/org/apache/karaf/features/internal/resolver/CapabilitySet.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/resolver/CapabilitySet.java b/features/core/src/main/java/org/apache/karaf/features/internal/resolver/CapabilitySet.java
deleted file mode 100644
index 4c5656d..0000000
--- a/features/core/src/main/java/org/apache/karaf/features/internal/resolver/CapabilitySet.java
+++ /dev/null
@@ -1,612 +0,0 @@
-/*
- * 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.karaf.features.internal.resolver;
-
-import java.lang.reflect.Array;
-import java.lang.reflect.Constructor;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Set;
-import java.util.TreeMap;
-
-import org.osgi.framework.Constants;
-import org.osgi.resource.Capability;
-
-public class CapabilitySet
-{
-    private final Map<String, Map<Object, Set<Capability>>> m_indices;
-    private final Set<Capability> m_capSet = new HashSet<Capability>();
-
-public void dump()
-{
-    for (Entry<String, Map<Object, Set<Capability>>> entry : m_indices.entrySet())
-    {
-        boolean header1 = false;
-        for (Entry<Object, Set<Capability>> entry2 : entry.getValue().entrySet())
-        {
-            boolean header2 = false;
-            for (Capability cap : entry2.getValue())
-            {
-                if (!header1)
-                {
-                    System.out.println(entry.getKey() + ":");
-                    header1 = true;
-                }
-                if (!header2)
-                {
-                    System.out.println("   " + entry2.getKey());
-                    header2 = true;
-                }
-                System.out.println("      " + cap);
-            }
-        }
-    }
-}
-
-    public CapabilitySet(List<String> indexProps)
-    {
-        m_indices = new TreeMap<String, Map<Object, Set<Capability>>>();
-        for (int i = 0; (indexProps != null) && (i < indexProps.size()); i++)
-        {
-            m_indices.put(
-                indexProps.get(i), new HashMap<Object, Set<Capability>>());
-        }
-    }
-
-    public void addCapability(Capability cap)
-    {
-        m_capSet.add(cap);
-
-        // Index capability.
-        for (Entry<String, Map<Object, Set<Capability>>> entry : m_indices.entrySet())
-        {
-            Object value = cap.getAttributes().get(entry.getKey());
-            if (value != null)
-            {
-                if (value.getClass().isArray())
-                {
-                    value = convertArrayToList(value);
-                }
-
-                Map<Object, Set<Capability>> index = entry.getValue();
-
-                if (value instanceof Collection)
-                {
-                    Collection c = (Collection) value;
-                    for (Object o : c)
-                    {
-                        indexCapability(index, cap, o);
-                    }
-                }
-                else
-                {
-                    indexCapability(index, cap, value);
-                }
-            }
-        }
-    }
-
-    private void indexCapability(
-        Map<Object, Set<Capability>> index, Capability cap, Object capValue)
-    {
-        Set<Capability> caps = index.get(capValue);
-        if (caps == null)
-        {
-            caps = new HashSet<Capability>();
-            index.put(capValue, caps);
-        }
-        caps.add(cap);
-    }
-
-    public void removeCapability(Capability cap)
-    {
-        if (m_capSet.remove(cap))
-        {
-            for (Entry<String, Map<Object, Set<Capability>>> entry : m_indices.entrySet())
-            {
-                Object value = cap.getAttributes().get(entry.getKey());
-                if (value != null)
-                {
-                    if (value.getClass().isArray())
-                    {
-                        value = convertArrayToList(value);
-                    }
-
-                    Map<Object, Set<Capability>> index = entry.getValue();
-
-                    if (value instanceof Collection)
-                    {
-                        Collection c = (Collection) value;
-                        for (Object o : c)
-                        {
-                            deindexCapability(index, cap, o);
-                        }
-                    }
-                    else
-                    {
-                        deindexCapability(index, cap, value);
-                    }
-                }
-            }
-        }
-    }
-
-    private void deindexCapability(
-        Map<Object, Set<Capability>> index, Capability cap, Object value)
-    {
-        Set<Capability> caps = index.get(value);
-        if (caps != null)
-        {
-            caps.remove(cap);
-            if (caps.isEmpty())
-            {
-                index.remove(value);
-            }
-        }
-    }
-
-    public Set<Capability> match(SimpleFilter sf, boolean obeyMandatory)
-    {
-        Set<Capability> matches = match(m_capSet, sf);
-        return (obeyMandatory)
-            ? matchMandatory(matches, sf)
-            : matches;
-    }
-
-    private Set<Capability> match(Set<Capability> caps, SimpleFilter sf)
-    {
-        Set<Capability> matches = new HashSet<Capability>();
-
-        if (sf.getOperation() == SimpleFilter.MATCH_ALL)
-        {
-            matches.addAll(caps);
-        }
-        else if (sf.getOperation() == SimpleFilter.AND)
-        {
-            // Evaluate each subfilter against the remaining capabilities.
-            // For AND we calculate the intersection of each subfilter.
-            // We can short-circuit the AND operation if there are no
-            // remaining capabilities.
-            List<SimpleFilter> sfs = (List<SimpleFilter>) sf.getValue();
-            for (int i = 0; (caps.size() > 0) && (i < sfs.size()); i++)
-            {
-                matches = match(caps, sfs.get(i));
-                caps = matches;
-            }
-        }
-        else if (sf.getOperation() == SimpleFilter.OR)
-        {
-            // Evaluate each subfilter against the remaining capabilities.
-            // For OR we calculate the union of each subfilter.
-            List<SimpleFilter> sfs = (List<SimpleFilter>) sf.getValue();
-            for (int i = 0; i < sfs.size(); i++)
-            {
-                matches.addAll(match(caps, sfs.get(i)));
-            }
-        }
-        else if (sf.getOperation() == SimpleFilter.NOT)
-        {
-            // Evaluate each subfilter against the remaining capabilities.
-            // For OR we calculate the union of each subfilter.
-            matches.addAll(caps);
-            List<SimpleFilter> sfs = (List<SimpleFilter>) sf.getValue();
-            for (int i = 0; i < sfs.size(); i++)
-            {
-                matches.removeAll(match(caps, sfs.get(i)));
-            }
-        }
-        else
-        {
-            Map<Object, Set<Capability>> index = m_indices.get(sf.getName());
-            if ((sf.getOperation() == SimpleFilter.EQ) && (index != null))
-            {
-                Set<Capability> existingCaps = index.get(sf.getValue());
-                if (existingCaps != null)
-                {
-                    matches.addAll(existingCaps);
-                    matches.retainAll(caps);
-                }
-            }
-            else
-            {
-                for (Iterator<Capability> it = caps.iterator(); it.hasNext(); )
-                {
-                    Capability cap = it.next();
-                    Object lhs = cap.getAttributes().get(sf.getName());
-                    if (lhs != null)
-                    {
-                        if (compare(lhs, sf.getValue(), sf.getOperation()))
-                        {
-                            matches.add(cap);
-                        }
-                    }
-                }
-            }
-        }
-
-        return matches;
-    }
-
-    public static boolean matches(Capability cap, SimpleFilter sf)
-    {
-        return matchesInternal(cap, sf) && matchMandatory(cap, sf);
-    }
-
-    private static boolean matchesInternal(Capability cap, SimpleFilter sf)
-    {
-        boolean matched = true;
-
-        if (sf.getOperation() == SimpleFilter.MATCH_ALL)
-        {
-            matched = true;
-        }
-        else if (sf.getOperation() == SimpleFilter.AND)
-        {
-            // Evaluate each subfilter against the remaining capabilities.
-            // For AND we calculate the intersection of each subfilter.
-            // We can short-circuit the AND operation if there are no
-            // remaining capabilities.
-            List<SimpleFilter> sfs = (List<SimpleFilter>) sf.getValue();
-            for (int i = 0; matched && (i < sfs.size()); i++)
-            {
-                matched = matchesInternal(cap, sfs.get(i));
-            }
-        }
-        else if (sf.getOperation() == SimpleFilter.OR)
-        {
-            // Evaluate each subfilter against the remaining capabilities.
-            // For OR we calculate the union of each subfilter.
-            matched = false;
-            List<SimpleFilter> sfs = (List<SimpleFilter>) sf.getValue();
-            for (int i = 0; !matched && (i < sfs.size()); i++)
-            {
-                matched = matchesInternal(cap, sfs.get(i));
-            }
-        }
-        else if (sf.getOperation() == SimpleFilter.NOT)
-        {
-            // Evaluate each subfilter against the remaining capabilities.
-            // For OR we calculate the union of each subfilter.
-            List<SimpleFilter> sfs = (List<SimpleFilter>) sf.getValue();
-            for (int i = 0; i < sfs.size(); i++)
-            {
-                matched = !(matchesInternal(cap, sfs.get(i)));
-            }
-        }
-        else
-        {
-            matched = false;
-            Object lhs = cap.getAttributes().get(sf.getName());
-            if (lhs != null)
-            {
-                matched = compare(lhs, sf.getValue(), sf.getOperation());
-            }
-        }
-
-        return matched;
-    }
-
-    private static Set<Capability> matchMandatory(
-        Set<Capability> caps, SimpleFilter sf)
-    {
-        for (Iterator<Capability> it = caps.iterator(); it.hasNext(); )
-        {
-            Capability cap = it.next();
-            if (!matchMandatory(cap, sf))
-            {
-                it.remove();
-            }
-        }
-        return caps;
-    }
-
-    private static boolean matchMandatory(Capability cap, SimpleFilter sf)
-    {
-        if (cap instanceof CapabilityImpl) {
-            for (Entry<String, Object> entry : cap.getAttributes().entrySet())
-            {
-                if (((CapabilityImpl) cap).isAttributeMandatory(entry.getKey())
-                    && !matchMandatoryAttribute(entry.getKey(), sf))
-                {
-                    return false;
-                }
-            }
-        } else {
-            String value = cap.getDirectives().get(Constants.MANDATORY_DIRECTIVE);
-            if (value != null) {
-                List<String> names = ResourceBuilder.parseDelimitedString(value, ",");
-                for (Entry<String, Object> entry : cap.getAttributes().entrySet())
-                {
-                    if (names.contains(entry.getKey())
-                            && !matchMandatoryAttribute(entry.getKey(), sf))
-                    {
-                        return false;
-                    }
-                }
-            }
-
-        }
-        return true;
-    }
-
-    private static boolean matchMandatoryAttribute(String attrName, SimpleFilter sf)
-    {
-        if ((sf.getName() != null) && sf.getName().equals(attrName))
-        {
-            return true;
-        }
-        else if (sf.getOperation() == SimpleFilter.AND)
-        {
-            List list = (List) sf.getValue();
-            for (int i = 0; i < list.size(); i++)
-            {
-                SimpleFilter sf2 = (SimpleFilter) list.get(i);
-                if ((sf2.getName() != null)
-                    && sf2.getName().equals(attrName))
-                {
-                    return true;
-                }
-            }
-        }
-        return false;
-    }
-
-    private static final Class<?>[] STRING_CLASS = new Class[] { String.class };
-
-    private static boolean compare(Object lhs, Object rhsUnknown, int op)
-    {
-        if (lhs == null)
-        {
-            return false;
-        }
-
-        // If this is a PRESENT operation, then just return true immediately
-        // since we wouldn't be here if the attribute wasn't present.
-        if (op == SimpleFilter.PRESENT)
-        {
-            return true;
-        }
-
-        // If the type is comparable, then we can just return the
-        // result immediately.
-        if (lhs instanceof Comparable)
-        {
-            // Spec says SUBSTRING is false for all types other than string.
-            if ((op == SimpleFilter.SUBSTRING) && !(lhs instanceof String))
-            {
-                return false;
-            }
-
-            Object rhs;
-            if (op == SimpleFilter.SUBSTRING)
-            {
-                rhs = rhsUnknown;
-            }
-            else
-            {
-                try
-                {
-                    rhs = coerceType(lhs, (String) rhsUnknown);
-                }
-                catch (Exception ex)
-                {
-                    return false;
-                }
-            }
-
-            switch (op)
-            {
-                case SimpleFilter.EQ :
-                    try
-                    {
-                        return (((Comparable) lhs).compareTo(rhs) == 0);
-                    }
-                    catch (Exception ex)
-                    {
-                        return false;
-                    }
-                case SimpleFilter.GTE :
-                    try
-                    {
-                        return (((Comparable) lhs).compareTo(rhs) >= 0);
-                    }
-                    catch (Exception ex)
-                    {
-                        return false;
-                    }
-                case SimpleFilter.LTE :
-                    try
-                    {
-                        return (((Comparable) lhs).compareTo(rhs) <= 0);
-                    }
-                    catch (Exception ex)
-                    {
-                        return false;
-                    }
-                case SimpleFilter.APPROX :
-                    return compareApproximate(((Comparable) lhs), rhs);
-                case SimpleFilter.SUBSTRING :
-                    return SimpleFilter.compareSubstring((List<String>) rhs, (String) lhs);
-                default:
-                    throw new RuntimeException(
-                        "Unknown comparison operator: " + op);
-            }
-        }
-        // Booleans do not implement comparable, so special case them.
-        else if (lhs instanceof Boolean)
-        {
-            Object rhs;
-            try
-            {
-                rhs = coerceType(lhs, (String) rhsUnknown);
-            }
-            catch (Exception ex)
-            {
-                return false;
-            }
-
-            switch (op)
-            {
-                case SimpleFilter.EQ :
-                case SimpleFilter.GTE :
-                case SimpleFilter.LTE :
-                case SimpleFilter.APPROX :
-                    return (lhs.equals(rhs));
-                default:
-                    throw new RuntimeException(
-                        "Unknown comparison operator: " + op);
-            }
-        }
-
-        // If the LHS is not a comparable or boolean, check if it is an
-        // array. If so, convert it to a list so we can treat it as a
-        // collection.
-        if (lhs.getClass().isArray())
-        {
-            lhs = convertArrayToList(lhs);
-        }
-
-        // If LHS is a collection, then call compare() on each element
-        // of the collection until a match is found.
-        if (lhs instanceof Collection)
-        {
-            for (Iterator iter = ((Collection) lhs).iterator(); iter.hasNext(); )
-            {
-                if (compare(iter.next(), rhsUnknown, op))
-                {
-                    return true;
-                }
-            }
-
-            return false;
-        }
-
-        // Spec says SUBSTRING is false for all types other than string.
-        if ((op == SimpleFilter.SUBSTRING) && !(lhs instanceof String))
-        {
-            return false;
-        }
-
-        // Since we cannot identify the LHS type, then we can only perform
-        // equality comparison.
-        try
-        {
-            return lhs.equals(coerceType(lhs, (String) rhsUnknown));
-        }
-        catch (Exception ex)
-        {
-            return false;
-        }
-    }
-
-    private static boolean compareApproximate(Object lhs, Object rhs)
-    {
-        if (rhs instanceof String)
-        {
-            return removeWhitespace((String) lhs)
-                .equalsIgnoreCase(removeWhitespace((String) rhs));
-        }
-        else if (rhs instanceof Character)
-        {
-            return Character.toLowerCase(((Character) lhs))
-                == Character.toLowerCase(((Character) rhs));
-        }
-        return lhs.equals(rhs);
-    }
-
-    private static String removeWhitespace(String s)
-    {
-        StringBuffer sb = new StringBuffer(s.length());
-        for (int i = 0; i < s.length(); i++)
-        {
-            if (!Character.isWhitespace(s.charAt(i)))
-            {
-                sb.append(s.charAt(i));
-            }
-        }
-        return sb.toString();
-    }
-
-    private static Object coerceType(Object lhs, String rhsString) throws Exception
-    {
-        // If the LHS expects a string, then we can just return
-        // the RHS since it is a string.
-        if (lhs.getClass() == rhsString.getClass())
-        {
-            return rhsString;
-        }
-
-        // Try to convert the RHS type to the LHS type by using
-        // the string constructor of the LHS class, if it has one.
-        Object rhs = null;
-        try
-        {
-            // The Character class is a special case, since its constructor
-            // does not take a string, so handle it separately.
-            if (lhs instanceof Character)
-            {
-                rhs = new Character(rhsString.charAt(0));
-            }
-            else
-            {
-                // Spec says we should trim number types.
-                if ((lhs instanceof Number) || (lhs instanceof Boolean))
-                {
-                    rhsString = rhsString.trim();
-                }
-                Constructor ctor = lhs.getClass().getConstructor(STRING_CLASS);
-                ctor.setAccessible(true);
-                rhs = ctor.newInstance(new Object[] { rhsString });
-            }
-        }
-        catch (Exception ex)
-        {
-            throw new Exception(
-                "Could not instantiate class "
-                    + lhs.getClass().getName()
-                    + " from string constructor with argument '"
-                    + rhsString + "' because " + ex);
-        }
-
-        return rhs;
-    }
-
-    /**
-     * This is an ugly utility method to convert an array of primitives
-     * to an array of primitive wrapper objects. This method simplifies
-     * processing LDAP filters since the special case of primitive arrays
-     * can be ignored.
-     * @param array An array of primitive types.
-     * @return An corresponding array using pritive wrapper objects.
-    **/
-    private static List convertArrayToList(Object array)
-    {
-        int len = Array.getLength(array);
-        List list = new ArrayList(len);
-        for (int i = 0; i < len; i++)
-        {
-            list.add(Array.get(array, i));
-        }
-        return list;
-    }
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/core/src/main/java/org/apache/karaf/features/internal/resolver/FeatureNamespace.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/resolver/FeatureNamespace.java b/features/core/src/main/java/org/apache/karaf/features/internal/resolver/FeatureNamespace.java
deleted file mode 100644
index e211618..0000000
--- a/features/core/src/main/java/org/apache/karaf/features/internal/resolver/FeatureNamespace.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * 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.karaf.features.internal.resolver;
-
-import java.util.List;
-
-import org.osgi.framework.Version;
-import org.osgi.resource.Capability;
-import org.osgi.resource.Namespace;
-import org.osgi.resource.Resource;
-
-/**
- */
-public final class FeatureNamespace extends Namespace {
-
-    public static final String FEATURE_NAMESPACE = "karaf.feature";
-
-    public static final String	CAPABILITY_VERSION_ATTRIBUTE	= "version";
-
-    /**
-     * The attribute value identifying the resource
-     * {@link org.osgi.framework.namespace.IdentityNamespace#CAPABILITY_TYPE_ATTRIBUTE type} as an OSGi bundle.
-     *
-     * @see org.osgi.framework.namespace.IdentityNamespace#CAPABILITY_TYPE_ATTRIBUTE
-     */
-    public static final String	TYPE_FEATURE = "karaf.feature";
-
-    public static String getName(Resource resource)
-    {
-        List<Capability> caps = resource.getCapabilities(null);
-        for (Capability cap : caps)
-        {
-            if (cap.getNamespace().equals(FEATURE_NAMESPACE))
-            {
-                return cap.getAttributes().get(FEATURE_NAMESPACE).toString();
-            }
-        }
-        return null;
-    }
-
-    public static Version getVersion(Resource resource)
-    {
-        List<Capability> caps = resource.getCapabilities(null);
-        for (Capability cap : caps)
-        {
-            if (cap.getNamespace().equals(FEATURE_NAMESPACE))
-            {
-                return (Version)
-                        cap.getAttributes().get(CAPABILITY_VERSION_ATTRIBUTE);
-            }
-        }
-        return null;
-    }
-
-
-    private FeatureNamespace() {
-    }
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/core/src/main/java/org/apache/karaf/features/internal/resolver/FeatureResource.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/resolver/FeatureResource.java b/features/core/src/main/java/org/apache/karaf/features/internal/resolver/FeatureResource.java
deleted file mode 100644
index 88f08ae..0000000
--- a/features/core/src/main/java/org/apache/karaf/features/internal/resolver/FeatureResource.java
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * 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.karaf.features.internal.resolver;
-
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import org.apache.felix.utils.version.VersionRange;
-import org.apache.felix.utils.version.VersionTable;
-import org.apache.karaf.features.BundleInfo;
-import org.apache.karaf.features.Conditional;
-import org.apache.karaf.features.Dependency;
-import org.apache.karaf.features.Feature;
-import org.apache.karaf.features.internal.util.Macro;
-import org.osgi.framework.BundleException;
-import org.osgi.framework.Constants;
-import org.osgi.framework.Version;
-import org.osgi.framework.namespace.IdentityNamespace;
-import org.osgi.resource.Capability;
-import org.osgi.resource.Requirement;
-import org.osgi.resource.Resource;
-
-/**
-*/
-public class FeatureResource extends ResourceImpl {
-
-    private final Feature feature;
-
-    public static Resource build(Feature feature, Conditional conditional, String featureRange, Map<String, Resource> locToRes) throws BundleException {
-        Feature fcond = conditional.asFeature(feature.getName(), feature.getVersion());
-        FeatureResource resource = (FeatureResource) build(fcond, featureRange, locToRes);
-        for (Dependency dep : conditional.getCondition()) {
-            addDependency(resource, dep, featureRange);
-        }
-        org.apache.karaf.features.internal.model.Dependency dep = new org.apache.karaf.features.internal.model.Dependency();
-        dep.setName(feature.getName());
-        dep.setVersion(feature.getVersion());
-        addDependency(resource, dep, featureRange);
-        return resource;
-    }
-
-    public static Resource build(Feature feature, String featureRange, Map<String, Resource> locToRes) throws BundleException {
-        FeatureResource resource = new FeatureResource(feature);
-        Map<String, String> dirs = new HashMap<String, String>();
-        Map<String, Object> attrs = new HashMap<String, Object>();
-        attrs.put(FeatureNamespace.FEATURE_NAMESPACE, feature.getName());
-        attrs.put(FeatureNamespace.CAPABILITY_VERSION_ATTRIBUTE, VersionTable.getVersion(feature.getVersion()));
-        resource.addCapability(new CapabilityImpl(resource, FeatureNamespace.FEATURE_NAMESPACE, dirs, attrs));
-        for (BundleInfo info : feature.getBundles()) {
-            if (!info.isDependency()) {
-                Resource res = locToRes.get(info.getLocation());
-                if (res == null) {
-                    throw new IllegalStateException("Resource not found for url " + info.getLocation());
-                }
-                List<Capability> caps = res.getCapabilities(IdentityNamespace.IDENTITY_NAMESPACE);
-                if (caps.size() != 1) {
-                    throw new IllegalStateException("Resource does not have a single " + IdentityNamespace.IDENTITY_NAMESPACE + " capability");
-                }
-                dirs = new HashMap<String, String>();
-                attrs = new HashMap<String, Object>();
-                attrs.put(IdentityNamespace.IDENTITY_NAMESPACE, caps.get(0).getAttributes().get(IdentityNamespace.IDENTITY_NAMESPACE));
-                attrs.put(IdentityNamespace.CAPABILITY_TYPE_ATTRIBUTE, caps.get(0).getAttributes().get(IdentityNamespace.CAPABILITY_TYPE_ATTRIBUTE));
-                attrs.put(IdentityNamespace.CAPABILITY_VERSION_ATTRIBUTE, new VersionRange((Version) caps.get(0).getAttributes().get(IdentityNamespace.CAPABILITY_VERSION_ATTRIBUTE), true));
-                resource.addRequirement(new RequirementImpl(resource, IdentityNamespace.IDENTITY_NAMESPACE, dirs, attrs));
-            }
-        }
-        for (Dependency dep : feature.getDependencies()) {
-            addDependency(resource, dep, featureRange);
-        }
-        for (org.apache.karaf.features.Capability cap : feature.getCapabilities()) {
-            resource.addCapabilities(ResourceBuilder.parseCapability(resource, cap.getValue()));
-        }
-        for (org.apache.karaf.features.Requirement req : feature.getRequirements()) {
-            resource.addRequirements(ResourceBuilder.parseRequirement(resource, req.getValue()));
-        }
-        return resource;
-    }
-
-    protected static void addDependency(FeatureResource resource, Dependency dep, String featureRange) {
-        Map<String, String> dirs;
-        Map<String, Object> attrs;
-        String name = dep.getName();
-        String version = dep.getVersion();
-        if (version.equals("0.0.0")) {
-            version = null;
-        } else if (!version.startsWith("[") && !version.startsWith("(")) {
-            version = Macro.transform(featureRange, version);
-        }
-        dirs = new HashMap<String, String>();
-        attrs = new HashMap<String, Object>();
-        attrs.put(FeatureNamespace.FEATURE_NAMESPACE, name);
-        if (version != null) {
-            attrs.put(FeatureNamespace.CAPABILITY_VERSION_ATTRIBUTE, new VersionRange(version));
-        }
-        resource.addRequirement(new RequirementImpl(resource, FeatureNamespace.FEATURE_NAMESPACE, dirs, attrs));
-    }
-
-    public FeatureResource(Feature feature) {
-        super(feature.getName(), FeatureNamespace.TYPE_FEATURE, VersionTable.getVersion(feature.getVersion()));
-        this.feature = feature;
-    }
-
-    public Feature getFeature() {
-        return feature;
-    }
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/core/src/main/java/org/apache/karaf/features/internal/resolver/IdentityCapability.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/resolver/IdentityCapability.java b/features/core/src/main/java/org/apache/karaf/features/internal/resolver/IdentityCapability.java
deleted file mode 100644
index cdc00d1..0000000
--- a/features/core/src/main/java/org/apache/karaf/features/internal/resolver/IdentityCapability.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * 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.karaf.features.internal.resolver;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import org.osgi.framework.Version;
-import org.osgi.framework.namespace.IdentityNamespace;
-import org.osgi.resource.Capability;
-import org.osgi.resource.Resource;
-
-class IdentityCapability extends BaseClause implements Capability
-{
-    private final Resource m_resource;
-    private final Map<String, String> m_dirs;
-    private final Map<String, Object> m_attrs;
-
-    public IdentityCapability(Resource resource, String name, String type, Version version)
-    {
-        m_resource = resource;
-        m_dirs = new HashMap<String, String>();
-        m_attrs = new HashMap<String, Object>();
-        m_attrs.put(IdentityNamespace.IDENTITY_NAMESPACE, name);
-        m_attrs.put(IdentityNamespace.CAPABILITY_TYPE_ATTRIBUTE, type);
-        m_attrs.put(IdentityNamespace.CAPABILITY_VERSION_ATTRIBUTE, version);
-    }
-
-    public String getNamespace()
-    {
-        return IdentityNamespace.IDENTITY_NAMESPACE;
-    }
-
-    public Map<String, String> getDirectives()
-    {
-        return m_dirs;
-    }
-
-    public Map<String, Object> getAttributes()
-    {
-        return m_attrs;
-    }
-
-    public Resource getResource()
-    {
-        return m_resource;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/core/src/main/java/org/apache/karaf/features/internal/resolver/RequirementImpl.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/resolver/RequirementImpl.java b/features/core/src/main/java/org/apache/karaf/features/internal/resolver/RequirementImpl.java
deleted file mode 100644
index a4ef775..0000000
--- a/features/core/src/main/java/org/apache/karaf/features/internal/resolver/RequirementImpl.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * 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.karaf.features.internal.resolver;
-
-import java.util.Map;
-
-import org.osgi.framework.Constants;
-import org.osgi.resource.Capability;
-import org.osgi.resource.Requirement;
-import org.osgi.resource.Resource;
-
-public class RequirementImpl extends BaseClause implements Requirement {
-    private final Resource m_resource;
-    private final String m_namespace;
-    private final SimpleFilter m_filter;
-    private final boolean m_optional;
-    private final Map<String, String> m_dirs;
-    private final Map<String, Object> m_attrs;
-
-    public RequirementImpl(
-            Resource resource, String namespace,
-            Map<String, String> dirs, Map<String, Object> attrs, SimpleFilter filter) {
-        m_resource = resource;
-        m_namespace = namespace;
-        m_dirs = dirs;
-        m_attrs = attrs;
-        m_filter = filter;
-        // Find resolution import directives.
-        m_optional = Constants.RESOLUTION_OPTIONAL.equals(m_dirs.get(Constants.RESOLUTION_DIRECTIVE));
-    }
-
-    public RequirementImpl(
-            Resource resource, String namespace,
-            Map<String, String> dirs, Map<String, Object> attrs) {
-        this(resource, namespace, dirs, attrs, SimpleFilter.convert(attrs));
-    }
-
-    public String getNamespace() {
-        return m_namespace;
-    }
-
-    public Map<String, String> getDirectives() {
-        return m_dirs;
-    }
-
-    public Map<String, Object> getAttributes() {
-        return m_attrs;
-    }
-
-    public Resource getResource() {
-        return m_resource;
-    }
-
-    public boolean matches(Capability cap) {
-        return CapabilitySet.matches(cap, getFilter());
-    }
-
-    public boolean isOptional() {
-        return m_optional;
-    }
-
-    public SimpleFilter getFilter() {
-        return m_filter;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/core/src/main/java/org/apache/karaf/features/internal/resolver/ResolveContextImpl.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/resolver/ResolveContextImpl.java b/features/core/src/main/java/org/apache/karaf/features/internal/resolver/ResolveContextImpl.java
deleted file mode 100644
index e2ff793..0000000
--- a/features/core/src/main/java/org/apache/karaf/features/internal/resolver/ResolveContextImpl.java
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * 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.karaf.features.internal.resolver;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import org.osgi.framework.Constants;
-import org.osgi.resource.Capability;
-import org.osgi.resource.Requirement;
-import org.osgi.resource.Resource;
-import org.osgi.resource.Wiring;
-import org.osgi.service.repository.Repository;
-import org.osgi.service.resolver.HostedCapability;
-import org.osgi.service.resolver.ResolveContext;
-
-/**
-*/
-public class ResolveContextImpl extends ResolveContext {
-
-    private final Set<Resource> mandatory;
-    private final Set<Resource> optional;
-    private final Repository repository;
-    private final Map<Resource, Wiring> wirings;
-    private final boolean resolveOptional;
-
-    private final CandidateComparator candidateComparator = new CandidateComparator();
-
-    public ResolveContextImpl(Set<Resource> mandatory,
-                              Set<Resource> optional,
-                              Repository repository,
-                              boolean resolveOptional) {
-        this.mandatory = mandatory;
-        this.optional = optional;
-        this.repository = repository;
-        this.wirings = new HashMap<Resource, Wiring>();
-        this.resolveOptional = resolveOptional;
-    }
-
-    @Override
-    public Collection<Resource> getMandatoryResources() {
-        return mandatory;
-    }
-
-    @Override
-    public Collection<Resource> getOptionalResources() {
-        return optional;
-    }
-
-    @Override
-    public List<Capability> findProviders(Requirement requirement) {
-        List<Capability> caps = new ArrayList<Capability>();
-        Map<Requirement, Collection<Capability>> resMap =
-                repository.findProviders(Collections.singleton(requirement));
-        Collection<Capability> res = resMap != null ? resMap.get(requirement) : null;
-        if (res != null) {
-            caps.addAll(res);
-        }
-        Collections.sort(caps, candidateComparator);
-        return caps;
-    }
-    @Override
-    public int insertHostedCapability(List capabilities, HostedCapability hostedCapability) {
-        for (int i=0; i < capabilities.size(); i++) {
-            Capability cap = (Capability) capabilities.get(i);
-            if (candidateComparator.compare(hostedCapability, cap) <= 0) {
-                capabilities.add(i, hostedCapability);
-                return i;
-            }
-        }
-        capabilities.add(hostedCapability);
-        return capabilities.size() - 1;
-    }
-    @Override
-    public boolean isEffective(Requirement requirement) {
-        return resolveOptional ||
-                !Constants.RESOLUTION_OPTIONAL.equals(requirement.getDirectives().get(Constants.RESOLUTION_DIRECTIVE));
-    }
-    @Override
-    public Map<Resource, Wiring> getWirings() {
-        return wirings;
-    }
-}


[51/59] [abbrv] [KARAF-2852] Merge web/core and web/command

Posted by gn...@apache.org.
http://git-wip-us.apache.org/repos/asf/karaf/blob/2b7e96df/web/src/main/java/org/apache/karaf/web/management/internal/WebMBeanImpl.java
----------------------------------------------------------------------
diff --git a/web/src/main/java/org/apache/karaf/web/management/internal/WebMBeanImpl.java b/web/src/main/java/org/apache/karaf/web/management/internal/WebMBeanImpl.java
new file mode 100644
index 0000000..f1a81bb
--- /dev/null
+++ b/web/src/main/java/org/apache/karaf/web/management/internal/WebMBeanImpl.java
@@ -0,0 +1,116 @@
+/*
+ * 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.karaf.web.management.internal;
+
+import org.apache.karaf.web.WebBundle;
+import org.apache.karaf.web.WebContainerService;
+import org.apache.karaf.web.management.WebMBean;
+
+import javax.management.MBeanException;
+import javax.management.NotCompliantMBeanException;
+import javax.management.StandardMBean;
+import javax.management.openmbean.*;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Implementation of the Web MBean.
+ */
+public class WebMBeanImpl extends StandardMBean implements WebMBean {
+
+    private WebContainerService webContainerService;
+
+    public WebMBeanImpl() throws NotCompliantMBeanException {
+        super(WebMBean.class);
+    }
+
+    public void setWebContainerService(WebContainerService webContainerService) {
+        this.webContainerService = webContainerService;
+    }
+
+    public TabularData getWebBundles() throws MBeanException {
+        try {
+            CompositeType webType = new CompositeType("Web Bundle", "An OSGi Web bundle",
+                    new String[]{"ID", "State", "Web-State", "Level", "Web-ContextPath", "Name"},
+                    new String[]{"ID of the bundle",
+                            "OSGi state of the bundle",
+                            "Web state of the bundle",
+                            "Start level of the bundle",
+                            "Web context path",
+                            "Name of the bundle"},
+                    new OpenType[]{SimpleType.LONG, SimpleType.STRING, SimpleType.STRING, SimpleType.INTEGER, SimpleType.STRING, SimpleType.STRING});
+            TabularType tableType = new TabularType("Web Bundles", "Table of web bundles", webType,
+                    new String[]{"ID"});
+            TabularData table = new TabularDataSupport(tableType);
+            for (WebBundle webBundle : webContainerService.list()) {
+                try {
+                    CompositeData data = new CompositeDataSupport(webType,
+                            new String[]{"ID", "State", "Web-State", "Level", "Web-ContextPath", "Name"},
+                            new Object[]{webBundle.getBundleId(),
+                                    webBundle.getState(),
+                                    webBundle.getWebState(),
+                                    webBundle.getLevel(),
+                                    webBundle.getContextPath(),
+                                    webBundle.getName()});
+                    table.put(data);
+                } catch (Exception e) {
+                    e.printStackTrace();
+                }
+            }
+            return table;
+        } catch (Exception e) {
+            throw new MBeanException(null, e.getMessage());
+        }
+    }
+
+    public void start(Long bundleId) throws MBeanException {
+        try {
+            List<Long> list = new ArrayList<Long>();
+            list.add(bundleId);
+            webContainerService.start(list);
+        } catch (Exception e) {
+            throw new MBeanException(null, e.getMessage());
+        }
+    }
+
+    public void start(List<Long> bundleIds) throws MBeanException {
+        try {
+            webContainerService.start(bundleIds);
+        } catch (Exception e) {
+            throw new MBeanException(null, e.getMessage());
+        }
+    }
+
+    public void stop(Long bundleId) throws MBeanException {
+        try {
+            List<Long> list = new ArrayList<Long>();
+            list.add(bundleId);
+            webContainerService.stop(list);
+        } catch (Exception e) {
+            throw new MBeanException(null, e.getMessage());
+        }
+    }
+
+    public void stop(List<Long> bundleIds) throws MBeanException {
+        try {
+            webContainerService.stop(bundleIds);
+        } catch (Exception e) {
+            throw new MBeanException(null, e.getMessage());
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/2b7e96df/web/src/main/resources/OSGI-INF/bundle.info
----------------------------------------------------------------------
diff --git a/web/src/main/resources/OSGI-INF/bundle.info b/web/src/main/resources/OSGI-INF/bundle.info
new file mode 100644
index 0000000..650fee9
--- /dev/null
+++ b/web/src/main/resources/OSGI-INF/bundle.info
@@ -0,0 +1,16 @@
+h1. Synopsis
+
+${project.name}
+
+${project.description}
+
+Maven URL:
+[mvn:${project.groupId}/${project.artifactId}/${project.version}]
+
+h1. Description
+
+This bundle provides support of the WebContainer service, which allows to manipulate the Karaf embedded web container.
+
+h1. See also
+
+Web Container - section of the Karaf User Guide


[02/59] [abbrv] [KARAF-2852] Merge features/core and features/command

Posted by gn...@apache.org.
http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/src/main/resources/org/apache/karaf/features/karaf-features-1.0.0.xsd
----------------------------------------------------------------------
diff --git a/features/src/main/resources/org/apache/karaf/features/karaf-features-1.0.0.xsd b/features/src/main/resources/org/apache/karaf/features/karaf-features-1.0.0.xsd
new file mode 100644
index 0000000..9536ba1
--- /dev/null
+++ b/features/src/main/resources/org/apache/karaf/features/karaf-features-1.0.0.xsd
@@ -0,0 +1,239 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+    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.
+
+-->
+<xs:schema elementFormDefault="qualified"
+    targetNamespace="http://karaf.apache.org/xmlns/features/v1.0.0"
+    xmlns:tns="http://karaf.apache.org/xmlns/features/v1.0.0"
+    xmlns:xs="http://www.w3.org/2001/XMLSchema">
+
+    <xs:annotation>
+        <xs:documentation><![CDATA[
+Karaf features mechanism. For documentation please visit the
+<a href="http://karaf.apache.org/">Karaf website</a>.
+        ]]></xs:documentation>
+    </xs:annotation>
+
+    <xs:complexType name="features">
+        <xs:annotation>
+            <xs:documentation><![CDATA[
+Root element of the Feature definition. It contains an optional attribute for
+designating the name of the repository of this feature. The Karaf shell will
+show the repository name when displaying information about the feature.
+            ]]></xs:documentation>
+        </xs:annotation>
+        <xs:choice minOccurs="0" maxOccurs="unbounded">
+            <xs:element name="repository" type="xs:anyURI">
+                <xs:annotation>
+                    <xs:documentation><![CDATA[
+Additional repositories where dependencies are stored.
+                    ]]></xs:documentation>
+                </xs:annotation>
+            </xs:element>
+            <xs:element name="feature" type="tns:feature">
+                <xs:annotation>
+                    <xs:documentation><![CDATA[
+Feature definition.
+                    ]]></xs:documentation>
+                </xs:annotation>
+            </xs:element>
+        </xs:choice>
+        <xs:attribute name="name" type="xs:string" />
+    </xs:complexType>
+
+    <xs:complexType name="feature">
+        <xs:annotation>
+            <xs:documentation><![CDATA[
+Definition of the Feature.
+            ]]></xs:documentation>
+        </xs:annotation>
+        <xs:choice minOccurs="0" maxOccurs="unbounded">
+            <xs:element name="details" minOccurs="0" type="xs:string">
+                <xs:annotation>
+                    <xs:documentation><![CDATA[
+The help text shown for this feature when using the feature:info console command.
+                    ]]>
+                    </xs:documentation>
+                </xs:annotation>
+            </xs:element>
+            <xs:element name="config" type="tns:config" />
+            <xs:element name="configfile" type="tns:configFile" />
+            <xs:element name="feature" type="tns:dependency" />
+            <xs:element name="bundle" type="tns:bundle" />
+        </xs:choice>
+        <xs:attribute name="name" type="tns:featureName" use="required" />
+        <xs:attribute name="version" type="xs:string" default="0.0.0" />
+        <xs:attribute name="description" type="xs:string" />
+        <xs:attribute name="resolver" type="tns:resolver">
+            <xs:annotation>
+                <xs:documentation><![CDATA[
+Optional alternative resolver to use for determining the list of bundles to install for a given feature.
+                ]]>
+                </xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="install" type="tns:install">
+            <xs:annotation>
+                <xs:documentation><![CDATA[
+If true, marks that the feature should start automatically when placed in the deploy folder.
+                ]]>
+                </xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="start-level" type="xs:int">
+             <xs:annotation>
+                <xs:documentation><![CDATA[
+Set this attribute to have an OSGi start level for the bundles in this feature different
+from the default start level defined in Karaf's config.properties.
+                ]]>
+                </xs:documentation>
+             </xs:annotation>
+         </xs:attribute>
+         <xs:attribute name="region" type="xs:string"/>
+    </xs:complexType>
+
+    <xs:complexType name="bundle">
+        <xs:annotation>
+            <xs:documentation><![CDATA[
+Deployable element to install.
+            ]]></xs:documentation>
+        </xs:annotation>
+        <xs:simpleContent>
+            <xs:extension base="xs:anyURI">
+                <xs:attribute name="start-level" type="xs:int">
+                    <xs:annotation>
+                        <xs:documentation><![CDATA[
+Set this attribute to have an OSGi start level for this bundle different
+from the default start level defined in Karaf's config.properties.
+
+                        ]]>
+                        </xs:documentation>
+                    </xs:annotation>
+                </xs:attribute>
+                <xs:attribute name="start" type="xs:boolean" default="true">
+                    <xs:annotation>
+                        <xs:documentation><![CDATA[
+If false, leaves the bundle in resolved state rather than the default active state.
+                        ]]>
+                        </xs:documentation>
+                    </xs:annotation>
+                </xs:attribute>
+                <xs:attribute name="dependency" type="xs:boolean">
+                    <xs:annotation>
+                        <xs:documentation><![CDATA[
+Mark this bundle as a dependency for the resolver.
+                        ]]>
+                        </xs:documentation>
+                    </xs:annotation>
+                </xs:attribute>
+            </xs:extension>
+        </xs:simpleContent>
+    </xs:complexType>
+
+    <xs:complexType name="dependency">
+        <xs:annotation>
+            <xs:documentation><![CDATA[
+Dependency of feature.
+            ]]></xs:documentation>
+        </xs:annotation>
+        <xs:simpleContent>
+            <xs:extension base="tns:featureName">
+                <xs:attribute name="version" type="xs:string" default="0.0.0" />
+            </xs:extension>
+        </xs:simpleContent>
+    </xs:complexType>
+
+    <xs:complexType name="config">
+        <xs:annotation>
+            <xs:documentation><![CDATA[
+Configuration entries which should be created during feature installation. This
+configuration may be used with OSGi Configuration Admin. The element content is
+read in as a properties file.
+            ]]></xs:documentation>
+        </xs:annotation>
+        <xs:simpleContent>
+            <xs:extension base="xs:string">
+                <xs:attribute name="name" type="xs:string" use="required" />
+            </xs:extension>
+        </xs:simpleContent>
+    </xs:complexType>
+
+    <xs:complexType name="configFile">
+        <xs:annotation>
+            <xs:documentation><![CDATA[
+Additional configuration files which should be created during feature installation.
+            ]]></xs:documentation>
+        </xs:annotation>
+        <xs:simpleContent>
+            <xs:extension base="xs:anyURI">
+                <xs:attribute name="finalname" type="xs:string" use="required">
+                    <xs:annotation>
+                        <xs:documentation><![CDATA[
+The final destination path and name for the configuration file (relative to the KARAF_BASE).
+                        ]]></xs:documentation>
+                    </xs:annotation>
+                </xs:attribute>
+                <xs:attribute name="override" type="xs:boolean">
+                    <xs:annotation>
+                        <xs:documentation><![CDATA[
+If the configFile already exists at the finalname location, whether or not to replace it.
+                        ]]></xs:documentation>
+                    </xs:annotation>
+                </xs:attribute>
+
+            </xs:extension>
+        </xs:simpleContent>
+    </xs:complexType>
+
+    <xs:simpleType name="featureName">
+        <xs:annotation>
+            <xs:documentation><![CDATA[
+Feature name should be non empty string.
+            ]]></xs:documentation>
+        </xs:annotation>
+        <xs:restriction base="xs:string">
+            <xs:minLength value="1" />
+        </xs:restriction>
+    </xs:simpleType>
+
+    <xs:simpleType name="resolver">
+        <xs:annotation>
+            <xs:documentation><![CDATA[
+Resolver to use. Karaf will look for OSGi service which has following properties:
+objectClass: org.apache.karaf.features.Resolver
+name: the value
+            ]]></xs:documentation>
+        </xs:annotation>
+        <xs:restriction base="xs:string">
+            <xs:minLength value="1" />
+        </xs:restriction>
+    </xs:simpleType>
+    <xs:simpleType name="install">
+        <xs:annotation>
+            <xs:documentation><![CDATA[
+Installation mode. Can be either manual or auto. Specifies whether the feature should be automatically installed when
+dropped inside the deploy folder. Note: This attribute doesn't affect feature descriptors that are installed from the
+command line or as part of the org.apache.karaf.features.cfg.
+            ]]></xs:documentation>
+        </xs:annotation>
+        <xs:restriction base="xs:string">
+            <xs:minLength value="1" />
+        </xs:restriction>
+    </xs:simpleType>
+    <xs:element name="features" type="tns:features" />
+
+</xs:schema>

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/src/main/resources/org/apache/karaf/features/karaf-features-1.1.0.xsd
----------------------------------------------------------------------
diff --git a/features/src/main/resources/org/apache/karaf/features/karaf-features-1.1.0.xsd b/features/src/main/resources/org/apache/karaf/features/karaf-features-1.1.0.xsd
new file mode 100644
index 0000000..7138573
--- /dev/null
+++ b/features/src/main/resources/org/apache/karaf/features/karaf-features-1.1.0.xsd
@@ -0,0 +1,237 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+    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.
+
+-->
+<xs:schema elementFormDefault="qualified"
+    targetNamespace="http://karaf.apache.org/xmlns/features/v1.1.0"
+    xmlns:tns="http://karaf.apache.org/xmlns/features/v1.1.0"
+    xmlns:xs="http://www.w3.org/2001/XMLSchema">
+
+    <xs:annotation>
+        <xs:documentation><![CDATA[
+Karaf features mechanism. For documentation please visit the
+<a href="http://karaf.apache.org/">Karaf website</a>.
+        ]]></xs:documentation>
+    </xs:annotation>
+
+    <xs:complexType name="features">
+        <xs:annotation>
+            <xs:documentation><![CDATA[
+Root element of Feature definition. It contains an required attribute for
+designating from which repository this feature should be loaded. The Karaf
+shell will show the repository name when displaying information about the feature.
+            ]]></xs:documentation>
+        </xs:annotation>
+        <xs:choice minOccurs="0" maxOccurs="unbounded">
+            <xs:element name="repository" type="xs:anyURI">
+                <xs:annotation>
+                    <xs:documentation><![CDATA[
+Additional repositories where dependencies are stored.
+                    ]]></xs:documentation>
+                </xs:annotation>
+            </xs:element>
+            <xs:element name="feature" type="tns:feature">
+                <xs:annotation>
+                    <xs:documentation><![CDATA[
+Feature definition.
+                    ]]></xs:documentation>
+                </xs:annotation>
+            </xs:element>
+        </xs:choice>
+        <xs:attribute name="name" type="xs:string" use="required"/>
+    </xs:complexType>
+
+    <xs:complexType name="feature">
+        <xs:annotation>
+            <xs:documentation><![CDATA[
+Definition of the Feature.
+            ]]></xs:documentation>
+        </xs:annotation>
+        <xs:choice minOccurs="0" maxOccurs="unbounded">
+            <xs:element name="details" minOccurs="0" type="xs:string">
+                <xs:annotation>
+                    <xs:documentation><![CDATA[
+The help text shown for this feature when using feature:info console command.
+                    ]]>
+                    </xs:documentation>
+                </xs:annotation>
+            </xs:element>
+            <xs:element name="config" type="tns:config" />
+            <xs:element name="configfile" type="tns:configFile" />
+            <xs:element name="feature" type="tns:dependency" />
+            <xs:element name="bundle" type="tns:bundle" />
+        </xs:choice>
+        <xs:attribute name="name" type="tns:featureName" use="required" />
+        <xs:attribute name="version" type="xs:string" default="0.0.0" />
+        <xs:attribute name="description" type="xs:string" />
+        <xs:attribute name="resolver" type="tns:resolver">
+            <xs:annotation>
+                <xs:documentation><![CDATA[
+Optional alternative resolver to use for determining the list of bundles to install for a given feature.
+                ]]>
+                </xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="install" type="tns:install">
+            <xs:annotation>
+                <xs:documentation><![CDATA[
+Marks if the feaute will be automatically started when thrown to the deploy folder.
+                ]]>
+                </xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="start-level" type="xs:int">
+             <xs:annotation>
+                <xs:documentation><![CDATA[
+Set this attribute to have an OSGi start level for this feature different
+from the default start level defined in Karaf's config.properties.
+                ]]>
+                </xs:documentation>
+             </xs:annotation>
+         </xs:attribute>
+    </xs:complexType>
+
+    <xs:complexType name="bundle">
+        <xs:annotation>
+            <xs:documentation><![CDATA[
+Deployable element to install.
+            ]]></xs:documentation>
+        </xs:annotation>
+        <xs:simpleContent>
+            <xs:extension base="xs:anyURI">
+                <xs:attribute name="start-level" type="xs:int">
+                    <xs:annotation>
+                        <xs:documentation><![CDATA[
+Set this attribute to have an OSGi start level for this bundle different
+from the default start level defined in the Karaf's config.properties.
+                        ]]>
+                        </xs:documentation>
+                    </xs:annotation>
+                </xs:attribute>
+                <xs:attribute name="start" type="xs:boolean" default="true">
+                    <xs:annotation>
+                        <xs:documentation><![CDATA[
+If false, leaves bundle in resolved state rather than the default active state.
+                        ]]>
+                        </xs:documentation>
+                    </xs:annotation>
+                </xs:attribute>
+                <xs:attribute name="dependency" type="xs:boolean">
+                    <xs:annotation>
+                        <xs:documentation><![CDATA[
+Mark this bundle as a dependency for the resolver.
+                        ]]>
+                        </xs:documentation>
+                    </xs:annotation>
+                </xs:attribute>
+            </xs:extension>
+        </xs:simpleContent>
+    </xs:complexType>
+
+    <xs:complexType name="dependency">
+        <xs:annotation>
+            <xs:documentation><![CDATA[
+Dependency of feature.
+            ]]></xs:documentation>
+        </xs:annotation>
+        <xs:simpleContent>
+            <xs:extension base="tns:featureName">
+                <xs:attribute name="version" type="xs:string" default="0.0.0" />
+            </xs:extension>
+        </xs:simpleContent>
+    </xs:complexType>
+
+    <xs:complexType name="config">
+        <xs:annotation>
+            <xs:documentation><![CDATA[
+Configuration entries which should be created during feature installation. This
+configuration may be used with OSGi Configuration Admin. The element content is
+read in as a properties file.
+            ]]></xs:documentation>
+        </xs:annotation>
+        <xs:simpleContent>
+            <xs:extension base="xs:string">
+                <xs:attribute name="name" type="xs:string" use="required" />
+            </xs:extension>
+        </xs:simpleContent>
+    </xs:complexType>
+
+    <xs:complexType name="configFile">
+        <xs:annotation>
+            <xs:documentation><![CDATA[
+Additional configuration files which should be created during feature installation.
+            ]]></xs:documentation>
+        </xs:annotation>
+        <xs:simpleContent>
+            <xs:extension base="xs:anyURI">
+                <xs:attribute name="finalname" type="xs:string" use="required">
+                    <xs:annotation>
+                        <xs:documentation><![CDATA[
+The final destination path and name for the configuration file.
+                        ]]></xs:documentation>
+                    </xs:annotation>
+                </xs:attribute>
+                <xs:attribute name="override" type="xs:boolean">
+                    <xs:annotation>
+                        <xs:documentation><![CDATA[
+If the configFile already exists at the finalname location, whether or not to replace it.
+                        ]]></xs:documentation>
+                    </xs:annotation>
+                </xs:attribute>
+
+            </xs:extension>
+        </xs:simpleContent>
+    </xs:complexType>
+
+    <xs:simpleType name="featureName">
+        <xs:annotation>
+            <xs:documentation><![CDATA[
+Feature name should be non empty string.
+            ]]></xs:documentation>
+        </xs:annotation>
+        <xs:restriction base="xs:string">
+            <xs:minLength value="1" />
+        </xs:restriction>
+    </xs:simpleType>
+
+    <xs:simpleType name="resolver">
+        <xs:annotation>
+            <xs:documentation><![CDATA[
+Resolver to use. Karaf will look for OSGi service which have following properties:
+objectClass: org.apache.karaf.features.Resolver
+name: the value
+            ]]></xs:documentation>
+        </xs:annotation>
+        <xs:restriction base="xs:string">
+            <xs:minLength value="1" />
+        </xs:restriction>
+    </xs:simpleType>
+    <xs:simpleType name="install">
+        <xs:annotation>
+            <xs:documentation><![CDATA[
+Installation mode. Can be either manual or auto. Specifies whether the feature should be automatically installed when
+dropped inside the deploy folder. Note: This attribute doesn't affect feature descriptors that are installed from the
+command line or as part of the org.apache.karaf.features.cfg.
+            ]]></xs:documentation>
+        </xs:annotation>
+        <xs:restriction base="xs:string">
+            <xs:minLength value="1" />
+        </xs:restriction>
+    </xs:simpleType>
+    <xs:element name="features" type="tns:features" />
+
+</xs:schema>

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/src/main/resources/org/apache/karaf/features/karaf-features-1.2.0.xsd
----------------------------------------------------------------------
diff --git a/features/src/main/resources/org/apache/karaf/features/karaf-features-1.2.0.xsd b/features/src/main/resources/org/apache/karaf/features/karaf-features-1.2.0.xsd
new file mode 100644
index 0000000..dbc4bfa
--- /dev/null
+++ b/features/src/main/resources/org/apache/karaf/features/karaf-features-1.2.0.xsd
@@ -0,0 +1,254 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+    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.
+
+-->
+<xs:schema elementFormDefault="qualified"
+    targetNamespace="http://karaf.apache.org/xmlns/features/v1.2.0"
+    xmlns:tns="http://karaf.apache.org/xmlns/features/v1.2.0"
+    xmlns:xs="http://www.w3.org/2001/XMLSchema">
+
+    <xs:annotation>
+        <xs:documentation><![CDATA[
+Karaf features mechanism. For documentation please visit the
+<a href="http://karaf.apache.org/">Karaf website</a>.
+        ]]></xs:documentation>
+    </xs:annotation>
+
+    <xs:complexType name="features">
+        <xs:annotation>
+            <xs:documentation><![CDATA[
+Root element of Feature definition. It contains an required attribute for
+designating from which repository this feature should be loaded. The Karaf
+shell will show the repository name when displaying information about the feature.
+            ]]></xs:documentation>
+        </xs:annotation>
+        <xs:choice minOccurs="0" maxOccurs="unbounded">
+            <xs:element name="repository" type="xs:anyURI">
+                <xs:annotation>
+                    <xs:documentation><![CDATA[
+Additional repositories where dependencies are stored.
+                    ]]></xs:documentation>
+                </xs:annotation>
+            </xs:element>
+            <xs:element name="feature" type="tns:feature">
+                <xs:annotation>
+                    <xs:documentation><![CDATA[
+Feature definition.
+                    ]]></xs:documentation>
+                </xs:annotation>
+            </xs:element>
+        </xs:choice>
+        <xs:attribute name="name" type="xs:string" use="required"/>
+    </xs:complexType>
+
+    <xs:complexType name="feature">
+        <xs:annotation>
+            <xs:documentation><![CDATA[
+Definition of the Feature.
+            ]]></xs:documentation>
+        </xs:annotation>
+        <xs:choice minOccurs="0" maxOccurs="unbounded">
+            <xs:element name="details" minOccurs="0" type="xs:string">
+                <xs:annotation>
+                    <xs:documentation><![CDATA[
+The help text shown for this feature when using feature:info console command.
+                    ]]>
+                    </xs:documentation>
+                </xs:annotation>
+            </xs:element>
+            <xs:element name="config" type="tns:config" />
+            <xs:element name="configfile" type="tns:configFile" />
+            <xs:element name="feature" type="tns:dependency" />
+            <xs:element name="bundle" type="tns:bundle" />
+            <xs:element name="conditional" type="tns:conditional" />
+        </xs:choice>
+        <xs:attribute name="name" type="tns:featureName" use="required" />
+        <xs:attribute name="version" type="xs:string" default="0.0.0" />
+        <xs:attribute name="description" type="xs:string" />
+        <xs:attribute name="resolver" type="tns:resolver">
+            <xs:annotation>
+                <xs:documentation><![CDATA[
+Optional alternative resolver to use for determining the list of bundles to install for a given feature.
+                ]]>
+                </xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="install" type="tns:install">
+            <xs:annotation>
+                <xs:documentation><![CDATA[
+Marks if the feaute will be automatically started when thrown to the deploy folder.
+                ]]>
+                </xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="start-level" type="xs:int">
+             <xs:annotation>
+                <xs:documentation><![CDATA[
+Set this attribute to have an OSGi start level for this feature different
+from the default start level defined in Karaf's config.properties.
+                ]]>
+                </xs:documentation>
+             </xs:annotation>
+         </xs:attribute>
+    </xs:complexType>
+
+    <xs:complexType name="conditional">
+        <xs:annotation>
+            <xs:documentation><![CDATA[
+Definition of the Conditional.
+            ]]></xs:documentation>
+        </xs:annotation>
+        <xs:choice minOccurs="0" maxOccurs="unbounded">
+            <xs:element name="config" type="tns:config" />
+            <xs:element name="configfile" type="tns:configFile" />
+            <xs:element name="feature" type="tns:dependency" />
+            <xs:element name="bundle" type="tns:bundle" />
+            <xs:element name="condition" type="tns:dependency" minOccurs="0" maxOccurs="1" />
+        </xs:choice>
+    </xs:complexType>
+
+
+    <xs:complexType name="bundle">
+        <xs:annotation>
+            <xs:documentation><![CDATA[
+Deployable element to install.
+            ]]></xs:documentation>
+        </xs:annotation>
+        <xs:simpleContent>
+            <xs:extension base="xs:anyURI">
+                <xs:attribute name="start-level" type="xs:int">
+                    <xs:annotation>
+                        <xs:documentation><![CDATA[
+Set this attribute to have an OSGi start level for this bundle different
+from the default start level defined in the Karaf's config.properties.
+                        ]]>
+                        </xs:documentation>
+                    </xs:annotation>
+                </xs:attribute>
+                <xs:attribute name="start" type="xs:boolean" default="true">
+                    <xs:annotation>
+                        <xs:documentation><![CDATA[
+If false, leaves bundle in resolved state rather than the default active state.
+                        ]]>
+                        </xs:documentation>
+                    </xs:annotation>
+                </xs:attribute>
+                <xs:attribute name="dependency" type="xs:boolean">
+                    <xs:annotation>
+                        <xs:documentation><![CDATA[
+Mark this bundle as a dependency for the resolver.
+                        ]]>
+                        </xs:documentation>
+                    </xs:annotation>
+                </xs:attribute>
+            </xs:extension>
+        </xs:simpleContent>
+    </xs:complexType>
+
+    <xs:complexType name="dependency">
+        <xs:annotation>
+            <xs:documentation><![CDATA[
+Dependency of feature.
+            ]]></xs:documentation>
+        </xs:annotation>
+        <xs:simpleContent>
+            <xs:extension base="tns:featureName">
+                <xs:attribute name="version" type="xs:string" default="0.0.0" />
+            </xs:extension>
+        </xs:simpleContent>
+    </xs:complexType>
+
+    <xs:complexType name="config">
+        <xs:annotation>
+            <xs:documentation><![CDATA[
+Configuration entries which should be created during feature installation. This
+configuration may be used with OSGi Configuration Admin. The element content is
+read in as a properties file.
+            ]]></xs:documentation>
+        </xs:annotation>
+        <xs:simpleContent>
+            <xs:extension base="xs:string">
+                <xs:attribute name="name" type="xs:string" use="required" />
+            </xs:extension>
+        </xs:simpleContent>
+    </xs:complexType>
+
+    <xs:complexType name="configFile">
+        <xs:annotation>
+            <xs:documentation><![CDATA[
+Additional configuration files which should be created during feature installation.
+            ]]></xs:documentation>
+        </xs:annotation>
+        <xs:simpleContent>
+            <xs:extension base="xs:anyURI">
+                <xs:attribute name="finalname" type="xs:string" use="required">
+                    <xs:annotation>
+                        <xs:documentation><![CDATA[
+The final destination path and name for the configuration file.
+                        ]]></xs:documentation>
+                    </xs:annotation>
+                </xs:attribute>
+                <xs:attribute name="override" type="xs:boolean">
+                    <xs:annotation>
+                        <xs:documentation><![CDATA[
+If the configFile already exists at the finalname location, whether or not to replace it.
+                        ]]></xs:documentation>
+                    </xs:annotation>
+                </xs:attribute>
+
+            </xs:extension>
+        </xs:simpleContent>
+    </xs:complexType>
+
+    <xs:simpleType name="featureName">
+        <xs:annotation>
+            <xs:documentation><![CDATA[
+Feature name should be non empty string.
+            ]]></xs:documentation>
+        </xs:annotation>
+        <xs:restriction base="xs:string">
+            <xs:minLength value="1" />
+        </xs:restriction>
+    </xs:simpleType>
+
+    <xs:simpleType name="resolver">
+        <xs:annotation>
+            <xs:documentation><![CDATA[
+Resolver to use. Karaf will look for OSGi service which have following properties:
+objectClass: org.apache.karaf.features.Resolver
+name: the value
+            ]]></xs:documentation>
+        </xs:annotation>
+        <xs:restriction base="xs:string">
+            <xs:minLength value="1" />
+        </xs:restriction>
+    </xs:simpleType>
+    <xs:simpleType name="install">
+        <xs:annotation>
+            <xs:documentation><![CDATA[
+Installation mode. Can be either manual or auto. Specifies whether the feature should be automatically installed when
+dropped inside the deploy folder. Note: This attribute doesn't affect feature descriptors that are installed from the
+command line or as part of the org.apache.karaf.features.cfg.
+            ]]></xs:documentation>
+        </xs:annotation>
+        <xs:restriction base="xs:string">
+            <xs:minLength value="1" />
+        </xs:restriction>
+    </xs:simpleType>
+    <xs:element name="features" type="tns:features" />
+
+</xs:schema>

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/src/main/resources/org/apache/karaf/features/karaf-features-1.3.0.xsd
----------------------------------------------------------------------
diff --git a/features/src/main/resources/org/apache/karaf/features/karaf-features-1.3.0.xsd b/features/src/main/resources/org/apache/karaf/features/karaf-features-1.3.0.xsd
new file mode 100644
index 0000000..60ec8d2
--- /dev/null
+++ b/features/src/main/resources/org/apache/karaf/features/karaf-features-1.3.0.xsd
@@ -0,0 +1,280 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+    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.
+
+-->
+<xs:schema elementFormDefault="qualified"
+    targetNamespace="http://karaf.apache.org/xmlns/features/v1.3.0"
+    xmlns:tns="http://karaf.apache.org/xmlns/features/v1.3.0"
+    xmlns:xs="http://www.w3.org/2001/XMLSchema">
+
+    <xs:annotation>
+        <xs:documentation><![CDATA[
+Karaf features mechanism. For documentation please visit the
+<a href="http://karaf.apache.org/">Karaf website</a>.
+        ]]></xs:documentation>
+    </xs:annotation>
+
+    <xs:complexType name="features">
+        <xs:annotation>
+            <xs:documentation><![CDATA[
+Root element of Feature definition. It contains an required attribute for
+designating from which repository this feature should be loaded. The Karaf
+shell will show the repository name when displaying information about the feature.
+            ]]></xs:documentation>
+        </xs:annotation>
+        <xs:choice minOccurs="0" maxOccurs="unbounded">
+            <xs:element name="repository" type="xs:anyURI">
+                <xs:annotation>
+                    <xs:documentation><![CDATA[
+Additional repositories where dependencies are stored.
+                    ]]></xs:documentation>
+                </xs:annotation>
+            </xs:element>
+            <xs:element name="feature" type="tns:feature">
+                <xs:annotation>
+                    <xs:documentation><![CDATA[
+Feature definition.
+                    ]]></xs:documentation>
+                </xs:annotation>
+            </xs:element>
+        </xs:choice>
+        <xs:attribute name="name" type="xs:string" use="required"/>
+    </xs:complexType>
+
+    <xs:complexType name="feature">
+        <xs:annotation>
+            <xs:documentation><![CDATA[
+Definition of the Feature.
+            ]]></xs:documentation>
+        </xs:annotation>
+        <xs:choice minOccurs="0" maxOccurs="unbounded">
+            <xs:element name="details" minOccurs="0" type="xs:string">
+                <xs:annotation>
+                    <xs:documentation><![CDATA[
+The help text shown for this feature when using feature:info console command.
+                    ]]>
+                    </xs:documentation>
+                </xs:annotation>
+            </xs:element>
+            <xs:element name="config" type="tns:config" />
+            <xs:element name="configfile" type="tns:configFile" />
+            <xs:element name="feature" type="tns:dependency" />
+            <xs:element name="bundle" type="tns:bundle" />
+            <xs:element name="conditional" type="tns:conditional" />
+            <xs:element name="requirement" type="tns:requirement" />
+            <xs:element name="capability" type="tns:capability" />
+        </xs:choice>
+        <xs:attribute name="name" type="tns:featureName" use="required" />
+        <xs:attribute name="version" type="xs:string" default="0.0.0" />
+        <xs:attribute name="description" type="xs:string" />
+        <xs:attribute name="resolver" type="tns:resolver">
+            <xs:annotation>
+                <xs:documentation><![CDATA[
+Optional alternative resolver to use for determining the list of bundles to install for a given feature.
+                ]]>
+                </xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="install" type="tns:install">
+            <xs:annotation>
+                <xs:documentation><![CDATA[
+Marks if the feaute will be automatically started when thrown to the deploy folder.
+                ]]>
+                </xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="start-level" type="xs:int">
+             <xs:annotation>
+                <xs:documentation><![CDATA[
+Set this attribute to have an OSGi start level for this feature different
+from the default start level defined in Karaf's config.properties.
+                ]]>
+                </xs:documentation>
+             </xs:annotation>
+         </xs:attribute>
+    </xs:complexType>
+
+    <xs:complexType name="conditional">
+        <xs:annotation>
+            <xs:documentation><![CDATA[
+Definition of the Conditional.
+            ]]></xs:documentation>
+        </xs:annotation>
+        <xs:choice minOccurs="0" maxOccurs="unbounded">
+            <xs:element name="config" type="tns:config" />
+            <xs:element name="configfile" type="tns:configFile" />
+            <xs:element name="feature" type="tns:dependency" />
+            <xs:element name="bundle" type="tns:bundle" />
+            <xs:element name="condition" type="tns:dependency" minOccurs="0" maxOccurs="1" />
+        </xs:choice>
+    </xs:complexType>
+
+
+    <xs:complexType name="bundle">
+        <xs:annotation>
+            <xs:documentation><![CDATA[
+Deployable element to install.
+            ]]></xs:documentation>
+        </xs:annotation>
+        <xs:simpleContent>
+            <xs:extension base="xs:anyURI">
+                <xs:attribute name="start-level" type="xs:int">
+                    <xs:annotation>
+                        <xs:documentation><![CDATA[
+Set this attribute to have an OSGi start level for this bundle different
+from the default start level defined in the Karaf's config.properties.
+                        ]]>
+                        </xs:documentation>
+                    </xs:annotation>
+                </xs:attribute>
+                <xs:attribute name="start" type="xs:boolean" default="true">
+                    <xs:annotation>
+                        <xs:documentation><![CDATA[
+If false, leaves bundle in resolved state rather than the default active state.
+                        ]]>
+                        </xs:documentation>
+                    </xs:annotation>
+                </xs:attribute>
+                <xs:attribute name="dependency" type="xs:boolean">
+                    <xs:annotation>
+                        <xs:documentation><![CDATA[
+Mark this bundle as a dependency for the resolver.
+                        ]]>
+                        </xs:documentation>
+                    </xs:annotation>
+                </xs:attribute>
+            </xs:extension>
+        </xs:simpleContent>
+    </xs:complexType>
+
+    <xs:complexType name="dependency">
+        <xs:annotation>
+            <xs:documentation><![CDATA[
+Dependency of feature.
+            ]]></xs:documentation>
+        </xs:annotation>
+        <xs:simpleContent>
+            <xs:extension base="tns:featureName">
+                <xs:attribute name="version" type="xs:string" default="0.0.0" />
+            </xs:extension>
+        </xs:simpleContent>
+    </xs:complexType>
+
+    <xs:complexType name="config">
+        <xs:annotation>
+            <xs:documentation><![CDATA[
+Configuration entries which should be created during feature installation. This
+configuration may be used with OSGi Configuration Admin. The element content is
+read in as a properties file.
+            ]]></xs:documentation>
+        </xs:annotation>
+        <xs:simpleContent>
+            <xs:extension base="xs:string">
+                <xs:attribute name="name" type="xs:string" use="required" />
+            </xs:extension>
+        </xs:simpleContent>
+    </xs:complexType>
+
+    <xs:complexType name="configFile">
+        <xs:annotation>
+            <xs:documentation><![CDATA[
+Additional configuration files which should be created during feature installation.
+            ]]></xs:documentation>
+        </xs:annotation>
+        <xs:simpleContent>
+            <xs:extension base="xs:anyURI">
+                <xs:attribute name="finalname" type="xs:string" use="required">
+                    <xs:annotation>
+                        <xs:documentation><![CDATA[
+The final destination path and name for the configuration file.
+                        ]]></xs:documentation>
+                    </xs:annotation>
+                </xs:attribute>
+                <xs:attribute name="override" type="xs:boolean">
+                    <xs:annotation>
+                        <xs:documentation><![CDATA[
+If the configFile already exists at the finalname location, whether or not to replace it.
+                        ]]></xs:documentation>
+                    </xs:annotation>
+                </xs:attribute>
+
+            </xs:extension>
+        </xs:simpleContent>
+    </xs:complexType>
+
+    <xs:complexType name="requirement">
+        <xs:annotation>
+            <xs:documentation><![CDATA[
+Additional requirements of this feature.
+            ]]></xs:documentation>
+        </xs:annotation>
+        <xs:simpleContent>
+            <xs:extension base="xs:string">
+            </xs:extension>
+        </xs:simpleContent>
+    </xs:complexType>
+
+    <xs:complexType name="capability">
+        <xs:annotation>
+            <xs:documentation><![CDATA[
+Additional capability of this feature.
+            ]]></xs:documentation>
+        </xs:annotation>
+        <xs:simpleContent>
+            <xs:extension base="xs:string">
+            </xs:extension>
+        </xs:simpleContent>
+    </xs:complexType>
+
+    <xs:simpleType name="featureName">
+        <xs:annotation>
+            <xs:documentation><![CDATA[
+Feature name should be non empty string.
+            ]]></xs:documentation>
+        </xs:annotation>
+        <xs:restriction base="xs:string">
+            <xs:minLength value="1" />
+        </xs:restriction>
+    </xs:simpleType>
+
+    <xs:simpleType name="resolver">
+        <xs:annotation>
+            <xs:documentation><![CDATA[
+Resolver to use. Karaf will look for OSGi service which have following properties:
+objectClass: org.apache.karaf.features.Resolver
+name: the value
+            ]]></xs:documentation>
+        </xs:annotation>
+        <xs:restriction base="xs:string">
+            <xs:minLength value="1" />
+        </xs:restriction>
+    </xs:simpleType>
+    <xs:simpleType name="install">
+        <xs:annotation>
+            <xs:documentation><![CDATA[
+Installation mode. Can be either manual or auto. Specifies whether the feature should be automatically installed when
+dropped inside the deploy folder. Note: This attribute doesn't affect feature descriptors that are installed from the
+command line or as part of the org.apache.karaf.features.cfg.
+            ]]></xs:documentation>
+        </xs:annotation>
+        <xs:restriction base="xs:string">
+            <xs:minLength value="1" />
+        </xs:restriction>
+    </xs:simpleType>
+    <xs:element name="features" type="tns:features" />
+
+</xs:schema>

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/src/test/java/org/apache/karaf/features/ConditionalTest.java
----------------------------------------------------------------------
diff --git a/features/src/test/java/org/apache/karaf/features/ConditionalTest.java b/features/src/test/java/org/apache/karaf/features/ConditionalTest.java
new file mode 100644
index 0000000..d5e7e46
--- /dev/null
+++ b/features/src/test/java/org/apache/karaf/features/ConditionalTest.java
@@ -0,0 +1,47 @@
+/*
+ * 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.karaf.features;
+
+import junit.framework.TestCase;
+import org.apache.karaf.features.internal.service.RepositoryImpl;
+
+
+public class ConditionalTest extends TestCase {
+
+    public void testLoad() throws Exception {
+        RepositoryImpl r = new RepositoryImpl(getClass().getResource("internal/service/f06.xml").toURI());
+        // Check repo
+        Feature[] features = r.getFeatures();
+        assertNotNull(features);
+        assertEquals(1, features.length);
+        Feature feature = features[0];
+
+        assertNotNull(feature.getConditional());
+        assertEquals(1,feature.getConditional().size());
+
+        Conditional conditional = feature.getConditional().get(0);
+        assertNotNull(conditional.getCondition());
+        assertEquals(1,conditional.getCondition().size());
+        Dependency dependency = conditional.getCondition().get(0);
+        assertNotNull(dependency);
+        assertEquals(dependency.getName(),"http");
+        assertNotNull(conditional.getBundles());
+        assertEquals(1, feature.getConditional().get(0).getBundles().size());
+
+        String wrapperName = "my6/1.5.3-beta-3".replaceAll("[^A-Za-z0-9 ]", "_");
+    }
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/src/test/java/org/apache/karaf/features/FeatureTest.java
----------------------------------------------------------------------
diff --git a/features/src/test/java/org/apache/karaf/features/FeatureTest.java b/features/src/test/java/org/apache/karaf/features/FeatureTest.java
new file mode 100644
index 0000000..b7d4c27
--- /dev/null
+++ b/features/src/test/java/org/apache/karaf/features/FeatureTest.java
@@ -0,0 +1,32 @@
+/*
+ * 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.karaf.features;
+
+import junit.framework.TestCase;
+
+public class FeatureTest extends TestCase {
+	
+	public void testValueOf() {
+		Feature feature = org.apache.karaf.features.internal.model.Feature.valueOf("name" + org.apache.karaf.features.internal.model.Feature.SPLIT_FOR_NAME_AND_VERSION + "version");
+		assertEquals(feature.getName(), "name");
+		assertEquals(feature.getVersion(), "version");
+		feature = org.apache.karaf.features.internal.model.Feature.valueOf("name");
+		assertEquals(feature.getName(), "name");
+		assertEquals(feature.getVersion(), org.apache.karaf.features.internal.model.Feature.DEFAULT_VERSION);
+	}
+	
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/src/test/java/org/apache/karaf/features/FeaturesServiceTest.java
----------------------------------------------------------------------
diff --git a/features/src/test/java/org/apache/karaf/features/FeaturesServiceTest.java b/features/src/test/java/org/apache/karaf/features/FeaturesServiceTest.java
new file mode 100644
index 0000000..a74e3d0
--- /dev/null
+++ b/features/src/test/java/org/apache/karaf/features/FeaturesServiceTest.java
@@ -0,0 +1,429 @@
+/*
+ * 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.karaf.features;
+
+import static org.easymock.EasyMock.eq;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
+import static org.easymock.EasyMock.reset;
+import static org.easymock.EasyMock.verify;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.PrintWriter;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.EnumSet;
+import java.util.List;
+import java.util.concurrent.CopyOnWriteArraySet;
+
+import org.apache.karaf.features.internal.service.FeaturesServiceImpl;
+import org.apache.karaf.features.internal.service.StateStorage;
+import org.easymock.EasyMock;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+
+public class FeaturesServiceTest extends TestBase {
+    private static final String FEATURE_WITH_INVALID_BUNDLE = "<features name='test' xmlns='http://karaf.apache.org/xmlns/features/v1.0.0'>"
+            + "  <feature name='f1'><bundle>%s</bundle><bundle>zfs:unknown</bundle></feature>"
+            + "  <feature name='f2'><bundle>%s</bundle></feature>"
+            + "</features>";
+
+    File dataFile;
+
+    @Before
+    public void setUp() throws IOException {
+        dataFile = File.createTempFile("features", null, null);
+    }
+    
+    private URI createTempRepo(String repoContent, Object ... variables) throws IOException {
+        File tmp = File.createTempFile("karaf", ".feature");
+        PrintWriter pw = new PrintWriter(new FileWriter(tmp));
+        pw.printf(repoContent, variables);
+        pw.close();
+        return tmp.toURI();
+    }
+
+    /*
+       TODO: migrate those tests
+
+    @Test
+    public void testInstallFeature() throws Exception {
+        URI uri = createTempRepo(
+                "<features name='test' xmlns='http://karaf.apache.org/xmlns/features/v1.0.0'>" 
+                + "  <feature name='f1'><bundle start='true'>bundle-f1</bundle></feature>"
+                + "</features>");
+
+        BundleManager bundleManager = EasyMock.createMock(BundleManager.class);
+        Bundle installedBundle = createDummyBundle(12345L, "bundle-f1", headers());
+        FeaturesServiceImpl svc = testAddRepository("bundle-f1", uri, bundleManager, installedBundle);
+        
+        reset(bundleManager);
+        
+        expect(bundleManager.installBundleIfNeeded(eq("bundle-f1"), eq(0), eq((String)null))).andReturn(new BundleInstallerResult(installedBundle, true));
+        expect(bundleManager.getDataFile(EasyMock.anyObject(String.class))).andReturn(dataFile);
+        ignoreRefreshes(bundleManager);
+        replay(bundleManager);
+        svc.installFeature("f1", org.apache.karaf.features.internal.model.Feature.DEFAULT_VERSION, EnumSet.of(FeaturesService.Option.NoAutoRefreshBundles));
+        verify(bundleManager);
+        
+        Feature[] installed = svc.listInstalledFeatures();
+        assertEquals(1, installed.length);
+        assertEquals("f1", installed[0].getName());
+    }
+
+    private FeaturesServiceImpl testAddRepository(String name, URI uri, BundleManager bundleManager,
+            Bundle installedBundle) throws IOException, BundleException, Exception {
+        expect(bundleManager.getDataFile(EasyMock.anyObject(String.class))).andReturn(dataFile);
+        expect(bundleManager.installBundleIfNeeded(eq(name), eq(0), eq((String)null))).andReturn(new BundleInstallerResult(installedBundle, true)).anyTimes();
+
+        replay(bundleManager);
+        FeaturesServiceImpl svc = new FeaturesServiceImpl(bundleManager);
+        svc.addRepository(uri);
+        Repository[] repositories = svc.listRepositories();
+        verify(bundleManager);
+
+        assertNotNull(repositories);
+        assertEquals(1, repositories.length);
+        assertNotNull(repositories[0]);
+        Feature[] features = repositories[0].getFeatures();
+        assertNotNull(features);
+        assertEquals(1, features.length);
+        assertNotNull(features[0]);
+        assertEquals("f1", features[0].getName());
+        assertNotNull(features[0].getDependencies());
+        assertEquals(0, features[0].getDependencies().size());
+        assertNotNull(features[0].getBundles());
+        assertEquals(1, features[0].getBundles().size());
+        assertEquals(name, features[0].getBundles().get(0).getLocation());
+        assertTrue(features[0].getBundles().get(0).isStart());
+        return svc;
+    }
+
+    @SuppressWarnings("unchecked")
+    @Test
+    public void testUninstallFeatureWithTwoVersions() throws Exception {
+        URI uri  = createTempRepo("<features name='test' xmlns='http://karaf.apache.org/xmlns/features/v1.0.0'>"
+                + "  <feature name='f1' version='0.1'><bundle>bundle-0.1</bundle></feature>"
+                + "  <feature name='f1' version='0.2'><bundle>bundle-0.1</bundle></feature>" 
+                + "</features>");
+
+        Bundle bundlef101 = createDummyBundle(12345L, "bundle-0.1", headers());
+
+        BundleManager bundleManager = EasyMock.createMock(BundleManager.class);
+        BundleContext bundleContext = EasyMock.createMock(BundleContext.class);
+        expect(bundleManager.getDataFile(EasyMock.anyObject(String.class))).andReturn(dataFile).anyTimes();
+        expect(bundleManager.installBundleIfNeeded("bundle-0.1", 0, null)).andReturn(new BundleInstallerResult(bundlef101, true));
+        expect(bundleManager.installBundleIfNeeded("bundle-0.1", 0, null)).andReturn(new BundleInstallerResult(bundlef101, false));
+        expect(bundleManager.getBundleContext()).andReturn(bundleContext);
+        ignoreRefreshes(bundleManager);
+        bundleManager.uninstall(Collections.EMPTY_LIST, true);
+        EasyMock.expectLastCall().times(2);
+        
+        
+        replay(bundleManager);
+        FeaturesServiceImpl svc = new FeaturesServiceImpl(bundleManager);
+        svc.addRepository(uri);
+
+        try {
+            svc.uninstallFeature("f1");
+            fail("Uninstall should have failed as feature is not installed");
+        } catch (Exception e) {
+            // ok
+        }
+
+        svc.installFeature("f1", "0.1", EnumSet.of(FeaturesService.Option.NoAutoRefreshBundles));
+        svc.installFeature("f1", "0.2", EnumSet.of(FeaturesService.Option.NoAutoRefreshBundles));
+
+        try {
+            svc.uninstallFeature("f1");
+            fail("Uninstall should have failed as feature is installed in multiple versions");
+        } catch (Exception e) {
+            // ok
+        }
+
+        svc.uninstallFeature("f1", "0.1");
+        svc.uninstallFeature("f1");
+        verify(bundleManager);
+    }    
+    
+    @Test
+    public void testAddAndRemoveRepository() throws Exception {
+        URI uri = createTempRepo("<features name='test' xmlns='http://karaf.apache.org/xmlns/features/v1.0.0'>"
+                + "  <feature name='f1' version='0.1'><bundle>bundle-f1-0.1</bundle></feature>"
+                + "</features>");
+
+        BundleManager bundleManager = EasyMock.createMock(BundleManager.class);
+        expect(bundleManager.getDataFile(EasyMock.<String>anyObject())).andReturn(dataFile).anyTimes();
+
+        replay(bundleManager);
+        FeaturesServiceImpl svc = new FeaturesServiceImpl(bundleManager);
+        EasyMock.verify(bundleManager);
+
+        svc.addRepository(uri);                                                     
+        svc.removeRepository(uri);
+        verify(bundleManager);
+    }
+
+    // Tests install of a Repository that includes a feature
+    // with a feature dependency
+    // The dependant feature is in the same repository
+    // Tests uninstall of features
+    @SuppressWarnings("unchecked")
+    @Test
+    public void testInstallFeatureWithDependantFeatures() throws Exception {
+        URI uri = createTempRepo("<features name='test' xmlns='http://karaf.apache.org/xmlns/features/v1.0.0'>"
+                                 + "  <feature name='f1' version='0.1'><feature version='0.1'>f2</feature><bundle>bundle-f1-0.1</bundle></feature>"
+                                 + "  <feature name='f2' version='0.1'><bundle>bundle-f2-0.1</bundle></feature>"
+                                 + "</features>");
+
+        BundleManager bundleManager = EasyMock.createMock(BundleManager.class);
+        BundleContext bundleContext = EasyMock.createMock(BundleContext.class);
+        Bundle bundlef101 = createDummyBundle(12345L, "bundle-f1-0.1", headers());
+        Bundle bundlef201 = createDummyBundle(54321L, "bundle-f2-0.1", headers());
+        expect(bundleManager.getDataFile(EasyMock.<String> anyObject())).andReturn(dataFile).anyTimes();
+        expect(bundleManager.installBundleIfNeeded("bundle-f1-0.1", 0, null))
+            .andReturn(new BundleInstallerResult(bundlef101, true));
+        expect(bundleManager.installBundleIfNeeded("bundle-f2-0.1", 0, null))
+            .andReturn(new BundleInstallerResult(bundlef201, true));
+        expect(bundleManager.getBundleContext()).andReturn(bundleContext).anyTimes();
+        expect(bundleContext.getBundle(12345)).andReturn(bundlef101).anyTimes();
+        ignoreRefreshes(bundleManager);
+        bundleManager.uninstall(Collections.EMPTY_LIST, true);
+       
+        EasyMock.expectLastCall().anyTimes();
+        replay(bundleManager);
+        
+        FeaturesServiceImpl svc = new FeaturesServiceImpl(bundleManager);
+        svc.addRepository(uri);
+        svc.installFeature("f1", "0.1");
+        svc.uninstallFeature("f1", "0.1");
+        verify(bundleManager);
+
+    }
+
+    @SuppressWarnings("unchecked")
+    private BundleManager prepareBundleManagerForInstallUninstall(String bundleUri, String bundlename) throws Exception {
+        BundleManager bundleManager = EasyMock.createMock(BundleManager.class);
+        BundleContext bundleContext = EasyMock.createMock(BundleContext.class);
+        Bundle installedBundle = createDummyBundle(12345L, bundlename, headers());
+        expect(bundleManager.getDataFile(EasyMock.<String>anyObject())).andReturn(dataFile).anyTimes();
+        expect(bundleManager.installBundleIfNeeded(bundleUri, 0, null)).andReturn(new BundleInstallerResult(installedBundle, true));
+        expect(bundleManager.getBundleContext()).andReturn(bundleContext);
+        ignoreRefreshes(bundleManager);
+        bundleManager.uninstall(Collections.EMPTY_LIST, true);
+        EasyMock.expectLastCall().times(2);
+        return bundleManager;
+    }
+
+    @Test
+    public void testInstallFeatureWithDependantFeaturesAndVersionWithoutPreinstall() throws Exception {
+        URI uri = createTempRepo("<features name='test' xmlns='http://karaf.apache.org/xmlns/features/v1.0.0'>"
+                + "  <feature name='f1' version='0.1'><feature version='0.1'>f2</feature></feature>"
+                + "  <feature name='f2' version='0.1'><bundle>bundle-0.1</bundle></feature>"
+                + "  <feature name='f2' version='0.2'><bundle>bundle-0.2</bundle></feature>"
+                + "</features>");
+
+        BundleManager bundleManager = prepareBundleManagerForInstallUninstall("bundle-0.1", "bundle-0.1");
+
+        replay(bundleManager);
+        FeaturesServiceImpl svc = new FeaturesServiceImpl(bundleManager);
+        svc.addRepository(uri);
+        svc.installFeature("f1", "0.1");
+        svc.uninstallFeature("f1", "0.1");
+        svc.uninstallFeature("f2", "0.1");
+        verify(bundleManager);
+    }
+
+    @Test
+    public void testInstallFeatureWithDependantFeaturesAndNoVersionWithoutPreinstall() throws Exception {
+        URI uri = createTempRepo("<features name='test' xmlns='http://karaf.apache.org/xmlns/features/v1.0.0'>"
+                + "  <feature name='f1' version='0.1'><feature>f2</feature></feature>"
+                + "  <feature name='f2' version='0.1'><bundle>bundle-0.1</bundle></feature>"
+                + "  <feature name='f2' version='0.2'><bundle>bundle-0.2</bundle></feature>"
+                + "</features>");
+
+        BundleManager bundleManager = prepareBundleManagerForInstallUninstall("bundle-0.2", "bundle-0.2");
+
+        replay(bundleManager);
+        FeaturesServiceImpl svc = new FeaturesServiceImpl(bundleManager);
+        svc.addRepository(uri);
+        svc.installFeature("f1", "0.1");
+        svc.uninstallFeature("f1", "0.1");
+        svc.uninstallFeature("f2", "0.2");
+        verify(bundleManager);
+    }
+
+    @SuppressWarnings("unchecked")
+    @Test
+    public void testInstallFeatureWithDependantFeaturesAndRangeWithoutPreinstall() throws Exception {
+        URI uri = createTempRepo("<features name='test' xmlns='http://karaf.apache.org/xmlns/features/v1.0.0'>"
+                + "  <feature name='f1' version='0.1'><feature version='[0.1,0.3)'>f2</feature></feature>"
+                + "  <feature name='f2' version='0.1'><bundle>bundle-0.1</bundle></feature>"
+                + "  <feature name='f2' version='0.2'><bundle>bundle-0.2</bundle></feature>"
+                + "</features>");
+
+        BundleManager bundleManager = EasyMock.createMock(BundleManager.class);
+        BundleContext bundleContext = EasyMock.createMock(BundleContext.class);
+        Bundle bundleVer02 = createDummyBundle(54321L, "bundleVer02", headers());
+        expect(bundleManager.getDataFile(EasyMock.<String>anyObject())).andReturn(dataFile).anyTimes();
+        expect(bundleManager.installBundleIfNeeded("bundle-0.2", 0, null)).andReturn(new BundleInstallerResult(bundleVer02, true));
+        expect(bundleManager.getBundleContext()).andReturn(bundleContext);
+        ignoreRefreshes(bundleManager);
+        bundleManager.uninstall(Collections.EMPTY_LIST, true);
+
+        EasyMock.expectLastCall().times(2);
+
+        replay(bundleManager);
+        FeaturesServiceImpl svc = new FeaturesServiceImpl(bundleManager);
+        svc.addRepository(uri);
+        svc.installFeature("f1", "0.1");
+        svc.uninstallFeature("f1", "0.1");
+        svc.uninstallFeature("f2", "0.2");
+        verify(bundleManager);
+    }
+
+    @SuppressWarnings("unchecked")
+    @Test
+    public void testInstallFeatureWithDependantFeaturesAndRangeWithPreinstall() throws Exception {
+        String bundleVer01Uri = "bundle-0.1";
+        String bundleVer02Uri = "bundle-0.2";
+
+        URI uri = createTempRepo("<features name='test' xmlns='http://karaf.apache.org/xmlns/features/v1.0.0'>"
+                + "<feature name='f1' version='0.1'><feature version='[0.1,0.3)'>f2</feature></feature>"
+                + "  <feature name='f2' version='0.1'><bundle>%s</bundle></feature>"
+                + "  <feature name='f2' version='0.2'><bundle>%s</bundle></feature>"
+                + "</features>", bundleVer01Uri, bundleVer02Uri);
+        
+        BundleContext bundleContext = EasyMock.createMock(BundleContext.class);
+        expect(bundleContext.getBundles()).andReturn(new Bundle[0]);
+        replay(bundleContext);
+
+        FeaturesServiceImpl svc = new FeaturesServiceImpl(null, bundleContext, new Storage(), null, null, null, null);
+        svc.addRepository(uri);
+        svc.installFeature("f2", "0.1");
+        svc.installFeature("f1", "0.1");
+        svc.uninstallFeature("f1", "0.1");
+        svc.uninstallFeature("f2", "0.1");
+
+        verify(bundleContext);
+    }
+    */
+
+    @Test
+    public void testGetFeaturesShouldHandleDifferentVersionPatterns() throws Exception {
+        URI uri = createTempRepo("<features name='test' xmlns='http://karaf.apache.org/xmlns/features/v1.0.0'>"
+                + "  <feature name='f1' version='0.1'><feature version='[0.1,0.3)'>f2</feature></feature>"
+                + "  <feature name='f2' version='0.1'><bundle>bundle1</bundle></feature>"
+                + "  <feature name='f2' version='0.2'><bundle>bundle2</bundle></feature>"
+                + "</features>");
+
+        FeaturesServiceImpl svc = new FeaturesServiceImpl(null, null, new Storage(), null, null, null, null, null, null, null);
+        svc.addRepository(uri);
+
+        assertEquals(feature("f2", "0.2"), svc.getFeature("f2", "[0.1,0.3)"));
+        assertEquals(feature("f2", "0.2"), svc.getFeature("f2", "0.0.0"));
+        assertEquals(feature("f2", "0.2"), svc.getFeature("f2", "0.2"));
+        assertNull(svc.getFeature("f2", "0.3"));
+    }
+
+    @Test
+    public void testInstallBatchFeatureWithFailure() throws Exception {
+        String bundle1Uri = "file:bundle1";
+        String bundle2Uri = "file:bundle2";
+
+        URI uri = createTempRepo(FEATURE_WITH_INVALID_BUNDLE, bundle1Uri, bundle2Uri);
+        
+        BundleContext bundleContext = EasyMock.createMock(BundleContext.class);
+        expect(bundleContext.getBundles()).andReturn(new Bundle[0]);
+        replay(bundleContext);
+
+        FeaturesServiceImpl svc = new FeaturesServiceImpl(null, bundleContext, new Storage(), null, null, null, null, null, null, null);
+        svc.addRepository(uri);
+        try {
+            List<String> features = new ArrayList<String>();
+            for (Feature feature : svc.listFeatures()) {
+                features.add(feature.getId());
+            }
+            Collections.reverse(features);
+            svc.installFeatures(new CopyOnWriteArraySet<String>(features),
+                                EnumSet.noneOf(FeaturesService.Option.class));
+            fail("Call should have thrown an exception");
+        } catch (MalformedURLException e) {
+        }
+        verify(bundleContext);
+    }
+
+    /**
+     * This test checks schema validation of submited uri.
+     */
+    @Test
+    public void testSchemaValidation() throws Exception {
+        URI uri = createTempRepo("<features name='test' xmlns='http://karaf.apache.org/xmlns/features/v1.0.0'>"
+                + "  <featur><bundle>somebundle</bundle></featur></features>");
+
+        FeaturesServiceImpl svc = new FeaturesServiceImpl(null, null, new Storage(), null, null, null, null, null, null, null);
+        try {
+            svc.addRepository(uri);
+            fail("exception expected");
+        } catch (Exception e) {
+            assertTrue(e.getMessage().contains("Unable to validate"));
+        }
+    }
+
+    /**
+     * This test checks feature service behavior with old, non namespaced descriptor.
+     */
+    @Test
+    public void testLoadOldFeatureFile() throws Exception {
+        URI uri = createTempRepo("<features name='test' xmlns='http://karaf.apache.org/xmlns/features/v1.0.0'>"
+                + "  <feature name='f1'><bundle>file:bundle1</bundle><bundle>file:bundle2</bundle></feature>"
+                + "</features>");
+
+        FeaturesServiceImpl svc = new FeaturesServiceImpl(null, null, new Storage(), null, null, null, null, null, null, null);
+        svc.addRepository(uri);
+        Feature feature = svc.getFeature("f1");
+        Assert.assertNotNull("No feature named fi found", feature);        
+        List<BundleInfo> bundles = feature.getBundles();
+        Assert.assertEquals(2, bundles.size());
+    }
+
+    static class Storage extends StateStorage {
+        @Override
+        protected InputStream getInputStream() throws IOException {
+            return null;
+        }
+        @Override
+        protected OutputStream getOutputStream() throws IOException {
+            return null;
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/src/test/java/org/apache/karaf/features/RepositoryTest.java
----------------------------------------------------------------------
diff --git a/features/src/test/java/org/apache/karaf/features/RepositoryTest.java b/features/src/test/java/org/apache/karaf/features/RepositoryTest.java
new file mode 100644
index 0000000..164dc79
--- /dev/null
+++ b/features/src/test/java/org/apache/karaf/features/RepositoryTest.java
@@ -0,0 +1,140 @@
+/*
+ * 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.karaf.features;
+
+import java.net.URI;
+
+import junit.framework.TestCase;
+import org.apache.karaf.features.internal.resolver.FeatureResource;
+import org.apache.karaf.features.internal.service.RepositoryImpl;
+import org.osgi.resource.Resource;
+
+
+public class RepositoryTest extends TestCase {
+
+    public void testLoad() throws Exception {
+        RepositoryImpl r = new RepositoryImpl(getClass().getResource("repo1.xml").toURI());
+        // Check repo
+        URI[] repos = r.getRepositories();
+        assertNotNull(repos);
+        assertEquals(1, repos.length);
+        assertEquals(URI.create("urn:r1"), repos[0]);
+        // Check features
+        Feature[] features = r.getFeatures();
+        assertNotNull(features);
+        assertEquals(3, features.length);
+        assertNotNull(features[0]);
+        assertEquals("f1", features[0].getName());
+        assertNotNull(features[0].getConfigurations());
+        assertEquals(1, features[0].getConfigurations().size());
+        assertNotNull(features[0].getConfigurations().get("c1"));
+        assertEquals(1, features[0].getConfigurations().get("c1").size());
+        assertEquals("v", features[0].getConfigurations().get("c1").get("k"));
+        assertNotNull(features[0].getDependencies());
+        assertEquals(0, features[0].getDependencies().size());
+        assertNotNull(features[0].getBundles());
+        assertEquals(2, features[0].getBundles().size());
+        assertEquals("b1", features[0].getBundles().get(0).getLocation());
+        assertEquals("b2", features[0].getBundles().get(1).getLocation());
+        assertNotNull(features[1]);
+        assertEquals("f2", features[1].getName());
+        assertNotNull(features[1].getConfigurations());
+        assertEquals(0, features[1].getConfigurations().size());
+        assertNotNull(features[1].getDependencies());
+        assertEquals(1, features[1].getDependencies().size());
+        assertEquals("f1" + org.apache.karaf.features.internal.model.Feature.SPLIT_FOR_NAME_AND_VERSION + org.apache.karaf.features.internal.model.Feature.DEFAULT_VERSION, features[1].getDependencies().get(0).toString());
+        assertNotNull(features[1].getBundles());
+        assertEquals(1, features[1].getBundles().size());
+        assertEquals("b3", features[1].getBundles().get(0).getLocation());
+        assertEquals("f3", features[2].getName());
+        assertNotNull(features[2].getConfigurationFiles());
+        assertEquals(1, features[2].getConfigurationFiles().size());
+        assertEquals("cf1", features[2].getConfigurationFiles().get(0).getFinalname());
+        assertEquals(true, features[2].getConfigurationFiles().get(0).isOverride());
+        assertEquals("cfloc", features[2].getConfigurationFiles().get(0).getLocation());
+    }
+
+    public void testLoadFormattedRepo() throws Exception {
+        RepositoryImpl r = new RepositoryImpl(getClass().getResource("repo2.xml").toURI());
+        // Check repo
+        URI[] repos = r.getRepositories();
+        assertNotNull(repos);
+        assertEquals(1, repos.length);
+        assertEquals(URI.create("urn:r1"), repos[0]);
+        // Check features
+        Feature[] features = r.getFeatures();
+        assertNotNull(features);
+        assertEquals(3, features.length);
+        assertNotNull(features[0]);
+        assertEquals("f1", features[0].getName());
+        assertNotNull(features[0].getConfigurations());
+        assertEquals(1, features[0].getConfigurations().size());
+        assertNotNull(features[0].getConfigurations().get("c1"));
+        assertEquals(1, features[0].getConfigurations().get("c1").size());
+        assertEquals("v", features[0].getConfigurations().get("c1").get("k"));
+        assertNotNull(features[0].getDependencies());
+        assertEquals(0, features[0].getDependencies().size());
+        assertNotNull(features[0].getBundles());
+        assertEquals(2, features[0].getBundles().size());
+        assertEquals("b1", features[0].getBundles().get(0).getLocation());
+        assertEquals("b2", features[0].getBundles().get(1).getLocation());
+        assertNotNull(features[1]);
+        assertEquals("f2", features[1].getName());
+        assertNotNull(features[1].getConfigurations());
+        assertEquals(0, features[1].getConfigurations().size());
+        assertNotNull(features[1].getDependencies());
+        assertEquals(1, features[1].getDependencies().size());
+        assertEquals("f1" + org.apache.karaf.features.internal.model.Feature.SPLIT_FOR_NAME_AND_VERSION + org.apache.karaf.features.internal.model.Feature.DEFAULT_VERSION, features[1].getDependencies().get(0).toString());
+        assertNotNull(features[1].getBundles());
+        assertEquals(1, features[1].getBundles().size());
+        assertEquals("b3", features[1].getBundles().get(0).getLocation());
+        assertEquals("f3", features[2].getName());
+        assertNotNull(features[2].getConfigurationFiles());
+        assertEquals(1, features[2].getConfigurationFiles().size());
+        assertEquals("cf1", features[2].getConfigurationFiles().get(0).getFinalname());
+        assertEquals(true, features[2].getConfigurationFiles().get(0).isOverride());
+        assertEquals("cfloc", features[2].getConfigurationFiles().get(0).getLocation());
+    }
+
+    public void testLoadRepoWithCapabilitiesAndRequirement() throws Exception {
+        RepositoryImpl r = new RepositoryImpl(getClass().getResource("repo3.xml").toURI());
+        // Check features
+        Feature[] features = r.getFeatures();
+        assertNotNull(features);
+        assertEquals(1, features.length);
+        assertNotNull(features[0]);
+        assertEquals("f1", features[0].getName());
+        assertEquals(1, features[0].getCapabilities().size());
+        assertEquals("cap", features[0].getCapabilities().get(0).getValue().trim());
+        assertEquals(1, features[0].getRequirements().size());
+        assertEquals("req", features[0].getRequirements().get(0).getValue().trim());
+
+        Resource res = FeatureResource.build(features[0], null, null);
+        assertEquals(1, res.getCapabilities("cap").size());
+        assertEquals(1, res.getRequirements("req").size());
+    }
+
+    public void testShowWrongUriInException() throws Exception {
+        String uri = "src/test/resources/org/apache/karaf/shell/features/repo1.xml";
+        RepositoryImpl r = new RepositoryImpl(new URI(uri));
+        try {
+            r.load();
+        } catch (Exception e) {
+            assertTrue(e.getMessage().contains(uri));
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/src/test/java/org/apache/karaf/features/TestBase.java
----------------------------------------------------------------------
diff --git a/features/src/test/java/org/apache/karaf/features/TestBase.java b/features/src/test/java/org/apache/karaf/features/TestBase.java
new file mode 100644
index 0000000..ac8f3d9
--- /dev/null
+++ b/features/src/test/java/org/apache/karaf/features/TestBase.java
@@ -0,0 +1,105 @@
+/*
+ * 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.karaf.features;
+
+import java.util.Arrays;
+import java.util.Dictionary;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Hashtable;
+import java.util.Map;
+import java.util.Set;
+
+import org.easymock.EasyMock;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.startlevel.BundleStartLevel;
+
+import static java.util.Arrays.asList;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
+
+public class TestBase {
+    public Bundle createDummyBundle(long id, final String symbolicName, Dictionary<String,String> headers) {
+        Bundle bundle = EasyMock.createNiceMock(Bundle.class);
+        
+        // Be aware that this means all bundles are treated as different
+        expect(bundle.compareTo(EasyMock.<Bundle>anyObject())).andReturn(1).anyTimes();
+
+        expect(bundle.getBundleId()).andReturn(id).anyTimes();
+        expect(bundle.getSymbolicName()).andReturn(symbolicName).anyTimes();
+        expect(bundle.getHeaders()).andReturn(headers).anyTimes();
+        BundleStartLevel sl = EasyMock.createMock(BundleStartLevel.class);
+        expect(sl.isPersistentlyStarted()).andReturn(true).anyTimes();
+        expect(bundle.adapt(BundleStartLevel.class)).andReturn(sl).anyTimes();
+        replay(bundle, sl);
+        return bundle;
+    }
+    
+    public Dictionary<String, String> headers(String ... keyAndHeader) {
+        Hashtable<String, String> headersTable = new Hashtable<String, String>();
+        int c=0;
+        while (c < keyAndHeader.length) {
+            String key = keyAndHeader[c++];
+            String value = keyAndHeader[c++];
+            headersTable.put(key, value);
+        }
+        return headersTable;
+    }
+    
+    public Map<String, Map<String, Feature>> features(Feature ... features) {
+        final Map<String, Map<String, Feature>> featuresMap = new HashMap<String, Map<String,Feature>>();
+        for (Feature feature : features) {
+            Map<String, Feature> featureVersion = getOrCreate(featuresMap, feature);
+            featureVersion.put(feature.getVersion(), feature);
+        }
+        return featuresMap;
+    }
+    
+    private Map<String, Feature> getOrCreate(final Map<String, Map<String, Feature>> featuresMap, Feature feature) {
+        Map<String, Feature> featureVersion = featuresMap.get(feature.getName());
+        if (featureVersion == null) {
+            featureVersion = new HashMap<String, Feature>();
+            featuresMap.put(feature.getName(), featureVersion);
+        }
+        return featureVersion;
+    }
+
+    public Feature feature(String name) {
+        return feature(name, null);
+    }
+
+    public Feature feature(String name, String version) {
+        return new org.apache.karaf.features.internal.model.Feature(name, version);
+    }
+    
+    public Set<Bundle> setOf(Bundle ... elements) {
+        return new HashSet<Bundle>(Arrays.asList(elements));
+    }
+    
+    public Set<Long> setOf(Long ... elements) {
+        return new HashSet<Long>(Arrays.asList(elements));
+    }
+    
+    public Set<String> setOf(String ... elements) {
+        return new HashSet<String>(asList(elements));
+    }
+    
+    public Set<Feature> setOf(Feature ... elements) {
+        return new HashSet<Feature>(Arrays.asList(elements));
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/src/test/java/org/apache/karaf/features/internal/service/BootFeaturesInstallerTest.java
----------------------------------------------------------------------
diff --git a/features/src/test/java/org/apache/karaf/features/internal/service/BootFeaturesInstallerTest.java b/features/src/test/java/org/apache/karaf/features/internal/service/BootFeaturesInstallerTest.java
new file mode 100644
index 0000000..31f4f29
--- /dev/null
+++ b/features/src/test/java/org/apache/karaf/features/internal/service/BootFeaturesInstallerTest.java
@@ -0,0 +1,93 @@
+/*
+ * 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.karaf.features.internal.service;
+
+import static java.util.Arrays.asList;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
+import static org.junit.Assert.fail;
+
+import java.net.URI;
+import java.util.EnumSet;
+
+import org.apache.karaf.features.Feature;
+import org.apache.karaf.features.FeaturesService.Option;
+import org.apache.karaf.features.TestBase;
+import org.easymock.EasyMock;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class BootFeaturesInstallerTest extends TestBase {
+
+    @Test
+    @SuppressWarnings("unchecked")
+    public void testParser() {
+        BootFeaturesInstaller installer = new BootFeaturesInstaller(null, null, "", "", false);
+        Assert.assertEquals(asList(setOf("test1", "test2"),setOf("test3")), installer.parseBootFeatures("(test1, test2), test3"));
+        Assert.assertEquals(asList(setOf("test1", "test2", "test3")), installer.parseBootFeatures("test1, test2, test3"));
+    }
+    
+    @Test
+    public void testDefaultBootFeatures() throws Exception  {
+        FeaturesServiceImpl impl = EasyMock.createMock(FeaturesServiceImpl.class);
+
+        impl.installFeatures(setOf("config", "standard", "region"), EnumSet.of(Option.NoFailOnFeatureNotFound));
+        EasyMock.expectLastCall();
+
+        impl.bootDone();
+        EasyMock.expectLastCall();
+
+        replay(impl);
+        BootFeaturesInstaller bootFeatures = new BootFeaturesInstaller(null, impl, "", "config,standard,region", false);
+        bootFeatures.installBootFeatures();
+        EasyMock.verify(impl);        
+    }
+
+    @Test
+    public void testStagedBoot() throws Exception  {
+        FeaturesServiceImpl impl = EasyMock.createStrictMock(FeaturesServiceImpl.class);
+
+        impl.installFeatures(setOf("transaction"), EnumSet.of(Option.NoFailOnFeatureNotFound));
+        EasyMock.expectLastCall();
+        impl.installFeatures(setOf("ssh"), EnumSet.of(Option.NoFailOnFeatureNotFound));
+        EasyMock.expectLastCall();
+
+        impl.bootDone();
+        EasyMock.expectLastCall();
+
+        replay(impl);
+        BootFeaturesInstaller bootFeatures = new BootFeaturesInstaller(null, impl , "", "(transaction), ssh", false);
+        bootFeatures.installBootFeatures();
+        EasyMock.verify(impl);        
+    }
+
+    @Test
+    public void testStartDoesNotFailWithOneInvalidUri() throws Exception {
+        FeaturesServiceImpl impl = EasyMock.createStrictMock(FeaturesServiceImpl.class);
+        impl.addRepository(URI.create("mvn:inexistent/features/1.0/xml/features"));
+        EasyMock.expectLastCall().andThrow(new IllegalArgumentException());
+
+        impl.bootDone();
+        EasyMock.expectLastCall();
+
+        replay(impl);
+        BootFeaturesInstaller bootFeatures = new BootFeaturesInstaller(null, impl, "mvn:inexistent/features/1.0/xml/features", "", false);
+        bootFeatures.installBootFeatures();
+        EasyMock.verify(impl);
+    }
+
+}


[04/59] [abbrv] [KARAF-2852] Merge features/core and features/command

Posted by gn...@apache.org.
http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/src/main/java/org/apache/karaf/features/internal/service/BootFeaturesInstaller.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/service/BootFeaturesInstaller.java b/features/src/main/java/org/apache/karaf/features/internal/service/BootFeaturesInstaller.java
new file mode 100644
index 0000000..eaa9ba0
--- /dev/null
+++ b/features/src/main/java/org/apache/karaf/features/internal/service/BootFeaturesInstaller.java
@@ -0,0 +1,170 @@
+/*
+ * 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.karaf.features.internal.service;
+
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.EnumSet;
+import java.util.HashSet;
+import java.util.Hashtable;
+import java.util.List;
+import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.karaf.features.BootFinished;
+import org.apache.karaf.features.Feature;
+import org.apache.karaf.features.FeaturesService;
+import org.osgi.framework.BundleContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class BootFeaturesInstaller {
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(BootFeaturesInstaller.class);
+
+    public static String VERSION_PREFIX = "version=";
+
+    private final FeaturesServiceImpl featuresService;
+    private final BundleContext bundleContext;
+    private final String repositories;
+    private final String features;
+    private final boolean asynchronous;
+
+    /**
+     *
+     * @param features list of boot features separated by comma. Optionally contains ;version=x.x.x to specify a specific feature version
+     */
+    public BootFeaturesInstaller(BundleContext bundleContext,
+                                 FeaturesServiceImpl featuresService,
+                                 String repositories,
+                                 String features,
+                                 boolean asynchronous) {
+        this.bundleContext = bundleContext;
+        this.featuresService = featuresService;
+        this.repositories = repositories;
+        this.features = features;
+        this.asynchronous = asynchronous;
+    }
+
+    /**
+     * Install boot features
+     */
+    public void start() {
+        if (featuresService.isBootDone()) {
+            publishBootFinished();
+            return;
+        }
+        if (asynchronous) {
+            new Thread("Initial Features Provisioning") {
+                public void run() {
+                    installBootFeatures();
+                }
+            }.start();
+        } else {
+            installBootFeatures();
+        }
+    }
+
+    protected void installBootFeatures() {
+        try {
+            for (String repo : repositories.split(",")) {
+                repo = repo.trim();
+                if (!repo.isEmpty()) {
+                    try {
+                        featuresService.addRepository(URI.create(repo));
+                    } catch (Exception e) {
+                        LOGGER.error("Error installing boot feature repository " + repo);
+                    }
+                }
+            }
+
+            List<Set<String>> stagedFeatures = parseBootFeatures(features);
+            for (Set<String> features : stagedFeatures) {
+                featuresService.installFeatures(features, EnumSet.of(FeaturesService.Option.NoFailOnFeatureNotFound));
+            }
+            featuresService.bootDone();
+            publishBootFinished();
+        } catch (Exception e) {
+            // Special handling in case the bundle has been refreshed.
+            // In such a case, simply exits without logging any exception
+            // as the restart should cause the feature service to finish
+            // the work.
+            if (e instanceof IllegalStateException) {
+                try {
+                    bundleContext.getBundle();
+                } catch (IllegalStateException ies) {
+                    return;
+                }
+            }
+            LOGGER.error("Error installing boot features", e);
+        }
+    }
+
+    /**
+     *
+     * @param featureSt either feature name or <featurename>;version=<version>
+     * @return feature matching the feature string
+     * @throws Exception
+     */
+    private Feature getFeature(String featureSt) throws Exception {
+        String[] parts = featureSt.trim().split(";");
+        String featureName = parts[0];
+        String featureVersion = null;
+        for (String part : parts) {
+            // if the part starts with "version=" it contains the version info
+            if (part.startsWith(VERSION_PREFIX)) {
+                featureVersion = part.substring(VERSION_PREFIX.length());
+            }
+        }
+        if (featureVersion == null) {
+            // no version specified - use default version
+            featureVersion = org.apache.karaf.features.internal.model.Feature.DEFAULT_VERSION;
+        }
+        return featuresService.getFeature(featureName, featureVersion);
+    }
+
+    protected List<Set<String>> parseBootFeatures(String bootFeatures) {
+        Pattern pattern = Pattern.compile("(\\((.+))\\),|.+");
+        Matcher matcher = pattern.matcher(bootFeatures);
+        List<Set<String>> result = new ArrayList<Set<String>>();
+        while (matcher.find()) {
+            String group = matcher.group(2) != null ? matcher.group(2) : matcher.group();
+            result.add(parseFeatureList(group));
+        }
+        return result;
+    }
+
+    protected Set<String> parseFeatureList(String group) {
+        HashSet<String> features = new HashSet<String>();
+        for (String feature : Arrays.asList(group.trim().split("\\s*,\\s*"))) {
+            if (feature.length() > 0) {
+                features.add(feature);
+            }
+        }
+        return features;
+    }
+
+    private void publishBootFinished() {
+        if (bundleContext != null) {
+            BootFinished bootFinished = new BootFinished() {};
+            bundleContext.registerService(BootFinished.class, bootFinished, new Hashtable<String, String>());
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/src/main/java/org/apache/karaf/features/internal/service/EventAdminListener.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/service/EventAdminListener.java b/features/src/main/java/org/apache/karaf/features/internal/service/EventAdminListener.java
new file mode 100644
index 0000000..b6eaae5
--- /dev/null
+++ b/features/src/main/java/org/apache/karaf/features/internal/service/EventAdminListener.java
@@ -0,0 +1,91 @@
+/*
+ * 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.karaf.features.internal.service;
+
+import java.util.Dictionary;
+import java.util.Hashtable;
+
+import org.apache.karaf.features.EventConstants;
+import org.apache.karaf.features.FeatureEvent;
+import org.apache.karaf.features.FeaturesListener;
+import org.apache.karaf.features.RepositoryEvent;
+import org.osgi.framework.BundleContext;
+import org.osgi.service.event.Event;
+import org.osgi.service.event.EventAdmin;
+import org.osgi.util.tracker.ServiceTracker;
+
+/**
+ * A listener to publish events to EventAdmin
+ */
+public class EventAdminListener implements FeaturesListener {
+
+    private final ServiceTracker<EventAdmin, EventAdmin> tracker;
+
+    public EventAdminListener(BundleContext context) {
+        tracker = new ServiceTracker<EventAdmin, EventAdmin>(context, EventAdmin.class.getName(), null);
+        tracker.open();
+    }
+
+    public void featureEvent(FeatureEvent event) {
+        EventAdmin eventAdmin = tracker.getService();
+        if (eventAdmin == null) {
+            return;
+        }
+        Dictionary<String, Object> props = new Hashtable<String, Object>();
+        props.put(EventConstants.TYPE, event.getType());
+        props.put(EventConstants.EVENT, event);
+        props.put(EventConstants.TIMESTAMP, System.currentTimeMillis());
+        props.put(EventConstants.FEATURE_NAME, event.getFeature().getName());
+        props.put(EventConstants.FEATURE_VERSION, event.getFeature().getVersion());
+        String topic;
+        switch (event.getType()) {
+            case FeatureInstalled:
+                topic = EventConstants.TOPIC_FEATURES_INSTALLED;
+                break;
+            case FeatureUninstalled:
+                topic = EventConstants.TOPIC_FEATURES_UNINSTALLED;
+                break;
+            default:
+                throw new IllegalStateException("Unknown features event type: " + event.getType());
+        }
+        eventAdmin.postEvent(new Event(topic, props));
+    }
+
+    public void repositoryEvent(RepositoryEvent event) {
+        EventAdmin eventAdmin = tracker.getService();
+        if (eventAdmin == null) {
+            return;
+        }
+        Dictionary<String, Object> props = new Hashtable<String, Object>();
+        props.put(EventConstants.TYPE, event.getType());
+        props.put(EventConstants.EVENT, event);
+        props.put(EventConstants.TIMESTAMP, System.currentTimeMillis());
+        props.put(EventConstants.REPOSITORY_URI, event.getRepository().getURI().toString());
+        String topic;
+        switch (event.getType()) {
+            case RepositoryAdded:
+                topic = EventConstants.TOPIC_REPOSITORY_ADDED;
+                break;
+            case RepositoryRemoved:
+                topic = EventConstants.TOPIC_REPOSITORY_REMOVED;
+                break;
+            default:
+                throw new IllegalStateException("Unknown repository event type: " + event.getType());
+        }
+        eventAdmin.postEvent(new Event(topic, props));
+    }
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/src/main/java/org/apache/karaf/features/internal/service/FeatureConfigInstaller.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/service/FeatureConfigInstaller.java b/features/src/main/java/org/apache/karaf/features/internal/service/FeatureConfigInstaller.java
new file mode 100644
index 0000000..0e9038d
--- /dev/null
+++ b/features/src/main/java/org/apache/karaf/features/internal/service/FeatureConfigInstaller.java
@@ -0,0 +1,167 @@
+/*
+ * 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.karaf.features.internal.service;
+
+import java.io.BufferedInputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Dictionary;
+import java.util.Hashtable;
+
+import org.apache.karaf.features.ConfigFileInfo;
+import org.apache.karaf.features.Feature;
+import org.osgi.framework.Constants;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.service.cm.Configuration;
+import org.osgi.service.cm.ConfigurationAdmin;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class FeatureConfigInstaller {
+	private static final Logger LOGGER = LoggerFactory.getLogger(FeaturesServiceImpl.class);
+    private static final String CONFIG_KEY = "org.apache.karaf.features.configKey";
+
+    private final ConfigurationAdmin configAdmin;
+    
+    public FeatureConfigInstaller(ConfigurationAdmin configAdmin) {
+		this.configAdmin = configAdmin;
+	}
+
+    private String[] parsePid(String pid) {
+        int n = pid.indexOf('-');
+        if (n > 0) {
+            String factoryPid = pid.substring(n + 1);
+            pid = pid.substring(0, n);
+            return new String[]{pid, factoryPid};
+        } else {
+            return new String[]{pid, null};
+        }
+    }
+
+    private Configuration createConfiguration(ConfigurationAdmin configurationAdmin,
+                                                String pid, String factoryPid) throws IOException, InvalidSyntaxException {
+        if (factoryPid != null) {
+            return configurationAdmin.createFactoryConfiguration(factoryPid, null);
+        } else {
+            return configurationAdmin.getConfiguration(pid, null);
+        }
+    }
+
+    private Configuration findExistingConfiguration(ConfigurationAdmin configurationAdmin,
+                                                      String pid, String factoryPid) throws IOException, InvalidSyntaxException {
+        String filter;
+        if (factoryPid == null) {
+            filter = "(" + Constants.SERVICE_PID + "=" + pid + ")";
+        } else {
+            String key = createConfigurationKey(pid, factoryPid);
+            filter = "(" + CONFIG_KEY + "=" + key + ")";
+        }
+        Configuration[] configurations = configurationAdmin.listConfigurations(filter);
+        if (configurations != null && configurations.length > 0) {
+            return configurations[0];
+        }
+        return null;
+    }
+
+    void installFeatureConfigs(Feature feature) throws IOException, InvalidSyntaxException {
+        for (String config : feature.getConfigurations().keySet()) {
+            Dictionary<String,String> props = new Hashtable<String, String>(feature.getConfigurations().get(config));
+            String[] pid = parsePid(config);
+            Configuration cfg = findExistingConfiguration(configAdmin, pid[0], pid[1]);
+            if (cfg == null) {
+                cfg = createConfiguration(configAdmin, pid[0], pid[1]);
+                String key = createConfigurationKey(pid[0], pid[1]);
+                props.put(CONFIG_KEY, key);
+                if (cfg.getBundleLocation() != null) {
+                    cfg.setBundleLocation(null);
+                }
+                cfg.update(props);
+            }
+        }
+        for (ConfigFileInfo configFile : feature.getConfigurationFiles()) {
+            installConfigurationFile(configFile.getLocation(), configFile.getFinalname(), configFile.isOverride());
+        }
+    }
+
+    private String createConfigurationKey(String pid, String factoryPid) {
+        return factoryPid == null ? pid : pid + "-" + factoryPid;
+    }
+
+    private void installConfigurationFile(String fileLocation, String finalname, boolean override) throws IOException {
+    	String basePath = System.getProperty("karaf.base");
+    	
+    	if (finalname.contains("${")) {
+    		//remove any placeholder or variable part, this is not valid.
+    		int marker = finalname.indexOf("}");
+    		finalname = finalname.substring(marker+1);
+    	}
+    	
+    	finalname = basePath + File.separator + finalname;
+    	
+    	File file = new File(finalname); 
+    	if (file.exists()) {
+            if (!override) {
+                LOGGER.debug("Configuration file {} already exist, don't override it", finalname);
+                return;
+            } else {
+                LOGGER.info("Configuration file {} already exist, overriding it", finalname);
+            }
+    	} else {
+            LOGGER.info("Creating configuration file {}", finalname);
+        }
+
+        InputStream is = null;
+        FileOutputStream fop = null;
+        try {
+            is = new BufferedInputStream(new URL(fileLocation).openStream());
+
+            if (!file.exists()) {
+                File parentFile = file.getParentFile();
+                if (parentFile != null)
+                    parentFile.mkdirs();
+                file.createNewFile();
+            }
+
+            fop = new FileOutputStream(file);
+        
+            int bytesRead;
+            byte[] buffer = new byte[1024];
+            
+            while ((bytesRead = is.read(buffer)) != -1) {
+                fop.write(buffer, 0, bytesRead);
+            }
+        } catch (RuntimeException e) {
+            LOGGER.error(e.getMessage());
+            throw e;
+        } catch (MalformedURLException e) {
+        	LOGGER.error(e.getMessage());
+            throw e;
+		} finally {
+			if (is != null)
+				is.close();
+            if (fop != null) {
+			    fop.flush();
+			    fop.close();
+            }
+		}
+            
+    }
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/src/main/java/org/apache/karaf/features/internal/service/FeatureFinder.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/service/FeatureFinder.java b/features/src/main/java/org/apache/karaf/features/internal/service/FeatureFinder.java
new file mode 100644
index 0000000..d6defe0
--- /dev/null
+++ b/features/src/main/java/org/apache/karaf/features/internal/service/FeatureFinder.java
@@ -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.karaf.features.internal.service;
+
+import java.net.URI;
+import java.util.Dictionary;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+import org.osgi.service.cm.ConfigurationException;
+import org.osgi.service.cm.ManagedService;
+
+public class FeatureFinder implements ManagedService {
+
+    final Map<String, String> nameToArtifactMap = new HashMap<String, String>();
+
+    public String[] getNames() {
+        synchronized (nameToArtifactMap) {
+            Set<String> strings = nameToArtifactMap.keySet();
+            return strings.toArray(new String[strings.size()]);
+        }
+    }
+
+    public URI getUriFor(String name, String version) {
+        String coords;
+        synchronized (nameToArtifactMap) {
+            coords = nameToArtifactMap.get(name);
+        }
+        if (coords == null) {
+            return null;
+        }
+        Artifact artifact = new Artifact(coords);
+        return artifact.getMavenUrl(version);
+    }
+
+    @SuppressWarnings("rawtypes")
+    public void updated(Dictionary properties) throws ConfigurationException {
+        synchronized (nameToArtifactMap) {
+            if (properties != null) {
+                nameToArtifactMap.clear();
+                Enumeration keys = properties.keys();
+                while (keys.hasMoreElements()) {
+                    String key = (String) keys.nextElement();
+                    if (!"felix.fileinstall.filename".equals(key) && !"service.pid".equals(key)) {
+                        nameToArtifactMap.put(key, (String) properties.get(key));
+                    }
+                }
+            }
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/src/main/java/org/apache/karaf/features/internal/service/FeatureValidationUtil.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/service/FeatureValidationUtil.java b/features/src/main/java/org/apache/karaf/features/internal/service/FeatureValidationUtil.java
new file mode 100644
index 0000000..8fb161e
--- /dev/null
+++ b/features/src/main/java/org/apache/karaf/features/internal/service/FeatureValidationUtil.java
@@ -0,0 +1,113 @@
+/*
+ * 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.karaf.features.internal.service;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URI;
+import java.net.URLConnection;
+
+import javax.xml.XMLConstants;
+import javax.xml.namespace.QName;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamSource;
+import javax.xml.validation.Schema;
+import javax.xml.validation.SchemaFactory;
+import javax.xml.validation.Validator;
+
+import org.apache.karaf.features.FeaturesNamespaces;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.w3c.dom.Document;
+import org.xml.sax.SAXException;
+
+/**
+ * Utility class which fires XML Schema validation.
+ */
+public class FeatureValidationUtil {
+
+    public static final QName FEATURES_0_0 = new QName("features");
+    public static final QName FEATURES_1_0 = new QName("http://karaf.apache.org/xmlns/features/v1.0.0", "features");
+    public static final QName FEATURES_1_1 = new QName("http://karaf.apache.org/xmlns/features/v1.1.0", "features");
+    public static final QName FEATURES_1_2 = new QName("http://karaf.apache.org/xmlns/features/v1.2.0", "features");
+    private static final Logger LOGGER = LoggerFactory.getLogger(FeatureValidationUtil.class);
+
+    /**
+     * Runs schema validation.
+     * 
+     * @param uri Uri to validate.
+     * @throws Exception When validation fails.
+     */
+    public static void validate(URI uri) throws Exception {
+        Document doc = load(uri);
+
+        QName name = new QName(doc.getDocumentElement().getNamespaceURI(), doc.getDocumentElement().getLocalName());
+
+        if (FeaturesNamespaces.FEATURES_0_0_0.equals(name)) {
+            LOGGER.warn("Old style feature file without namespace found (URI: {}). This format is deprecated and support for it will soon be removed", uri);
+            return;
+        } else if (FeaturesNamespaces.FEATURES_1_0_0.equals(name)) {
+            validate(doc, "/org/apache/karaf/features/karaf-features-1.0.0.xsd");
+        } else if (FeaturesNamespaces.FEATURES_1_1_0.equals(name)) {
+            validate(doc, "/org/apache/karaf/features/karaf-features-1.1.0.xsd");
+        } else if (FeaturesNamespaces.FEATURES_1_2_0.equals(name)) {
+            validate(doc, "/org/apache/karaf/features/karaf-features-1.2.0.xsd");
+        } else if (FeaturesNamespaces.FEATURES_1_3_0.equals(name)) {
+            validate(doc, "/org/apache/karaf/features/karaf-features-1.3.0.xsd");
+        }
+        else {
+            throw new IllegalArgumentException("Unrecognized root element: " + name);
+        }
+    }
+
+    private static Document load(URI uri) throws IOException, SAXException, ParserConfigurationException {
+        InputStream stream = null;
+        try {
+            URLConnection conn;
+            try {
+                conn = uri.toURL().openConnection();
+            } catch (IllegalArgumentException e) {
+                throw new IllegalArgumentException("invalid URI: " + uri, e);
+            }
+            conn.setDefaultUseCaches(false);
+            stream = conn.getInputStream();
+            // load document and check the root element for namespace declaration
+            DocumentBuilderFactory dFactory = DocumentBuilderFactory.newInstance();
+            dFactory.setNamespaceAware(true);
+            return dFactory.newDocumentBuilder().parse(stream);
+        } finally {
+            if (stream != null) {
+                stream.close();
+            }
+        }
+    }
+
+    private static void validate(Document doc, String schemaLocation) throws SAXException {
+        SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
+        // root element has namespace - we can use schema validation
+        Schema schema = factory.newSchema(new StreamSource(FeatureValidationUtil.class.getResourceAsStream(schemaLocation)));
+        // create schema by reading it from an XSD file:
+        Validator validator = schema.newValidator();
+        try {
+            validator.validate(new DOMSource(doc));
+        } catch (Exception e) {
+            throw new IllegalArgumentException("Unable to validate " + doc.getDocumentURI(), e);
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/src/main/java/org/apache/karaf/features/internal/service/FeaturesServiceImpl.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/service/FeaturesServiceImpl.java b/features/src/main/java/org/apache/karaf/features/internal/service/FeaturesServiceImpl.java
new file mode 100644
index 0000000..6c16650
--- /dev/null
+++ b/features/src/main/java/org/apache/karaf/features/internal/service/FeaturesServiceImpl.java
@@ -0,0 +1,1455 @@
+/*
+ * 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.karaf.features.internal.service;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.EnumSet;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
+import java.util.TreeSet;
+import java.util.concurrent.Callable;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+import org.apache.felix.utils.version.VersionRange;
+import org.apache.felix.utils.version.VersionTable;
+import org.apache.karaf.features.BundleInfo;
+import org.apache.karaf.features.Feature;
+import org.apache.karaf.features.FeatureEvent;
+import org.apache.karaf.features.FeaturesListener;
+import org.apache.karaf.features.FeaturesService;
+import org.apache.karaf.features.Repository;
+import org.apache.karaf.features.RepositoryEvent;
+import org.apache.karaf.features.internal.deployment.DeploymentBuilder;
+import org.apache.karaf.features.internal.deployment.StreamProvider;
+import org.apache.karaf.features.internal.resolver.FeatureNamespace;
+import org.apache.karaf.features.internal.resolver.UriNamespace;
+import org.apache.karaf.features.internal.util.ChecksumUtils;
+import org.apache.karaf.features.internal.util.Macro;
+import org.apache.karaf.features.internal.util.MultiException;
+import org.apache.karaf.util.collections.CopyOnWriteArrayIdentityList;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleException;
+import org.osgi.framework.Constants;
+import org.osgi.framework.FrameworkEvent;
+import org.osgi.framework.FrameworkListener;
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.Version;
+import org.osgi.framework.namespace.PackageNamespace;
+import org.osgi.framework.startlevel.BundleStartLevel;
+import org.osgi.framework.wiring.BundleCapability;
+import org.osgi.framework.wiring.BundleRequirement;
+import org.osgi.framework.wiring.BundleRevision;
+import org.osgi.framework.wiring.FrameworkWiring;
+import org.osgi.resource.Resource;
+import org.osgi.resource.Wire;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import static org.apache.felix.resolver.Util.getSymbolicName;
+import static org.apache.felix.resolver.Util.getVersion;
+
+/**
+ *
+ */
+public class FeaturesServiceImpl implements FeaturesService {
+
+    public static final String UPDATE_SNAPSHOTS_NONE = "none";
+    public static final String UPDATE_SNAPSHOTS_CRC = "crc";
+    public static final String UPDATE_SNAPSHOTS_ALWAYS = "always";
+    public static final String DEFAULT_UPDATE_SNAPSHOTS = UPDATE_SNAPSHOTS_CRC;
+
+    public static final String DEFAULT_FEATURE_RESOLUTION_RANGE = "${range;[====,====]}";
+    public static final String DEFAULT_BUNDLE_UPDATE_RANGE = "${range;[==,=+)}";
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(FeaturesServiceImpl.class);
+    private static final String SNAPSHOT = "SNAPSHOT";
+    private static final String MAVEN = "mvn:";
+
+    /**
+     * Our bundle.
+     * We use it to check bundle operations affecting our own bundle.
+     */
+    private final Bundle bundle;
+
+    /**
+     * The system bundle context.
+     * For all bundles related operations, we use the system bundle context
+     * to allow this bundle to be stopped and still allow the deployment to
+     * take place.
+     */
+    private final BundleContext systemBundleContext;
+    /**
+     * Used to load and save the {@link State} of this service.
+     */
+    private final StateStorage storage;
+    private final FeatureFinder featureFinder;
+    private final EventAdminListener eventAdminListener;
+    private final FeatureConfigInstaller configInstaller;
+    private final String overrides;
+    /**
+     * Range to use when a version is specified on a feature dependency.
+     * The default is {@link FeaturesServiceImpl#DEFAULT_FEATURE_RESOLUTION_RANGE}
+     */
+    private final String featureResolutionRange;
+    /**
+     * Range to use when verifying if a bundle should be updated or
+     * new bundle installed.
+     * The default is {@link FeaturesServiceImpl#DEFAULT_BUNDLE_UPDATE_RANGE}
+     */
+    private final String bundleUpdateRange;
+    /**
+     * Use CRC to check snapshot bundles and update them if changed.
+     * Either:
+     *   - none : never update snapshots
+     *   - always : always update snapshots
+     *   - crc : use CRC to detect changes
+     */
+    private final String updateSnaphots;
+
+    private final List<FeaturesListener> listeners = new CopyOnWriteArrayIdentityList<FeaturesListener>();
+
+    // Synchronized on lock
+    private final Object lock = new Object();
+    private final State state = new State();
+    private final Map<String, Repository> repositoryCache = new HashMap<String, Repository>();
+    private Map<String, Map<String, Feature>> featureCache;
+
+
+    public FeaturesServiceImpl(Bundle bundle,
+                               BundleContext systemBundleContext,
+                               StateStorage storage,
+                               FeatureFinder featureFinder,
+                               EventAdminListener eventAdminListener,
+                               FeatureConfigInstaller configInstaller,
+                               String overrides,
+                               String featureResolutionRange,
+                               String bundleUpdateRange,
+                               String updateSnaphots) {
+        this.bundle = bundle;
+        this.systemBundleContext = systemBundleContext;
+        this.storage = storage;
+        this.featureFinder = featureFinder;
+        this.eventAdminListener = eventAdminListener;
+        this.configInstaller = configInstaller;
+        this.overrides = overrides;
+        this.featureResolutionRange = featureResolutionRange;
+        this.bundleUpdateRange = bundleUpdateRange;
+        this.updateSnaphots = updateSnaphots;
+        loadState();
+    }
+
+    //
+    // State support
+    //
+
+    protected void loadState() {
+        try {
+            synchronized (lock) {
+                storage.load(state);
+            }
+        } catch (IOException e) {
+            LOGGER.warn("Error loading FeaturesService state", e);
+        }
+    }
+
+    protected void saveState() {
+        try {
+            synchronized (lock) {
+                // Make sure we don't store bundle checksums if
+                // it has been disabled through configadmin
+                // so that we don't keep out-of-date checksums.
+                if (!UPDATE_SNAPSHOTS_CRC.equalsIgnoreCase(updateSnaphots)) {
+                    state.bundleChecksums.clear();
+                }
+                storage.save(state);
+            }
+        } catch (IOException e) {
+            LOGGER.warn("Error saving FeaturesService state", e);
+        }
+    }
+
+    boolean isBootDone() {
+        synchronized (lock) {
+            return state.bootDone.get();
+        }
+    }
+
+    void bootDone() {
+        synchronized (lock) {
+            state.bootDone.set(true);
+            saveState();
+        }
+    }
+
+    //
+    // Listeners support
+    //
+
+    public void registerListener(FeaturesListener listener) {
+        listeners.add(listener);
+        try {
+            Set<String> repositories = new TreeSet<String>();
+            Set<String> installedFeatures = new TreeSet<String>();
+            synchronized (lock) {
+                repositories.addAll(state.repositories);
+                installedFeatures.addAll(state.installedFeatures);
+            }
+            for (String uri : repositories) {
+                Repository repository = new RepositoryImpl(URI.create(uri));
+                listener.repositoryEvent(new RepositoryEvent(repository, RepositoryEvent.EventType.RepositoryAdded, true));
+            }
+            for (String id : installedFeatures) {
+                Feature feature = org.apache.karaf.features.internal.model.Feature.valueOf(id);
+                listener.featureEvent(new FeatureEvent(feature, FeatureEvent.EventType.FeatureInstalled, true));
+            }
+        } catch (Exception e) {
+            LOGGER.error("Error notifying listener about the current state", e);
+        }
+    }
+
+    public void unregisterListener(FeaturesListener listener) {
+        listeners.remove(listener);
+    }
+
+    protected void callListeners(FeatureEvent event) {
+        if (eventAdminListener != null) {
+            eventAdminListener.featureEvent(event);
+        }
+        for (FeaturesListener listener : listeners) {
+            listener.featureEvent(event);
+        }
+    }
+
+    protected void callListeners(RepositoryEvent event) {
+        if (eventAdminListener != null) {
+            eventAdminListener.repositoryEvent(event);
+        }
+        for (FeaturesListener listener : listeners) {
+            listener.repositoryEvent(event);
+        }
+    }
+
+    //
+    // Feature Finder support
+    //
+
+    @Override
+    public URI getRepositoryUriFor(String name, String version) {
+        return featureFinder.getUriFor(name, version);
+    }
+
+    @Override
+    public String[] getRepositoryNames() {
+        return featureFinder.getNames();
+    }
+
+
+    //
+    // Repositories support
+    //
+
+    public Repository loadRepository(URI uri) throws Exception {
+        // TODO: merge validation and loading by loading the DOM, validating, unmarshalling
+        FeatureValidationUtil.validate(uri);
+        RepositoryImpl repo = new RepositoryImpl(uri);
+        repo.load();
+        return repo;
+    }
+
+    @Override
+    public void validateRepository(URI uri) throws Exception {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void addRepository(URI uri) throws Exception {
+        addRepository(uri, false);
+    }
+
+    @Override
+    public void addRepository(URI uri, boolean install) throws Exception {
+        if (install) {
+            // TODO: implement
+            throw new UnsupportedOperationException();
+        }
+        Repository repository = loadRepository(uri);
+        synchronized (lock) {
+            // Clean cache
+            repositoryCache.put(uri.toString(), repository);
+            featureCache = null;
+            // Add repo
+            if (!state.repositories.add(uri.toString())) {
+                return;
+            }
+            saveState();
+        }
+        callListeners(new RepositoryEvent(repository, RepositoryEvent.EventType.RepositoryAdded, false));
+    }
+
+    @Override
+    public void removeRepository(URI uri) throws Exception {
+        removeRepository(uri, true);
+    }
+
+    @Override
+    public void removeRepository(URI uri, boolean uninstall) throws Exception {
+        // TODO: check we don't have any feature installed from this repository
+        Repository repo;
+        synchronized (lock) {
+            // Remove repo
+            if (!state.repositories.remove(uri.toString())) {
+                return;
+            }
+            // Clean cache
+            featureCache = null;
+            repo = repositoryCache.get(uri.toString());
+            List<String> toRemove = new ArrayList<String>();
+            toRemove.add(uri.toString());
+            while (!toRemove.isEmpty()) {
+                Repository rep = repositoryCache.remove(toRemove.remove(0));
+                if (rep != null) {
+                    for (URI u : rep.getRepositories()) {
+                        toRemove.add(u.toString());
+                    }
+                }
+            }
+            saveState();
+        }
+        if (repo == null) {
+            repo = new RepositoryImpl(uri);
+        }
+        callListeners(new RepositoryEvent(repo, RepositoryEvent.EventType.RepositoryRemoved, false));
+    }
+
+    @Override
+    public void restoreRepository(URI uri) throws Exception {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void refreshRepository(URI uri) throws Exception {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public Repository[] listRepositories() throws Exception {
+        // Make sure the cache is loaded
+        getFeatures();
+        synchronized (lock) {
+            return repositoryCache.values().toArray(new Repository[repositoryCache.size()]);
+        }
+    }
+
+    @Override
+    public Repository[] listRequiredRepositories() throws Exception {
+        // Make sure the cache is loaded
+        getFeatures();
+        synchronized (lock) {
+            List<Repository> repos = new ArrayList<Repository>();
+            for (Map.Entry<String, Repository> entry : repositoryCache.entrySet()) {
+                if (state.repositories.contains(entry.getKey())) {
+                    repos.add(entry.getValue());
+                }
+            }
+            return repos.toArray(new Repository[repos.size()]);
+        }
+    }
+
+    @Override
+    public Repository getRepository(String name) throws Exception {
+        // Make sure the cache is loaded
+        getFeatures();
+        synchronized (lock) {
+            for (Repository repo : this.repositoryCache.values()) {
+                if (name.equals(repo.getName())) {
+                    return repo;
+                }
+            }
+            return null;
+        }
+    }
+
+    //
+    // Features support
+    //
+
+    public Feature getFeature(String name) throws Exception {
+        return getFeature(name, null);
+    }
+
+    public Feature getFeature(String name, String version) throws Exception {
+        Map<String, Feature> versions = getFeatures().get(name);
+        return getFeatureMatching(versions, version);
+    }
+
+    protected Feature getFeatureMatching(Map<String, Feature> versions, String version) {
+        if (version != null) {
+            version = version.trim();
+            if (version.equals(org.apache.karaf.features.internal.model.Feature.DEFAULT_VERSION)) {
+                version = "";
+            }
+        } else {
+            version = "";
+        }
+        if (versions == null || versions.isEmpty()) {
+            return null;
+        } else {
+            Feature feature = version.isEmpty() ? null : versions.get(version);
+            if (feature == null) {
+                // Compute version range. If an version has been given, assume exact range
+                VersionRange versionRange = version.isEmpty() ?
+                        new VersionRange(Version.emptyVersion) :
+                        new VersionRange(version, true, true);
+                Version latest = Version.emptyVersion;
+                for (String available : versions.keySet()) {
+                    Version availableVersion = VersionTable.getVersion(available);
+                    if (availableVersion.compareTo(latest) >= 0 && versionRange.contains(availableVersion)) {
+                        feature = versions.get(available);
+                        latest = availableVersion;
+                    }
+                }
+            }
+            return feature;
+        }
+    }
+
+    public Feature[] listFeatures() throws Exception {
+        Set<Feature> features = new HashSet<Feature>();
+        for (Map<String, Feature> featureWithDifferentVersion : getFeatures().values()) {
+            for (Feature f : featureWithDifferentVersion.values()) {
+                features.add(f);
+            }
+        }
+        return features.toArray(new Feature[features.size()]);
+    }
+
+    protected Map<String, Map<String, Feature>> getFeatures() throws Exception {
+        List<String> uris;
+        synchronized (lock) {
+            if (featureCache != null) {
+                return featureCache;
+            }
+            uris = new ArrayList<String>(state.repositories);
+        }
+        //the outer map's key is feature name, the inner map's key is feature version
+        Map<String, Map<String, Feature>> map = new HashMap<String, Map<String, Feature>>();
+        // Two phase load:
+        // * first load dependent repositories
+        List<String> toLoad = new ArrayList<String>(uris);
+        while (!toLoad.isEmpty()) {
+            String uri = toLoad.remove(0);
+            Repository repo;
+            synchronized (lock) {
+                repo = repositoryCache.get(uri);
+            }
+            if (repo == null) {
+                RepositoryImpl rep = new RepositoryImpl(URI.create(uri));
+                rep.load();
+                repo = rep;
+                synchronized (lock) {
+                    repositoryCache.put(uri, repo);
+                }
+            }
+            for (URI u : repo.getRepositories()) {
+                toLoad.add(u.toString());
+            }
+        }
+        List<Repository> repos;
+        synchronized (lock) {
+            repos = new ArrayList<Repository>(repositoryCache.values());
+        }
+        // * then load all features
+        for (Repository repo : repos) {
+            for (Feature f : repo.getFeatures()) {
+                if (map.get(f.getName()) == null) {
+                    Map<String, Feature> versionMap = new HashMap<String, Feature>();
+                    versionMap.put(f.getVersion(), f);
+                    map.put(f.getName(), versionMap);
+                } else {
+                    map.get(f.getName()).put(f.getVersion(), f);
+                }
+            }
+        }
+        synchronized (lock) {
+            if (uris.size() == state.repositories.size() &&
+                    state.repositories.containsAll(uris)) {
+                featureCache = map;
+            }
+        }
+        return map;
+    }
+
+    //
+    // Installed features
+    //
+
+    @Override
+    public Feature[] listInstalledFeatures() throws Exception {
+        Set<Feature> features = new HashSet<Feature>();
+        Map<String, Map<String, Feature>> allFeatures = getFeatures();
+        synchronized (lock) {
+            for (Map<String, Feature> featureWithDifferentVersion : allFeatures.values()) {
+                for (Feature f : featureWithDifferentVersion.values()) {
+                    if (isInstalled(f)) {
+                        features.add(f);
+                    }
+                }
+            }
+        }
+        return features.toArray(new Feature[features.size()]);
+    }
+
+    @Override
+    public Feature[] listRequiredFeatures() throws Exception {
+        Set<Feature> features = new HashSet<Feature>();
+        Map<String, Map<String, Feature>> allFeatures = getFeatures();
+        synchronized (lock) {
+            for (Map<String, Feature> featureWithDifferentVersion : allFeatures.values()) {
+                for (Feature f : featureWithDifferentVersion.values()) {
+                    if (isRequired(f)) {
+                        features.add(f);
+                    }
+                }
+            }
+        }
+        return features.toArray(new Feature[features.size()]);
+    }
+
+
+    @Override
+    public boolean isInstalled(Feature f) {
+        String id = normalize(f.getId());
+        synchronized (lock) {
+            return state.installedFeatures.contains(id);
+        }
+    }
+
+    @Override
+    public boolean isRequired(Feature f) {
+        String id = normalize(f.getId());
+        synchronized (lock) {
+            return state.features.contains(id);
+        }
+    }
+
+    //
+    // Installation and uninstallation of features
+    //
+
+    public void installFeature(String name) throws Exception {
+        installFeature(name, EnumSet.noneOf(Option.class));
+    }
+
+    public void installFeature(String name, String version) throws Exception {
+        installFeature(version != null ? name + "/" + version : name, EnumSet.noneOf(Option.class));
+    }
+
+    public void installFeature(String name, EnumSet<Option> options) throws Exception {
+        installFeatures(Collections.singleton(name), options);
+    }
+
+    public void installFeature(String name, String version, EnumSet<Option> options) throws Exception {
+        installFeature(version != null ? name + "/" + version : name, options);
+    }
+
+    public void installFeature(Feature feature, EnumSet<Option> options) throws Exception {
+        installFeature(feature.getId());
+    }
+
+    @Override
+    public void uninstallFeature(String name, String version) throws Exception {
+        uninstallFeature(version != null ? name + "/" + version : name);
+    }
+
+    @Override
+    public void uninstallFeature(String name, String version, EnumSet<Option> options) throws Exception {
+        uninstallFeature(version != null ? name + "/" + version : name, options);
+    }
+
+    @Override
+    public void uninstallFeature(String name) throws Exception {
+        uninstallFeature(name, EnumSet.noneOf(Option.class));
+    }
+
+    @Override
+    public void uninstallFeature(String name, EnumSet<Option> options) throws Exception {
+        uninstallFeatures(Collections.singleton(name), options);
+    }
+
+
+    //
+    //
+    //
+    //   RESOLUTION
+    //
+    //
+    //
+
+
+
+
+
+
+    public void installFeatures(Set<String> features, EnumSet<Option> options) throws Exception {
+        Set<String> required;
+        Set<String> installed;
+        Set<Long> managed;
+        synchronized (lock) {
+            required = new HashSet<String>(state.features);
+            installed = new HashSet<String>(state.installedFeatures);
+            managed = new HashSet<Long>(state.managedBundles);
+        }
+        List<String> featuresToAdd = new ArrayList<String>();
+        Map<String, Map<String, Feature>> featuresMap = getFeatures();
+        for (String feature : features) {
+            feature = normalize(feature);
+            String name = feature.substring(0, feature.indexOf("/"));
+            String version = feature.substring(feature.indexOf("/") + 1);
+            Feature f = getFeatureMatching(featuresMap.get(name), version);
+            if (f == null) {
+                if (!options.contains(Option.NoFailOnFeatureNotFound)) {
+                    throw new IllegalArgumentException("No matching features for " + feature);
+                }
+            } else {
+                featuresToAdd.add(normalize(f.getId()));
+            }
+        }
+        featuresToAdd = new ArrayList<String>(new LinkedHashSet<String>(featuresToAdd));
+        StringBuilder sb = new StringBuilder();
+        sb.append("Adding features: ");
+        for (int i = 0; i < featuresToAdd.size(); i++) {
+            if (i > 0) {
+                sb.append(", ");
+            }
+            sb.append(featuresToAdd.get(i));
+        }
+        print(sb.toString(), options.contains(Option.Verbose));
+        required.addAll(featuresToAdd);
+        doInstallFeaturesInThread(required, installed, managed, options);
+    }
+
+    public void uninstallFeatures(Set<String> features, EnumSet<Option> options) throws Exception {
+        Set<String> required;
+        Set<String> installed;
+        Set<Long> managed;
+        synchronized (lock) {
+            required = new HashSet<String>(state.features);
+            installed = new HashSet<String>(state.installedFeatures);
+            managed = new HashSet<Long>(state.managedBundles);
+        }
+        List<String> featuresToRemove = new ArrayList<String>();
+        for (String feature : new HashSet<String>(features)) {
+            List<String> toRemove = new ArrayList<String>();
+            feature = normalize(feature);
+            if (feature.endsWith("/0.0.0")) {
+                String nameSep = feature.substring(0, feature.indexOf("/") + 1);
+                for (String f : required) {
+                    if (normalize(f).startsWith(nameSep)) {
+                        toRemove.add(f);
+                    }
+                }
+            } else {
+                toRemove.add(feature);
+            }
+            toRemove.retainAll(required);
+            if (toRemove.isEmpty()) {
+                throw new IllegalArgumentException("Feature named '" + feature + "' is not installed");
+            } else if (toRemove.size() > 1) {
+                String name = feature.substring(0, feature.indexOf("/"));
+                StringBuilder sb = new StringBuilder();
+                sb.append("Feature named '").append(name).append("' has multiple versions installed (");
+                for (int i = 0; i < toRemove.size(); i++) {
+                    if (i > 0) {
+                        sb.append(", ");
+                    }
+                    sb.append(toRemove.get(i));
+                }
+                sb.append("). Please specify the version to uninstall.");
+                throw new IllegalArgumentException(sb.toString());
+            }
+            featuresToRemove.addAll(toRemove);
+        }
+        featuresToRemove = new ArrayList<String>(new LinkedHashSet<String>(featuresToRemove));
+        StringBuilder sb = new StringBuilder();
+        sb.append("Removing features: ");
+        for (int i = 0; i < featuresToRemove.size(); i++) {
+            if (i > 0) {
+                sb.append(", ");
+            }
+            sb.append(featuresToRemove.get(i));
+        }
+        print(sb.toString(), options.contains(Option.Verbose));
+        required.removeAll(featuresToRemove);
+        doInstallFeaturesInThread(required, installed, managed, options);
+    }
+
+    protected String normalize(String feature) {
+        if (!feature.contains("/")) {
+            feature += "/0.0.0";
+        }
+        int idx = feature.indexOf("/");
+        String name = feature.substring(0, idx);
+        String version = feature.substring(idx + 1);
+        return name + "/" + VersionTable.getVersion(version).toString();
+    }
+
+    /**
+     * Actual deployment needs to be done in a separate thread.
+     * The reason is that if the console is refreshed, the current thread which is running
+     * the command may be interrupted while waiting for the refresh to be done, leading
+     * to bundles not being started after the refresh.
+     */
+    public void doInstallFeaturesInThread(final Set<String> features,
+                                          final Set<String> installed,
+                                          final Set<Long> managed,
+                                          final EnumSet<Option> options) throws Exception {
+        ExecutorService executor = Executors.newCachedThreadPool();
+        try {
+            executor.submit(new Callable<Object>() {
+                @Override
+                public Object call() throws Exception {
+                    doInstallFeatures(features, installed, managed, options);
+                    return null;
+                }
+            }).get();
+        } catch (ExecutionException e) {
+            Throwable t = e.getCause();
+            if (t instanceof RuntimeException) {
+                throw ((RuntimeException) t);
+            } else if (t instanceof Error) {
+                throw ((Error) t);
+            } else if (t instanceof Exception) {
+                throw (Exception) t;
+            } else {
+                throw e;
+            }
+        } finally {
+            executor.shutdown();
+        }
+    }
+
+    public void doInstallFeatures(Set<String> features,    // all request features
+                                  Set<String> installed,   // installed features
+                                  Set<Long> managed,       // currently managed bundles
+                                  EnumSet<Option> options  // installation options
+                    ) throws Exception {
+
+        boolean noRefreshUnmanaged = options.contains(Option.NoAutoRefreshUnmanagedBundles);
+        boolean noRefreshManaged = options.contains(Option.NoAutoRefreshManagedBundles);
+        boolean noRefresh = options.contains(Option.NoAutoRefreshBundles);
+        boolean noStart = options.contains(Option.NoAutoStartBundles);
+        boolean verbose = options.contains(Option.Verbose);
+        boolean simulate = options.contains(Option.Simulate);
+
+        // Get a list of resolved and unmanaged bundles to use as capabilities during resolution
+        List<Resource> systemBundles = new ArrayList<Resource>();
+        Bundle[] bundles = systemBundleContext.getBundles();
+        for (Bundle bundle : bundles) {
+            if (bundle.getState() >= Bundle.RESOLVED && !managed.contains(bundle.getBundleId())) {
+                Resource res = bundle.adapt(BundleRevision.class);
+                systemBundles.add(res);
+            }
+        }
+        // Resolve
+        // TODO: requirements
+        // TODO: bundles
+        // TODO: regions: on isolated regions, we may need different resolution for each region
+        Set<String>  overrides    = Overrides.loadOverrides(this.overrides);
+        Repository[] repositories = listRepositories();
+        DeploymentBuilder builder = createDeploymentBuilder(repositories);
+        builder.setFeatureRange(featureResolutionRange);
+        builder.download(features,
+                         Collections.<String>emptySet(),
+                         Collections.<String>emptySet(),
+                         overrides,
+                         Collections.<String>emptySet());
+        Map<Resource, List<Wire>> resolution = builder.resolve(systemBundles, false);
+        Collection<Resource> allResources = resolution.keySet();
+        Map<String, StreamProvider> providers = builder.getProviders();
+
+        // Install conditionals
+        List<String> installedFeatureIds = getFeatureIds(allResources);
+        List<Feature> installedFeatures = getFeatures(repositories, installedFeatureIds);
+
+        //
+        // Compute list of installable resources (those with uris)
+        //
+        List<Resource> resources = getBundles(allResources);
+
+        // Compute information for each bundle
+        Map<String, BundleInfo> bundleInfos = new HashMap<String, BundleInfo>();
+        for (Feature feature : getFeatures(repositories, getFeatureIds(allResources))) {
+            for (BundleInfo bi : feature.getBundles()) {
+                BundleInfo oldBi = bundleInfos.get(bi.getLocation());
+                if (oldBi != null) {
+                    bi = mergeBundleInfo(bi, oldBi);
+                }
+                bundleInfos.put(bi.getLocation(), bi);
+            }
+        }
+
+        // TODO: handle bundleInfo.isStart()
+
+        // Get all resources that will be used to satisfy the old features set
+        Set<Resource> resourceLinkedToOldFeatures = new HashSet<Resource>();
+        if (noStart) {
+            for (Resource resource : resolution.keySet()) {
+                String name = FeatureNamespace.getName(resource);
+                if (name != null) {
+                    Version version = FeatureNamespace.getVersion(resource);
+                    String id = version != null ? name + "/" + version : name;
+                    if (installed.contains(id)) {
+                        addTransitive(resource, resourceLinkedToOldFeatures, resolution);
+                    }
+                }
+            }
+        }
+
+        //
+        // Compute deployment
+        //
+        Map<String, Long> bundleChecksums = new HashMap<String, Long>();
+        synchronized (lock) {
+            bundleChecksums.putAll(state.bundleChecksums);
+        }
+        Deployment deployment = computeDeployment(managed, bundles, providers, resources, bundleChecksums);
+
+        if (deployment.toDelete.isEmpty() &&
+                deployment.toUpdate.isEmpty() &&
+                deployment.toInstall.isEmpty()) {
+            print("No deployment change.", verbose);
+            return;
+        }
+        //
+        // Log deployment
+        //
+        logDeployment(deployment, verbose);
+
+        if (simulate) {
+            // TODO: it would be nice to print bundles that will be refreshed
+            // TODO: it could be done by checking the differences between
+            // TODO: the resolution result and the actual wiring state
+            return;
+        }
+
+        Set<Bundle> toRefresh = new HashSet<Bundle>();
+        Set<Bundle> toStart = new HashSet<Bundle>();
+
+        //
+        // Execute deployment
+        //
+
+        // TODO: handle update on the features service itself
+        if (deployment.toUpdate.containsKey(bundle) ||
+                deployment.toDelete.contains(bundle)) {
+
+            LOGGER.warn("Updating or uninstalling of the FeaturesService is not supported");
+            deployment.toUpdate.remove(bundle);
+            deployment.toDelete.remove(bundle);
+
+        }
+
+        //
+        // Perform bundle operations
+        //
+
+        // Stop bundles by chunks
+        Set<Bundle> toStop = new HashSet<Bundle>();
+        toStop.addAll(deployment.toUpdate.keySet());
+        toStop.addAll(deployment.toDelete);
+        removeFragmentsAndBundlesInState(toStop, Bundle.UNINSTALLED | Bundle.RESOLVED | Bundle.STOPPING);
+        if (!toStop.isEmpty()) {
+            print("Stopping bundles:", verbose);
+            while (!toStop.isEmpty()) {
+                List<Bundle> bs = getBundlesToStop(toStop);
+                for (Bundle bundle : bs) {
+                    print("  " + bundle.getSymbolicName() + " / " + bundle.getVersion(), verbose);
+                    bundle.stop(Bundle.STOP_TRANSIENT);
+                    toStop.remove(bundle);
+                }
+            }
+        }
+        if (!deployment.toDelete.isEmpty()) {
+            print("Uninstalling bundles:", verbose);
+            for (Bundle bundle : deployment.toDelete) {
+                print("  " + bundle.getSymbolicName() + " / " + bundle.getVersion(), verbose);
+                bundle.uninstall();
+                managed.remove(bundle.getBundleId());
+                toRefresh.add(bundle);
+            }
+        }
+        if (!deployment.toUpdate.isEmpty()) {
+            print("Updating bundles:", verbose);
+            for (Map.Entry<Bundle, Resource> entry : deployment.toUpdate.entrySet()) {
+                Bundle bundle = entry.getKey();
+                Resource resource = entry.getValue();
+                String uri = UriNamespace.getUri(resource);
+                print("  " + uri, verbose);
+                InputStream is = getBundleInputStream(resource, providers);
+                bundle.update(is);
+                toRefresh.add(bundle);
+                toStart.add(bundle);
+                BundleInfo bi = bundleInfos.get(uri);
+                if (bi != null && bi.getStartLevel() > 0) {
+                    bundle.adapt(BundleStartLevel.class).setStartLevel(bi.getStartLevel());
+                }
+                // TODO: handle region
+            }
+        }
+        if (!deployment.toInstall.isEmpty()) {
+            print("Installing bundles:", verbose);
+            for (Resource resource : deployment.toInstall) {
+                String uri = UriNamespace.getUri(resource);
+                print("  " + uri, verbose);
+                InputStream is = getBundleInputStream(resource, providers);
+                Bundle bundle = systemBundleContext.installBundle(uri, is);
+                managed.add(bundle.getBundleId());
+                if (!noStart || resourceLinkedToOldFeatures.contains(resource)) {
+                    toStart.add(bundle);
+                }
+                toRefresh.add(bundle);
+                deployment.resToBnd.put(resource, bundle);
+                // save a checksum of installed snapshot bundle
+                if (UPDATE_SNAPSHOTS_CRC.equals(updateSnaphots)
+                        && isUpdateable(resource) && !deployment.newCheckums.containsKey(bundle.getLocation())) {
+                    deployment.newCheckums.put(bundle.getLocation(), ChecksumUtils.checksum(getBundleInputStream(resource, providers)));
+                }
+                BundleInfo bi = bundleInfos.get(uri);
+                if (bi != null && bi.getStartLevel() > 0) {
+                    bundle.adapt(BundleStartLevel.class).setStartLevel(bi.getStartLevel());
+                }
+                // TODO: handle region
+            }
+        }
+
+        //
+        // Update and save state
+        //
+        List<String> newFeatures = new ArrayList<String>();
+        synchronized (lock) {
+            List<String> allFeatures = new ArrayList<String>();
+            for (Resource resource : allResources) {
+                String name = FeatureNamespace.getName(resource);
+                if (name != null) {
+                    Version version = FeatureNamespace.getVersion(resource);
+                    String id = version != null ? name + "/" + version : name;
+                    allFeatures.add(id);
+                    if (!state.installedFeatures.contains(id)) {
+                        newFeatures.add(id);
+                    }
+                }
+            }
+            state.bundleChecksums.putAll(deployment.newCheckums);
+            state.features.clear();
+            state.features.addAll(features);
+            state.installedFeatures.clear();
+            state.installedFeatures.addAll(allFeatures);
+            state.managedBundles.clear();
+            state.managedBundles.addAll(managed);
+            saveState();
+        }
+
+        //
+        // Install configurations
+        //
+        if (configInstaller != null && !newFeatures.isEmpty()) {
+            for (Repository repository : repositories) {
+                for (Feature feature : repository.getFeatures()) {
+                    if (newFeatures.contains(feature.getId())) {
+                        configInstaller.installFeatureConfigs(feature);
+                    }
+                }
+            }
+        }
+
+        if (!noRefreshManaged) {
+            findBundlesWithOptionalPackagesToRefresh(toRefresh);
+            findBundlesWithFragmentsToRefresh(toRefresh);
+        }
+
+        if (noRefreshUnmanaged) {
+            Set<Bundle> newSet = new HashSet<Bundle>();
+            for (Bundle bundle : toRefresh) {
+                if (managed.contains(bundle.getBundleId())) {
+                    newSet.add(bundle);
+                }
+            }
+            toRefresh = newSet;
+        }
+
+        // TODO: remove this hack, but it avoids loading the class after the bundle is refreshed
+        RequirementSort sort = new RequirementSort();
+
+        if (!noRefresh) {
+            toStop = new HashSet<Bundle>();
+            toStop.addAll(toRefresh);
+            removeFragmentsAndBundlesInState(toStop, Bundle.UNINSTALLED | Bundle.RESOLVED | Bundle.STOPPING);
+            if (!toStop.isEmpty()) {
+                print("Stopping bundles:", verbose);
+                while (!toStop.isEmpty()) {
+                    List<Bundle> bs = getBundlesToStop(toStop);
+                    for (Bundle bundle : bs) {
+                        print("  " + bundle.getSymbolicName() + " / " + bundle.getVersion(), verbose);
+                        bundle.stop(Bundle.STOP_TRANSIENT);
+                        toStop.remove(bundle);
+                        toStart.add(bundle);
+                    }
+                }
+            }
+
+            if (!toRefresh.isEmpty()) {
+                print("Refreshing bundles:", verbose);
+                for (Bundle bundle : toRefresh) {
+                    print("  " + bundle.getSymbolicName() + " / " + bundle.getVersion(), verbose);
+                }
+                if (!toRefresh.isEmpty()) {
+                    refreshPackages(toRefresh);
+                }
+            }
+        }
+
+        // Compute bundles to start
+        removeFragmentsAndBundlesInState(toStart, Bundle.UNINSTALLED | Bundle.ACTIVE | Bundle.STARTING);
+        if (!toStart.isEmpty()) {
+            // Compute correct start order
+            List<Exception> exceptions = new ArrayList<Exception>();
+            print("Starting bundles:", verbose);
+            while (!toStart.isEmpty()) {
+                List<Bundle> bs = getBundlesToStart(toStart);
+                for (Bundle bundle : bs) {
+                    LOGGER.info("  " + bundle.getSymbolicName() + " / " + bundle.getVersion());
+                    try {
+                        bundle.start();
+                    } catch (BundleException e) {
+                        exceptions.add(e);
+                    }
+                    toStart.remove(bundle);
+                }
+            }
+            if (!exceptions.isEmpty()) {
+                throw new MultiException("Error restarting bundles", exceptions);
+            }
+        }
+
+        // TODO: call listeners for features added and removed
+
+        print("Done.", verbose);
+    }
+
+    private void addTransitive(Resource resource, Set<Resource> resources, Map<Resource, List<Wire>> resolution) {
+        if (resources.add(resource)) {
+            for (Wire wire : resolution.get(resource)) {
+                addTransitive(wire.getProvider(), resources, resolution);
+            }
+        }
+    }
+
+    protected BundleInfo mergeBundleInfo(BundleInfo bi, BundleInfo oldBi) {
+        // TODO: we need a proper merge strategy when a bundle
+        // TODO: comes from different features
+        return bi;
+    }
+
+    private void print(String message, boolean verbose) {
+        LOGGER.info(message);
+        if (verbose) {
+            System.out.println(message);
+        }
+    }
+
+    private void removeFragmentsAndBundlesInState(Collection<Bundle> bundles, int state) {
+        for (Bundle bundle : new ArrayList<Bundle>(bundles)) {
+            if ((bundle.getState() & state) != 0
+                     || bundle.getHeaders().get(Constants.FRAGMENT_HOST) != null) {
+                bundles.remove(bundle);
+            }
+        }
+    }
+
+    protected void logDeployment(Deployment deployment, boolean verbose) {
+        print("Changes to perform:", verbose);
+        if (!deployment.toDelete.isEmpty()) {
+            print("  Bundles to uninstall:", verbose);
+            for (Bundle bundle : deployment.toDelete) {
+                print("    " + bundle.getSymbolicName() + " / " + bundle.getVersion(), verbose);
+            }
+        }
+        if (!deployment.toUpdate.isEmpty()) {
+            print("  Bundles to update:", verbose);
+            for (Map.Entry<Bundle, Resource> entry : deployment.toUpdate.entrySet()) {
+                print("    " + entry.getKey().getSymbolicName() + " / " + entry.getKey().getVersion() + " with " + UriNamespace.getUri(entry.getValue()), verbose);
+            }
+        }
+        if (!deployment.toInstall.isEmpty()) {
+            print("  Bundles to install:", verbose);
+            for (Resource resource : deployment.toInstall) {
+                print("    " + UriNamespace.getUri(resource), verbose);
+            }
+        }
+    }
+
+    protected Deployment computeDeployment(
+                                Set<Long> managed,
+                                Bundle[] bundles,
+                                Map<String, StreamProvider> providers,
+                                List<Resource> resources,
+                                Map<String, Long> bundleChecksums) throws IOException {
+        Deployment deployment = new Deployment();
+
+        // TODO: regions
+        List<Resource> toDeploy = new ArrayList<Resource>(resources);
+
+        // First pass: go through all installed bundles and mark them
+        // as either to ignore or delete
+        for (Bundle bundle : bundles) {
+            if (bundle.getSymbolicName() != null && bundle.getBundleId() != 0) {
+                Resource resource = null;
+                for (Resource res : toDeploy) {
+                    if (bundle.getSymbolicName().equals(getSymbolicName(res))) {
+                        if (bundle.getVersion().equals(getVersion(res))) {
+                            resource = res;
+                            break;
+                        }
+                    }
+                }
+                // We found a matching bundle
+                if (resource != null) {
+                    // In case of snapshots, check if the snapshot is out of date
+                    // and flag it as to update
+                    if (managed.contains(bundle.getBundleId()) && isUpdateable(resource)) {
+                        // Always update snapshots
+                        if (UPDATE_SNAPSHOTS_ALWAYS.equalsIgnoreCase(updateSnaphots)) {
+                            LOGGER.debug("Update snapshot for " + bundle.getLocation());
+                            deployment.toUpdate.put(bundle, resource);
+                        }
+                        else if (UPDATE_SNAPSHOTS_CRC.equalsIgnoreCase(updateSnaphots)) {
+                            // if the checksum are different
+                            InputStream is = null;
+                            try {
+                                is = getBundleInputStream(resource, providers);
+                                long newCrc = ChecksumUtils.checksum(is);
+                                long oldCrc = bundleChecksums.containsKey(bundle.getLocation()) ? bundleChecksums.get(bundle.getLocation()) : 0l;
+                                if (newCrc != oldCrc) {
+                                    LOGGER.debug("New snapshot available for " + bundle.getLocation());
+                                    deployment.toUpdate.put(bundle, resource);
+                                    deployment.newCheckums.put(bundle.getLocation(), newCrc);
+                                }
+                            } finally {
+                                if (is != null) {
+                                    is.close();
+                                }
+                            }
+                        }
+                    }
+                    // We're done for this resource
+                    toDeploy.remove(resource);
+                    deployment.resToBnd.put(resource, bundle);
+                // There's no matching resource
+                // If the bundle is managed, we need to delete it
+                } else if (managed.contains(bundle.getBundleId())) {
+                    deployment.toDelete.add(bundle);
+                }
+            }
+        }
+
+        // Second pass on remaining resources
+        for (Resource resource : toDeploy) {
+            TreeMap<Version, Bundle> matching = new TreeMap<Version, Bundle>();
+            VersionRange range = new VersionRange(Macro.transform(bundleUpdateRange, getVersion(resource).toString()));
+            for (Bundle bundle : deployment.toDelete) {
+                if (bundle.getSymbolicName().equals(getSymbolicName(resource)) && range.contains(bundle.getVersion())) {
+                    matching.put(bundle.getVersion(), bundle);
+                }
+            }
+            if (!matching.isEmpty()) {
+                Bundle bundle = matching.lastEntry().getValue();
+                deployment.toUpdate.put(bundle, resource);
+                deployment.toDelete.remove(bundle);
+                deployment.resToBnd.put(resource, bundle);
+            } else {
+                deployment.toInstall.add(resource);
+            }
+        }
+        return deployment;
+    }
+
+    protected List<Resource> getBundles(Collection<Resource> allResources) {
+        Map<String, Resource> deploy = new TreeMap<String, Resource>();
+        for (Resource res : allResources) {
+            String uri = UriNamespace.getUri(res);
+            if (uri != null) {
+                deploy.put(uri, res);
+            }
+        }
+        return new ArrayList<Resource>(deploy.values());
+    }
+
+    protected List<Feature> getFeatures(Repository[] repositories, List<String> featureIds) throws Exception {
+        List<Feature> installedFeatures = new ArrayList<Feature>();
+        for (Repository repository : repositories) {
+            for (Feature feature : repository.getFeatures()) {
+                String id = feature.getName() + "/" + VersionTable.getVersion(feature.getVersion());
+                if (featureIds.contains(id)) {
+                    installedFeatures.add(feature);
+                }
+            }
+        }
+        return installedFeatures;
+    }
+
+    protected List<String> getFeatureIds(Collection<Resource> allResources) {
+        List<String> installedFeatureIds = new ArrayList<String>();
+        for (Resource resource : allResources) {
+            String name = FeatureNamespace.getName(resource);
+            if (name != null) {
+                Version version = FeatureNamespace.getVersion(resource);
+                String id = version != null ? name + "/" + version : name;
+                installedFeatureIds.add(id);
+            }
+        }
+        return installedFeatureIds;
+    }
+
+    protected DeploymentBuilder createDeploymentBuilder(Repository[] repositories) {
+        return new DeploymentBuilder(new SimpleDownloader(), Arrays.asList(repositories));
+    }
+
+
+    protected boolean isUpdateable(Resource resource) {
+        return (getVersion(resource).getQualifier().endsWith(SNAPSHOT) ||
+                UriNamespace.getUri(resource).contains(SNAPSHOT) ||
+                !UriNamespace.getUri(resource).contains(MAVEN));
+    }
+
+    protected List<Bundle> getBundlesToStart(Collection<Bundle> bundles) {
+        // TODO: make this pluggable ?
+        // TODO: honor respectStartLvlDuringFeatureStartup
+
+        // We hit FELIX-2949 if we don't use the correct order as Felix resolver isn't greedy.
+        // In order to minimize that, we make sure we resolve the bundles in the order they
+        // are given back by the resolution, meaning that all root bundles (i.e. those that were
+        // not flagged as dependencies in features) are started before the others.   This should
+        // make sure those important bundles are started first and minimize the problem.
+
+        // Restart the features service last, regardless of any other consideration
+        // so that we don't end up with the service trying to do stuff before we're done
+        boolean restart = bundles.remove(bundle);
+
+        List<BundleRevision> revs = new ArrayList<BundleRevision>();
+        for (Bundle bundle : bundles) {
+            revs.add(bundle.adapt(BundleRevision.class));
+        }
+        List<Bundle> sorted = new ArrayList<Bundle>();
+        for (BundleRevision rev : RequirementSort.sort(revs)) {
+            sorted.add(rev.getBundle());
+        }
+        if (restart) {
+            sorted.add(bundle);
+        }
+        return sorted;
+    }
+
+    protected List<Bundle> getBundlesToStop(Collection<Bundle> bundles) {
+        // TODO: make this pluggable ?
+        // TODO: honor respectStartLvlDuringFeatureUninstall
+
+        List<Bundle> bundlesToDestroy = new ArrayList<Bundle>();
+        for (Bundle bundle : bundles) {
+            ServiceReference[] references = bundle.getRegisteredServices();
+            int usage = 0;
+            if (references != null) {
+                for (ServiceReference reference : references) {
+                    usage += getServiceUsage(reference, bundles);
+                }
+            }
+            LOGGER.debug("Usage for bundle {} is {}", bundle, usage);
+            if (usage == 0) {
+                bundlesToDestroy.add(bundle);
+            }
+        }
+        if (!bundlesToDestroy.isEmpty()) {
+            Collections.sort(bundlesToDestroy, new Comparator<Bundle>() {
+                public int compare(Bundle b1, Bundle b2) {
+                    return (int) (b2.getLastModified() - b1.getLastModified());
+                }
+            });
+            LOGGER.debug("Selected bundles {} for destroy (no services in use)", bundlesToDestroy);
+        } else {
+            ServiceReference ref = null;
+            for (Bundle bundle : bundles) {
+                ServiceReference[] references = bundle.getRegisteredServices();
+                for (ServiceReference reference : references) {
+                    if (getServiceUsage(reference, bundles) == 0) {
+                        continue;
+                    }
+                    if (ref == null || reference.compareTo(ref) < 0) {
+                        LOGGER.debug("Currently selecting bundle {} for destroy (with reference {})", bundle, reference);
+                        ref = reference;
+                    }
+                }
+            }
+            if (ref != null) {
+                bundlesToDestroy.add(ref.getBundle());
+            }
+            LOGGER.debug("Selected bundle {} for destroy (lowest ranking service)", bundlesToDestroy);
+        }
+        return bundlesToDestroy;
+    }
+
+    private static int getServiceUsage(ServiceReference ref, Collection<Bundle> bundles) {
+        Bundle[] usingBundles = ref.getUsingBundles();
+        int nb = 0;
+        if (usingBundles != null) {
+            for (Bundle bundle : usingBundles) {
+                if (bundles.contains(bundle)) {
+                    nb++;
+                }
+            }
+        }
+        return nb;
+    }
+
+    protected InputStream getBundleInputStream(Resource resource, Map<String, StreamProvider> providers) throws IOException {
+        String uri = UriNamespace.getUri(resource);
+        if (uri == null) {
+            throw new IllegalStateException("Resource has no uri");
+        }
+        StreamProvider provider = providers.get(uri);
+        if (provider == null) {
+            throw new IllegalStateException("Resource " + uri + " has no StreamProvider");
+        }
+        return provider.open();
+    }
+
+    protected void findBundlesWithOptionalPackagesToRefresh(Set<Bundle> toRefresh) {
+        // First pass: include all bundles contained in these features
+        if (toRefresh.isEmpty()) {
+            return;
+        }
+        Set<Bundle> bundles = new HashSet<Bundle>(Arrays.asList(systemBundleContext.getBundles()));
+        bundles.removeAll(toRefresh);
+        if (bundles.isEmpty()) {
+            return;
+        }
+        // Second pass: for each bundle, check if there is any unresolved optional package that could be resolved
+        for (Bundle bundle : bundles) {
+            BundleRevision rev = bundle.adapt(BundleRevision.class);
+            boolean matches = false;
+            if (rev != null) {
+                for (BundleRequirement req : rev.getDeclaredRequirements(null)) {
+                    if (PackageNamespace.PACKAGE_NAMESPACE.equals(req.getNamespace())
+                            && PackageNamespace.RESOLUTION_OPTIONAL.equals(req.getDirectives().get(PackageNamespace.REQUIREMENT_RESOLUTION_DIRECTIVE))) {
+                        // This requirement is an optional import package
+                        for (Bundle provider : toRefresh) {
+                            BundleRevision providerRev = provider.adapt(BundleRevision.class);
+                            if (providerRev != null) {
+                                for (BundleCapability cap : providerRev.getDeclaredCapabilities(null)) {
+                                    if (req.matches(cap)) {
+                                        matches = true;
+                                        break;
+                                    }
+                                }
+                            }
+                            if (matches) {
+                                break;
+                            }
+                        }
+                    }
+                    if (matches) {
+                        break;
+                    }
+                }
+            }
+            if (matches) {
+                toRefresh.add(bundle);
+            }
+        }
+    }
+
+    protected void findBundlesWithFragmentsToRefresh(Set<Bundle> toRefresh) {
+        if (toRefresh.isEmpty()) {
+            return;
+        }
+        Set<Bundle> bundles = new HashSet<Bundle>(Arrays.asList(systemBundleContext.getBundles()));
+        bundles.removeAll(toRefresh);
+        if (bundles.isEmpty()) {
+            return;
+        }
+        for (Bundle bundle : new ArrayList<Bundle>(toRefresh)) {
+            BundleRevision rev = bundle.adapt(BundleRevision.class);
+            if (rev != null) {
+                for (BundleRequirement req : rev.getDeclaredRequirements(null)) {
+                    if (BundleRevision.HOST_NAMESPACE.equals(req.getNamespace())) {
+                        for (Bundle hostBundle : bundles) {
+                            if (!toRefresh.contains(hostBundle)) {
+                                BundleRevision hostRev = hostBundle.adapt(BundleRevision.class);
+                                if (hostRev != null) {
+                                    for (BundleCapability cap : hostRev.getDeclaredCapabilities(null)) {
+                                        if (req.matches(cap)) {
+                                            toRefresh.add(hostBundle);
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    protected void refreshPackages(Collection<Bundle> bundles) throws InterruptedException {
+        final CountDownLatch latch = new CountDownLatch(1);
+        FrameworkWiring fw = systemBundleContext.getBundle().adapt(FrameworkWiring.class);
+        fw.refreshBundles(bundles, new FrameworkListener() {
+            @Override
+            public void frameworkEvent(FrameworkEvent event) {
+                if (event.getType() == FrameworkEvent.ERROR) {
+                    LOGGER.error("Framework error", event.getThrowable());
+                }
+                latch.countDown();
+            }
+        });
+        latch.await();
+    }
+
+
+    static class Deployment {
+        Map<String, Long> newCheckums = new HashMap<String, Long>();
+        Map<Resource, Bundle> resToBnd = new HashMap<Resource, Bundle>();
+        List<Resource> toInstall = new ArrayList<Resource>();
+        List<Bundle> toDelete = new ArrayList<Bundle>();
+        Map<Bundle, Resource> toUpdate = new HashMap<Bundle, Resource>();
+    }
+
+}


[16/59] [abbrv] [KARAF-2852] Merge features/core and features/command

Posted by gn...@apache.org.
http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/core/NOTICE
----------------------------------------------------------------------
diff --git a/features/core/NOTICE b/features/core/NOTICE
deleted file mode 100644
index b70f1f9..0000000
--- a/features/core/NOTICE
+++ /dev/null
@@ -1,71 +0,0 @@
-Apache Karaf
-Copyright 2010-2014 The Apache Software Foundation
-
-
-I. Included Software
-
-This product includes software developed at
-The Apache Software Foundation (http://www.apache.org/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-The OSGi Alliance (http://www.osgi.org/).
-Copyright (c) OSGi Alliance (2000, 2010).
-Licensed under the Apache License 2.0.
-
-This product includes software developed at
-OW2 (http://www.ow2.org/).
-Licensed under the BSD License.
-
-This product includes software developed at
-OPS4J (http://www.ops4j.org/).
-Licensed under the Apache License 2.0.
-
-This product includes software developed at
-Eclipse Foundation (http://www.eclipse.org/).
-Licensed under the EPL.
-
-This product includes software written by
-Antony Lesuisse.
-Licensed under Public Domain.
-
-
-II. Used Software
-
-This product uses software developed at
-FUSE Source (http://www.fusesource.org/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-AOP Alliance (http://aopalliance.sourceforge.net/).
-Licensed under the Public Domain.
-
-This product uses software developed at
-Tanuki Software (http://www.tanukisoftware.com/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-Jasypt (http://jasypt.sourceforge.net/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-JLine (http://jline.sourceforge.net).
-Licensed under the BSD License.
-
-This product uses software developed at
-SLF4J (http://www.slf4j.org/).
-Licensed under the MIT License.
-
-This product uses software developed at
-SpringSource (http://www.springsource.org/).
-Licensed under the Apache License 2.0.
-
-This product includes software from http://www.json.org.
-Copyright (c) 2002 JSON.org
-
-
-III. License Summary
-- Apache License 2.0
-- BSD License
-- EPL License
-- MIT License

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/core/pom.xml
----------------------------------------------------------------------
diff --git a/features/core/pom.xml b/features/core/pom.xml
deleted file mode 100644
index fc9f9ce..0000000
--- a/features/core/pom.xml
+++ /dev/null
@@ -1,138 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-
-    <!--
-
-        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.
-    -->
-
-    <modelVersion>4.0.0</modelVersion>
-
-    <parent>
-        <groupId>org.apache.karaf.features</groupId>
-        <artifactId>features</artifactId>
-        <version>4.0.0-SNAPSHOT</version>
-        <relativePath>../pom.xml</relativePath>
-    </parent>
-
-    <artifactId>org.apache.karaf.features.core</artifactId>
-    <packaging>bundle</packaging>
-    <name>Apache Karaf :: Features :: Core</name>
-    <description>This bundle is the core implementation of the Karaf features support.</description>
-
-    <properties>
-        <appendedResourcesDirectory>${basedir}/../../etc/appended-resources</appendedResourcesDirectory>
-    </properties>
-
-    <dependencies>
-        <dependency>
-            <groupId>org.osgi</groupId>
-            <artifactId>org.osgi.core</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.osgi</groupId>
-            <artifactId>org.osgi.compendium</artifactId>
-            <scope>provided</scope>
-            <optional>true</optional>
-        </dependency>
-
-        <dependency>
-            <groupId>org.apache.felix</groupId>
-            <artifactId>org.apache.felix.utils</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.slf4j</groupId>
-            <artifactId>slf4j-api</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.karaf</groupId>
-            <artifactId>org.apache.karaf.util</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.felix</groupId>
-            <artifactId>org.apache.felix.resolver</artifactId>
-            <scope>provided</scope>
-        </dependency>
-
-        <dependency>
-            <groupId>org.slf4j</groupId>
-            <artifactId>slf4j-jdk14</artifactId>
-            <scope>test</scope>
-        </dependency>
-
-        <dependency>
-            <groupId>org.ops4j.pax.tinybundles</groupId>
-            <artifactId>tinybundles</artifactId>
-            <scope>test</scope>
-        </dependency>
-    </dependencies>
-
-    <build>
-        <resources>
-            <resource>
-                <directory>${project.basedir}/src/main/resources</directory>
-                <includes>
-                    <include>**/*</include>
-                </includes>
-            </resource>
-            <resource>
-                <directory>${project.basedir}/src/main/resources</directory>
-                <filtering>true</filtering>
-                <includes>
-                    <include>**/*.info</include>
-                </includes>
-            </resource>
-        </resources>
-        <plugins>
-            <plugin>
-                <groupId>org.apache.felix</groupId>
-                <artifactId>maven-bundle-plugin</artifactId>
-                <configuration>
-                    <instructions>
-                        <Export-Package>
-                            org.apache.karaf.features;
-                            org.apache.karaf.features.management;
-                            org.apache.karaf.features.management.codec;
-                                -noimport:=true
-                        </Export-Package>
-                        <Provide-Capability>
-                            service-reference;effective:=active;objectClass=org.apache.karaf.features.FeaturesService
-                        </Provide-Capability>
-                        <Private-Package>
-                            org.apache.karaf.features.internal.*,
-                            org.apache.felix.resolver,
-                            org.apache.felix.utils.version,
-                            org.apache.felix.utils.manifest,
-                            org.apache.karaf.util.collections,
-                            org.apache.karaf.util.json,
-                            org.apache.karaf.util.tracker,
-                            org.osgi.service.resolver,
-                            org.osgi.service.repository
-                        </Private-Package>
-                        <Bundle-Activator>
-                            org.apache.karaf.features.internal.osgi.Activator
-                        </Bundle-Activator>
-                    </instructions>
-                </configuration>
-            </plugin>
-        </plugins>
-    </build>
-
-</project>

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/core/src/main/java/org/apache/karaf/features/BootFinished.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/BootFinished.java b/features/core/src/main/java/org/apache/karaf/features/BootFinished.java
deleted file mode 100644
index aa72248..0000000
--- a/features/core/src/main/java/org/apache/karaf/features/BootFinished.java
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * 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.karaf.features;
-
-/**
- * Marker interface for a service that announces when the karaf boot is finished
- */
-public interface BootFinished {
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/core/src/main/java/org/apache/karaf/features/BundleInfo.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/BundleInfo.java b/features/core/src/main/java/org/apache/karaf/features/BundleInfo.java
deleted file mode 100644
index 97a541f..0000000
--- a/features/core/src/main/java/org/apache/karaf/features/BundleInfo.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * 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.karaf.features;
-
-/**
- * A bundle info holds info about a Bundle.
- */
-public interface BundleInfo {
-
-	String getLocation();
-	
-    int getStartLevel();
-    
-    boolean isStart();
-
-    boolean isDependency();
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/core/src/main/java/org/apache/karaf/features/Capability.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/Capability.java b/features/core/src/main/java/org/apache/karaf/features/Capability.java
deleted file mode 100644
index d329708..0000000
--- a/features/core/src/main/java/org/apache/karaf/features/Capability.java
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * 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.karaf.features;
-
-public interface Capability {
-
-    String getValue();
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/core/src/main/java/org/apache/karaf/features/Conditional.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/Conditional.java b/features/core/src/main/java/org/apache/karaf/features/Conditional.java
deleted file mode 100644
index c0e4d59..0000000
--- a/features/core/src/main/java/org/apache/karaf/features/Conditional.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * 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.karaf.features;
-
-import java.util.List;
-import java.util.Map;
-
-public interface Conditional {
-
-    List<? extends Dependency> getCondition();
-
-    List<Dependency> getDependencies();
-
-    List<BundleInfo> getBundles();
-
-    Map<String, Map<String, String>> getConfigurations();
-
-    List<ConfigFileInfo> getConfigurationFiles();
-
-    Feature asFeature(String name, String version);
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/core/src/main/java/org/apache/karaf/features/ConfigFileInfo.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/ConfigFileInfo.java b/features/core/src/main/java/org/apache/karaf/features/ConfigFileInfo.java
deleted file mode 100644
index 960fb31..0000000
--- a/features/core/src/main/java/org/apache/karaf/features/ConfigFileInfo.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * 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.karaf.features;
-
-public interface ConfigFileInfo {
-	
-	String getLocation();
-	
-	String getFinalname();
-	
-	boolean isOverride();
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/core/src/main/java/org/apache/karaf/features/Dependency.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/Dependency.java b/features/core/src/main/java/org/apache/karaf/features/Dependency.java
deleted file mode 100644
index cafdd92..0000000
--- a/features/core/src/main/java/org/apache/karaf/features/Dependency.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * 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.karaf.features;
-
-public interface Dependency {
-
-    String getName();
-
-    String getVersion();
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/core/src/main/java/org/apache/karaf/features/EventConstants.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/EventConstants.java b/features/core/src/main/java/org/apache/karaf/features/EventConstants.java
deleted file mode 100644
index f83f185..0000000
--- a/features/core/src/main/java/org/apache/karaf/features/EventConstants.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * 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.karaf.features;
-
-/**
- * Constants for EventAdmin events
- */
-public final class EventConstants {
-
-    public static final String TYPE = "type";
-    public static final String EVENT = "event";
-    public static final String TIMESTAMP = "timestamp";
-
-    public static final String FEATURE_NAME = "name";
-    public static final String FEATURE_VERSION = "version";
-
-    public static final String REPOSITORY_NAME = "name";
-    public static final String REPOSITORY_URI = "uri";
-
-    public static final String TOPIC_EVENTS = "org/apache/karaf/features";
-    public static final String TOPIC_FEATURES_INSTALLED = TOPIC_EVENTS + "/features/INSTALLED";
-    public static final String TOPIC_FEATURES_UNINSTALLED = TOPIC_EVENTS + "/features/UNINSTALLED";
-    public static final String TOPIC_REPOSITORY_ADDED = TOPIC_EVENTS + "/repositories/ADDED";
-    public static final String TOPIC_REPOSITORY_REMOVED = TOPIC_EVENTS + "/repositories/REMOVED";
-
-    private EventConstants() {
-        // non-instantiable class
-    }
-
-
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/core/src/main/java/org/apache/karaf/features/Feature.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/Feature.java b/features/core/src/main/java/org/apache/karaf/features/Feature.java
deleted file mode 100644
index 2f9f001..0000000
--- a/features/core/src/main/java/org/apache/karaf/features/Feature.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * 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.karaf.features;
-
-import java.util.List;
-import java.util.Map;
-
-/**
- * A feature is a list of bundles associated identified by its name.
- */
-public interface Feature {
-
-    public static String DEFAULT_INSTALL_MODE = "auto";
-
-    String getId();
-
-    String getName();
-
-    String getDescription();
-
-    String getDetails();
-
-    String getVersion();
-
-    boolean hasVersion();
-
-    String getResolver();
-
-    String getInstall();
-
-    List<Dependency> getDependencies();
-
-    List<BundleInfo> getBundles();
-
-    Map<String, Map<String, String>> getConfigurations();
-
-    List<ConfigFileInfo> getConfigurationFiles();
-
-    List<? extends Conditional> getConditional();
-    
-    int getStartLevel();
-
-    String getRegion();
-
-    List<? extends Capability> getCapabilities();
-
-    List<? extends Requirement> getRequirements();
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/core/src/main/java/org/apache/karaf/features/FeatureEvent.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/FeatureEvent.java b/features/core/src/main/java/org/apache/karaf/features/FeatureEvent.java
deleted file mode 100644
index 516c988..0000000
--- a/features/core/src/main/java/org/apache/karaf/features/FeatureEvent.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * 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.karaf.features;
-
-import java.util.EventObject;
-
-public class FeatureEvent extends EventObject {
-
-    public static enum EventType {
-        FeatureInstalled,
-        FeatureUninstalled
-    }
-
-    private final EventType type;
-    private final Feature feature;
-    private final boolean replay;
-
-    public FeatureEvent(Feature feature, EventType type, boolean replay) {
-        super(feature);
-        this.type = type;
-        this.feature = feature;
-        this.replay = replay;
-    }
-
-    public EventType getType() {
-        return type;
-    }
-
-    public Feature getFeature() {
-        return feature;
-    }
-
-    public boolean isReplay() {
-        return replay;
-    }
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/core/src/main/java/org/apache/karaf/features/FeaturesListener.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/FeaturesListener.java b/features/core/src/main/java/org/apache/karaf/features/FeaturesListener.java
deleted file mode 100644
index 69f68c6..0000000
--- a/features/core/src/main/java/org/apache/karaf/features/FeaturesListener.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * 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.karaf.features;
-
-public interface FeaturesListener {
-
-    void featureEvent(FeatureEvent event);
-
-    void repositoryEvent(RepositoryEvent event);
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/core/src/main/java/org/apache/karaf/features/FeaturesNamespaces.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/FeaturesNamespaces.java b/features/core/src/main/java/org/apache/karaf/features/FeaturesNamespaces.java
deleted file mode 100644
index 282ff71..0000000
--- a/features/core/src/main/java/org/apache/karaf/features/FeaturesNamespaces.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * 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.karaf.features;
-
-import javax.xml.namespace.QName;
-
-/**
- * Provides features XML/XSD constants.
- */
-public interface FeaturesNamespaces {
-
-    String URI_0_0_0 = "";
-    String URI_1_0_0 = "http://karaf.apache.org/xmlns/features/v1.0.0";
-    String URI_1_1_0 = "http://karaf.apache.org/xmlns/features/v1.1.0";
-    String URI_1_2_0 = "http://karaf.apache.org/xmlns/features/v1.2.0";
-    String URI_1_3_0 = "http://karaf.apache.org/xmlns/features/v1.3.0";
-
-    String URI_CURRENT = URI_1_3_0;
-
-    QName FEATURES_0_0_0 = new QName("features");
-    QName FEATURES_1_0_0 = new QName(URI_1_0_0, "features");
-    QName FEATURES_1_1_0 = new QName(URI_1_1_0, "features");
-    QName FEATURES_1_2_0 = new QName(URI_1_2_0, "features");
-    QName FEATURES_1_3_0 = new QName(URI_1_3_0, "features");
-
-    QName FEATURES_CURRENT = FEATURES_1_3_0;
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/core/src/main/java/org/apache/karaf/features/FeaturesService.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/FeaturesService.java b/features/core/src/main/java/org/apache/karaf/features/FeaturesService.java
deleted file mode 100644
index ef3dbcf..0000000
--- a/features/core/src/main/java/org/apache/karaf/features/FeaturesService.java
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * 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.karaf.features;
-
-import java.net.URI;
-import java.util.EnumSet;
-import java.util.Set;
-
-/**
- * The service managing features repositories.
- */
-public interface FeaturesService {
-
-    enum Option {
-        NoFailOnFeatureNotFound,
-        NoAutoRefreshManagedBundles,
-        NoAutoRefreshUnmanagedBundles,
-        NoAutoRefreshBundles,
-        NoAutoStartBundles,
-        Simulate,
-        Verbose
-    }
-
-    /**
-     * Validate repository contents.
-     * 
-     * @param uri Repository uri.
-     * @throws Exception When validation fails.
-     */
-    void validateRepository(URI uri) throws Exception;
-
-    void addRepository(URI uri) throws Exception;
-
-    void addRepository(URI uri, boolean install) throws Exception;
-
-    void removeRepository(URI uri) throws Exception;
-
-    void removeRepository(URI uri, boolean uninstall) throws Exception;
-    
-    void restoreRepository(URI uri) throws Exception;
-
-    Repository[] listRequiredRepositories() throws Exception;
-
-    Repository[] listRepositories() throws Exception;
-    
-    Repository getRepository(String repoName) throws Exception;
-
-    void installFeature(String name) throws Exception;
-
-    void installFeature(String name, EnumSet<Option> options) throws Exception;
-    
-    void installFeature(String name, String version) throws Exception;
-
-    void installFeature(String name, String version, EnumSet<Option> options) throws Exception;
-
-    void installFeature(Feature f, EnumSet<Option> options) throws Exception;
-
-    void installFeatures(Set<String> features, EnumSet<Option> options) throws Exception;
-
-    void uninstallFeature(String name, EnumSet<Option> options) throws Exception;
-
-    void uninstallFeature(String name) throws Exception;
-
-    void uninstallFeature(String name, String version, EnumSet<Option> options) throws Exception;
-    
-    void uninstallFeature(String name, String version) throws Exception;
-
-    void uninstallFeatures(Set<String> features, EnumSet<Option> options) throws Exception;
-
-    Feature[] listFeatures() throws Exception;
-
-    Feature[] listRequiredFeatures() throws Exception;
-
-    Feature[] listInstalledFeatures() throws Exception;
-
-    boolean isRequired(Feature f);
-
-    boolean isInstalled(Feature f);
-
-    Feature getFeature(String name, String version) throws Exception;
-
-    Feature getFeature(String name) throws Exception;
-
-	void refreshRepository(URI uri) throws Exception;
-
-    public URI getRepositoryUriFor(String name, String version);
-
-    public String[] getRepositoryNames();
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/core/src/main/java/org/apache/karaf/features/RegionsPersistence.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/RegionsPersistence.java b/features/core/src/main/java/org/apache/karaf/features/RegionsPersistence.java
deleted file mode 100644
index 96ca7da..0000000
--- a/features/core/src/main/java/org/apache/karaf/features/RegionsPersistence.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * 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.karaf.features;
-
-import org.osgi.framework.Bundle;
-import org.osgi.framework.BundleException;
-
-public interface RegionsPersistence {
-    void install(Bundle b, String regionName) throws BundleException;
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/core/src/main/java/org/apache/karaf/features/Repository.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/Repository.java b/features/core/src/main/java/org/apache/karaf/features/Repository.java
deleted file mode 100644
index 6ee96da..0000000
--- a/features/core/src/main/java/org/apache/karaf/features/Repository.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * 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.karaf.features;
-
-import java.net.URI;
-
-/**
- * A repository of features.
- */
-public interface Repository {
-
-    String getName();
-
-    URI getURI();
-
-    URI[] getRepositories() throws Exception;
-
-    Feature[] getFeatures() throws Exception;
-    
-    boolean isValid();
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/core/src/main/java/org/apache/karaf/features/RepositoryEvent.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/RepositoryEvent.java b/features/core/src/main/java/org/apache/karaf/features/RepositoryEvent.java
deleted file mode 100644
index 68f287b..0000000
--- a/features/core/src/main/java/org/apache/karaf/features/RepositoryEvent.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * 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.karaf.features;
-
-import java.util.EventObject;
-
-public class RepositoryEvent extends EventObject {
-
-    public static enum EventType {
-        RepositoryAdded,
-        RepositoryRemoved,
-    }
-
-    private final EventType type;
-    private final Repository repository;
-    private final boolean replay;
-
-    public RepositoryEvent(Repository repository, EventType type, boolean replay) {
-        super(repository);
-        this.type = type;
-        this.repository = repository;
-        this.replay = replay;
-    }
-
-    public EventType getType() {
-        return type;
-    }
-
-    public Repository getRepository() {
-        return repository;
-    }
-
-    public boolean isReplay() {
-        return replay;
-    }
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/core/src/main/java/org/apache/karaf/features/Requirement.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/Requirement.java b/features/core/src/main/java/org/apache/karaf/features/Requirement.java
deleted file mode 100644
index 4446335..0000000
--- a/features/core/src/main/java/org/apache/karaf/features/Requirement.java
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * 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.karaf.features;
-
-public interface Requirement {
-
-    String getValue();
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/core/src/main/java/org/apache/karaf/features/Resolver.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/Resolver.java b/features/core/src/main/java/org/apache/karaf/features/Resolver.java
deleted file mode 100644
index d2fa941..0000000
--- a/features/core/src/main/java/org/apache/karaf/features/Resolver.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * 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.karaf.features;
-
-import java.util.List;
-
-public interface Resolver {
-
-    List<BundleInfo> resolve(Feature feature) throws Exception;
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/core/src/main/java/org/apache/karaf/features/internal/deployment/DeploymentBuilder.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/deployment/DeploymentBuilder.java b/features/core/src/main/java/org/apache/karaf/features/internal/deployment/DeploymentBuilder.java
deleted file mode 100644
index 00a91c4..0000000
--- a/features/core/src/main/java/org/apache/karaf/features/internal/deployment/DeploymentBuilder.java
+++ /dev/null
@@ -1,334 +0,0 @@
-/*
- * 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.karaf.features.internal.deployment;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.jar.Attributes;
-import java.util.jar.Manifest;
-import java.util.zip.ZipEntry;
-import java.util.zip.ZipInputStream;
-
-import org.apache.felix.resolver.ResolverImpl;
-import org.apache.felix.utils.version.VersionRange;
-import org.apache.felix.utils.version.VersionTable;
-import org.apache.karaf.features.BundleInfo;
-import org.apache.karaf.features.Conditional;
-import org.apache.karaf.features.Dependency;
-import org.apache.karaf.features.Feature;
-import org.apache.karaf.features.Repository;
-import org.apache.karaf.features.internal.repository.AggregateRepository;
-import org.apache.karaf.features.internal.repository.StaticRepository;
-import org.apache.karaf.features.internal.resolver.FeatureNamespace;
-import org.apache.karaf.features.internal.resolver.FeatureResource;
-import org.apache.karaf.features.internal.resolver.RequirementImpl;
-import org.apache.karaf.features.internal.resolver.ResolveContextImpl;
-import org.apache.karaf.features.internal.resolver.ResourceBuilder;
-import org.apache.karaf.features.internal.resolver.ResourceImpl;
-import org.apache.karaf.features.internal.resolver.Slf4jResolverLog;
-import org.apache.karaf.features.internal.service.Overrides;
-import org.apache.karaf.features.internal.util.Macro;
-import org.apache.karaf.features.internal.util.MultiException;
-import org.osgi.framework.BundleException;
-import org.osgi.framework.Version;
-import org.osgi.framework.namespace.IdentityNamespace;
-import org.osgi.resource.Capability;
-import org.osgi.resource.Requirement;
-import org.osgi.resource.Resource;
-import org.osgi.resource.Wire;
-import org.osgi.service.resolver.ResolutionException;
-import org.osgi.service.resolver.ResolveContext;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- */
-public class DeploymentBuilder {
-
-    private static final Logger LOGGER = LoggerFactory.getLogger(DeploymentBuilder.class);
-
-    public static final String REQ_PROTOCOL = "req:";
-
-    private final Collection<Repository> repositories;
-
-    private final List<org.osgi.service.repository.Repository> resourceRepos;
-
-    String featureRange = "${range;[====,====]}";
-
-    Downloader downloader;
-    ResourceImpl requirements;
-    Map<String, Resource> resources;
-    Set<Resource> optionals;
-    Map<String, StreamProvider> providers;
-
-    Set<Feature> featuresToRegister = new HashSet<Feature>();
-
-    public DeploymentBuilder(Downloader downloader,
-                             Collection<Repository> repositories) {
-        this.downloader = downloader;
-        this.repositories = repositories;
-        this.resourceRepos = new ArrayList<org.osgi.service.repository.Repository>();
-    }
-
-    public void addResourceRepository(org.osgi.service.repository.Repository repository) {
-        resourceRepos.add(repository);
-    }
-
-    public Map<String, StreamProvider> getProviders() {
-        return providers;
-    }
-
-    public void setFeatureRange(String featureRange) {
-        this.featureRange = featureRange;
-    }
-
-    public Map<String, Resource> download(
-                         Set<String> features,
-                         Set<String> bundles,
-                         Set<String> reqs,
-                         Set<String> overrides,
-                         Set<String> optionals)
-                throws IOException, MultiException, InterruptedException, ResolutionException, BundleException {
-        this.resources = new ConcurrentHashMap<String, Resource>();
-        this.optionals = new HashSet<Resource>();
-        this.providers = new ConcurrentHashMap<String, StreamProvider>();
-        this.requirements = new ResourceImpl("dummy", "dummy", Version.emptyVersion);
-        // First, gather all bundle resources
-        for (String feature : features) {
-            registerMatchingFeatures(feature);
-        }
-        for (String bundle : bundles) {
-            downloadAndBuildResource(bundle);
-        }
-        for (String req : reqs) {
-            buildRequirement(req);
-        }
-        for (String override : overrides) {
-            // TODO: ignore download failures for overrides
-            downloadAndBuildResource(Overrides.extractUrl(override));
-        }
-        for (String optional : optionals) {
-            downloadAndBuildResource(optional);
-        }
-        // Wait for all resources to be created
-        downloader.await();
-        // Do override replacement
-        Overrides.override(resources, overrides);
-        // Build features resources
-        for (Feature feature : featuresToRegister) {
-            Resource resource = FeatureResource.build(feature, featureRange, resources);
-            resources.put("feature:" + feature.getName() + "/" + feature.getVersion(), resource);
-            for (Conditional cond : feature.getConditional()) {
-                this.optionals.add(FeatureResource.build(feature, cond, featureRange, resources));
-            }
-        }
-        // Build requirements
-        for (String feature : features) {
-            requireFeature(feature);
-        }
-        for (String bundle : bundles) {
-            requireResource(bundle);
-        }
-        for (String req : reqs) {
-            requireResource(REQ_PROTOCOL + req);
-        }
-        return resources;
-    }
-
-    public Map<Resource, List<Wire>> resolve(List<Resource> systemBundles,
-                                        boolean resolveOptionalImports) throws ResolutionException {
-        // Resolve
-        for (int i = 0; i < systemBundles.size(); i++) {
-            resources.put("system-bundle-" + i, systemBundles.get(i));
-        }
-
-        List<org.osgi.service.repository.Repository> repos = new ArrayList<org.osgi.service.repository.Repository>();
-        repos.add(new StaticRepository(resources.values()));
-        repos.addAll(resourceRepos);
-
-        ResolverImpl resolver = new ResolverImpl(new Slf4jResolverLog(LOGGER));
-        ResolveContext context = new ResolveContextImpl(
-                Collections.<Resource>singleton(requirements),
-                this.optionals,
-                new AggregateRepository(repos),
-                resolveOptionalImports);
-
-        return resolver.resolve(context);
-    }
-
-    public void requireFeature(String feature) throws IOException {
-        // Find name and version range
-        String[] split = feature.split("/");
-        String name = split[0].trim();
-        String version = (split.length > 1) ? split[1].trim() : null;
-        if (version != null && !version.equals("0.0.0") && !version.startsWith("[") && !version.startsWith("(")) {
-            version = Macro.transform(featureRange, version);
-        }
-        VersionRange range = version != null ? new VersionRange(version) : VersionRange.ANY_VERSION;
-        // Add requirement
-        Map<String, Object> attrs = new HashMap<String, Object>();
-        attrs.put(IdentityNamespace.IDENTITY_NAMESPACE, name);
-        attrs.put(IdentityNamespace.CAPABILITY_TYPE_ATTRIBUTE, FeatureNamespace.TYPE_FEATURE);
-        attrs.put(IdentityNamespace.CAPABILITY_VERSION_ATTRIBUTE, range);
-        requirements.addRequirement(
-                new RequirementImpl(requirements, IdentityNamespace.IDENTITY_NAMESPACE,
-                        Collections.<String, String>emptyMap(), attrs)
-        );
-    }
-
-    public void requireResource(String location) {
-        Resource res = resources.get(location);
-        if (res == null) {
-            throw new IllegalStateException("Could not find resource for " + location);
-        }
-        List<Capability> caps = res.getCapabilities(IdentityNamespace.IDENTITY_NAMESPACE);
-        if (caps.size() != 1) {
-            throw new IllegalStateException("Resource does not have a single " + IdentityNamespace.IDENTITY_NAMESPACE + " capability");
-        }
-        Capability cap = caps.get(0);
-        // Add requirement
-        Map<String, Object> attrs = new HashMap<String, Object>();
-        attrs.put(IdentityNamespace.IDENTITY_NAMESPACE, cap.getAttributes().get(IdentityNamespace.IDENTITY_NAMESPACE));
-        attrs.put(IdentityNamespace.CAPABILITY_TYPE_ATTRIBUTE, cap.getAttributes().get(IdentityNamespace.CAPABILITY_TYPE_ATTRIBUTE));
-        attrs.put(IdentityNamespace.CAPABILITY_VERSION_ATTRIBUTE, new VersionRange((Version) cap.getAttributes().get(IdentityNamespace.CAPABILITY_VERSION_ATTRIBUTE), true));
-        requirements.addRequirement(
-                new RequirementImpl(requirements, IdentityNamespace.IDENTITY_NAMESPACE,
-                        Collections.<String, String>emptyMap(), attrs));
-
-    }
-
-    public void registerMatchingFeatures(String feature) throws IOException {
-        // Find name and version range
-        String[] split = feature.split("/");
-        String name = split[0].trim();
-        String version = (split.length > 1)
-                ? split[1].trim() : Version.emptyVersion.toString();
-        // Register matching features
-        registerMatchingFeatures(name, new VersionRange(version));
-    }
-
-    public void registerMatchingFeatures(String name, String version) throws IOException {
-        if (version != null && !version.equals("0.0.0") && !version.startsWith("[") && !version.startsWith("(")) {
-            version = Macro.transform(featureRange, version);
-        }
-        registerMatchingFeatures(name, version != null ? new VersionRange(version) : VersionRange.ANY_VERSION);
-    }
-
-    public void registerMatchingFeatures(String name, VersionRange range) throws IOException {
-        for (Repository repo : repositories) {
-            Feature[] features;
-            try {
-                features = repo.getFeatures();
-            } catch (Exception e) {
-                // This should not happen as the repository has been loaded already
-                throw new IllegalStateException(e);
-            }
-            for (Feature f : features) {
-                if (name.equals(f.getName())) {
-                    Version v = VersionTable.getVersion(f.getVersion());
-                    if (range.contains(v)) {
-                        featuresToRegister.add(f);
-                        for (Dependency dep : f.getDependencies()) {
-                            registerMatchingFeatures(dep.getName(), dep.getVersion());
-                        }
-                        for (BundleInfo bundle : f.getBundles()) {
-                            downloadAndBuildResource(bundle.getLocation());
-                        }
-                        for (Conditional cond : f.getConditional()) {
-                            Feature c = cond.asFeature(f.getName(), f.getVersion());
-                            featuresToRegister.add(c);
-                            for (BundleInfo bundle : c.getBundles()) {
-                                downloadAndBuildResource(bundle.getLocation());
-                            }
-                        }
-                    }
-                }
-            }
-        }
-    }
-
-    public void buildRequirement(String requirement) {
-        try {
-            String location = REQ_PROTOCOL + requirement;
-            ResourceImpl resource = new ResourceImpl(location, "dummy", Version.emptyVersion);
-            for (Requirement req : ResourceBuilder.parseRequirement(resource, requirement)) {
-                resource.addRequirement(req);
-            }
-            resources.put(location, resource);
-        } catch (BundleException e) {
-            throw new IllegalArgumentException("Error parsing requirement: " + requirement, e);
-        }
-    }
-
-    public void downloadAndBuildResource(final String location) throws IOException {
-        if (!resources.containsKey(location)) {
-            downloader.download(location, new Downloader.DownloadCallback() {
-                @Override
-                public void downloaded(StreamProvider provider) throws Exception {
-                    manageResource(location, provider);
-                }
-            });
-        }
-    }
-
-    private void manageResource(String location, StreamProvider provider) throws Exception {
-        if (!resources.containsKey(location)) {
-            Attributes attributes = getAttributes(location, provider);
-            Resource resource = createResource(location, attributes);
-            resources.put(location, resource);
-            providers.put(location, provider);
-        }
-    }
-
-    private Resource createResource(String uri, Attributes attributes) throws Exception {
-        Map<String, String> headers = new HashMap<String, String>();
-        for (Map.Entry attr : attributes.entrySet()) {
-            headers.put(attr.getKey().toString(), attr.getValue().toString());
-        }
-        try {
-            return ResourceBuilder.build(uri, headers);
-        } catch (BundleException e) {
-            throw new Exception("Unable to create resource for bundle " + uri, e);
-        }
-    }
-
-    protected Attributes getAttributes(String uri, StreamProvider provider) throws Exception {
-        InputStream is = provider.open();
-        try {
-            ZipInputStream zis = new ZipInputStream(is);
-            ZipEntry entry;
-            while ( (entry = zis.getNextEntry()) != null ) {
-                if ("META-INF/MANIFEST.MF".equals(entry.getName())) {
-                    return new Manifest(zis).getMainAttributes();
-                }
-            }
-        } finally {
-            is.close();
-        }
-        throw new IllegalArgumentException("Resource " + uri + " does not contain a manifest");
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/core/src/main/java/org/apache/karaf/features/internal/deployment/Downloader.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/deployment/Downloader.java b/features/core/src/main/java/org/apache/karaf/features/internal/deployment/Downloader.java
deleted file mode 100644
index 2d5dd98..0000000
--- a/features/core/src/main/java/org/apache/karaf/features/internal/deployment/Downloader.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * 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.karaf.features.internal.deployment;
-
-import java.net.MalformedURLException;
-
-import org.apache.karaf.features.internal.util.MultiException;
-
-public interface Downloader {
-
-    void await() throws InterruptedException, MultiException;
-
-    void download(String location, DownloadCallback downloadCallback) throws MalformedURLException;
-
-    interface DownloadCallback {
-
-        void downloaded(StreamProvider provider) throws Exception;
-
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/core/src/main/java/org/apache/karaf/features/internal/deployment/StreamProvider.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/deployment/StreamProvider.java b/features/core/src/main/java/org/apache/karaf/features/internal/deployment/StreamProvider.java
deleted file mode 100644
index 60a3dfc..0000000
--- a/features/core/src/main/java/org/apache/karaf/features/internal/deployment/StreamProvider.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * 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.karaf.features.internal.deployment;
-
-import java.io.IOException;
-import java.io.InputStream;
-
-public interface StreamProvider {
-
-    InputStream open() throws IOException;
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/core/src/main/java/org/apache/karaf/features/internal/management/FeaturesServiceMBeanImpl.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/management/FeaturesServiceMBeanImpl.java b/features/core/src/main/java/org/apache/karaf/features/internal/management/FeaturesServiceMBeanImpl.java
deleted file mode 100644
index b1a5865..0000000
--- a/features/core/src/main/java/org/apache/karaf/features/internal/management/FeaturesServiceMBeanImpl.java
+++ /dev/null
@@ -1,290 +0,0 @@
-/*
- * 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.features.internal.management;
-
-import java.net.URI;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.EnumSet;
-import java.util.Hashtable;
-import java.util.List;
-
-import javax.management.MBeanNotificationInfo;
-import javax.management.MBeanRegistration;
-import javax.management.MBeanServer;
-import javax.management.NotCompliantMBeanException;
-import javax.management.Notification;
-import javax.management.ObjectName;
-import javax.management.openmbean.TabularData;
-
-import org.apache.karaf.features.*;
-import org.apache.karaf.features.management.FeaturesServiceMBean;
-import org.apache.karaf.features.management.codec.JmxFeature;
-import org.apache.karaf.features.management.codec.JmxFeatureEvent;
-import org.apache.karaf.features.management.codec.JmxRepository;
-import org.apache.karaf.features.management.codec.JmxRepositoryEvent;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.ServiceRegistration;
-
-/**
- * Implementation of {@link FeaturesServiceMBean}.
- */
-public class FeaturesServiceMBeanImpl extends StandardEmitterMBean implements
-        MBeanRegistration, FeaturesServiceMBean {
-
-    private ServiceRegistration<FeaturesListener> registration;
-
-    private BundleContext bundleContext;
-
-    private ObjectName objectName;
-
-    private volatile long sequenceNumber = 0;
-
-    private org.apache.karaf.features.FeaturesService featuresService;
-
-    public FeaturesServiceMBeanImpl() throws NotCompliantMBeanException {
-        super(FeaturesServiceMBean.class);
-    }
-
-    public ObjectName preRegister(MBeanServer server, ObjectName name) throws Exception {
-        objectName = name;
-        return name;
-    }
-
-    public void postRegister(Boolean registrationDone) {
-        registration = bundleContext.registerService(FeaturesListener.class,
-                getFeaturesListener(), new Hashtable<String, String>());
-    }
-
-    public void preDeregister() throws Exception {
-        registration.unregister();
-    }
-
-    public void postDeregister() {
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public TabularData getFeatures() throws Exception {
-        try {
-            List<Feature> allFeatures = Arrays.asList(featuresService.listFeatures());
-            List<Feature> insFeatures = Arrays.asList(featuresService.listInstalledFeatures());
-            ArrayList<JmxFeature> features = new ArrayList<JmxFeature>();
-            for (Feature feature : allFeatures) {
-                try {
-                    features.add(new JmxFeature(feature, insFeatures.contains(feature)));
-                } catch (Throwable t) {
-                    t.printStackTrace();
-                }
-            }
-            TabularData table = JmxFeature.tableFrom(features);
-            return table;
-        } catch (Throwable t) {
-            t.printStackTrace();
-            return null;
-        }
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    public TabularData getRepositories() throws Exception {
-        try {
-            List<Repository> allRepositories = Arrays.asList(featuresService.listRepositories());
-            ArrayList<JmxRepository> repositories = new ArrayList<JmxRepository>();
-            for (Repository repository : allRepositories) {
-                try {
-                    repositories.add(new JmxRepository(repository));
-                } catch (Throwable t) {
-                    t.printStackTrace();
-                }
-            }
-            TabularData table = JmxRepository.tableFrom(repositories);
-            return table;
-        } catch (Throwable t) {
-            t.printStackTrace();
-            return null;
-        }
-    }
-
-    public void addRepository(String uri) throws Exception {
-        featuresService.addRepository(new URI(uri));
-    }
-
-    public void addRepository(String uri, boolean install) throws Exception {
-        featuresService.addRepository(new URI(uri), install);
-    }
-
-    public void removeRepository(String uri) throws Exception {
-        featuresService.removeRepository(new URI(uri));
-    }
-
-    public void removeRepository(String uri, boolean uninstall) throws Exception {
-        featuresService.removeRepository(new URI(uri), uninstall);
-    }
-
-    public void installFeature(String name) throws Exception {
-        featuresService.installFeature(name);
-    }
-
-    public void installFeature(String name, boolean noRefresh) throws Exception {
-        EnumSet<org.apache.karaf.features.FeaturesService.Option> options = EnumSet.noneOf(org.apache.karaf.features.FeaturesService.Option.class);
-        if (noRefresh) {
-            options.add(org.apache.karaf.features.FeaturesService.Option.NoAutoRefreshBundles);
-        }
-        featuresService.installFeature(name, options);
-    }
-
-    public void installFeature(String name, boolean noRefresh, boolean noStart) throws Exception {
-        EnumSet<org.apache.karaf.features.FeaturesService.Option> options = EnumSet.noneOf(org.apache.karaf.features.FeaturesService.Option.class);
-        if (noRefresh) {
-            options.add(org.apache.karaf.features.FeaturesService.Option.NoAutoRefreshBundles);
-        }
-        if (noStart) {
-            options.add(org.apache.karaf.features.FeaturesService.Option.NoAutoStartBundles);
-        }
-        featuresService.installFeature(name, options);
-    }
-
-    public void installFeature(String name, String version) throws Exception {
-        featuresService.installFeature(name, version);
-    }
-
-    public void installFeature(String name, String version, boolean noRefresh) throws Exception {
-        EnumSet<org.apache.karaf.features.FeaturesService.Option> options = EnumSet.noneOf(org.apache.karaf.features.FeaturesService.Option.class);
-        if (noRefresh) {
-            options.add(org.apache.karaf.features.FeaturesService.Option.NoAutoRefreshBundles);
-        }
-        featuresService.installFeature(name, version, options);
-    }
-
-    public void installFeature(String name, String version, boolean noRefresh, boolean noStart) throws Exception {
-        EnumSet<org.apache.karaf.features.FeaturesService.Option> options = EnumSet.noneOf(org.apache.karaf.features.FeaturesService.Option.class);
-        if (noRefresh) {
-            options.add(org.apache.karaf.features.FeaturesService.Option.NoAutoRefreshBundles);
-        }
-        if (noStart) {
-            options.add(org.apache.karaf.features.FeaturesService.Option.NoAutoStartBundles);
-        }
-        featuresService.installFeature(name, version, options);
-    }
-
-    public TabularData infoFeature(String name) throws Exception {
-        try {
-            Feature feature = featuresService.getFeature(name);
-            return infoFeature(feature);
-        } catch (Throwable t) {
-            t.printStackTrace();
-            return null;
-        }
-    }
-
-    public TabularData infoFeature(String name, String version) throws Exception {
-        try {
-            Feature feature = featuresService.getFeature(name, version);
-            return infoFeature(feature);
-        } catch (Throwable t) {
-            t.printStackTrace();
-            return null;
-        }
-    }
-
-    private TabularData infoFeature(Feature feature) throws Exception {
-        JmxFeature jmxFeature = null;
-        if (featuresService.isInstalled(feature)) {
-            jmxFeature = new JmxFeature(feature, true);
-        } else {
-            jmxFeature = new JmxFeature(feature, false);
-        }
-        ArrayList<JmxFeature> features = new ArrayList<JmxFeature>();
-        features.add(jmxFeature);
-        TabularData table = JmxFeature.tableFrom(features);
-        return table;
-    }
-
-    public void uninstallFeature(String name) throws Exception {
-        featuresService.uninstallFeature(name);
-    }
-
-    public void uninstallFeature(String name, boolean noRefresh) throws Exception {
-        EnumSet<org.apache.karaf.features.FeaturesService.Option> options = EnumSet.noneOf(org.apache.karaf.features.FeaturesService.Option.class);
-        if (noRefresh) {
-            options.add(org.apache.karaf.features.FeaturesService.Option.NoAutoRefreshBundles);
-        }
-        featuresService.uninstallFeature(name, options);
-    }
-
-    public void uninstallFeature(String name, String version) throws Exception {
-        featuresService.uninstallFeature(name, version);
-    }
-
-    public void uninstallFeature(String name, String version, boolean noRefresh) throws Exception {
-        EnumSet<org.apache.karaf.features.FeaturesService.Option> options = EnumSet.noneOf(org.apache.karaf.features.FeaturesService.Option.class);
-        if (noRefresh) {
-            options.add(org.apache.karaf.features.FeaturesService.Option.NoAutoRefreshBundles);
-        }
-        featuresService.uninstallFeature(name, version, options);
-    }
-
-    public void setBundleContext(BundleContext bundleContext) {
-        this.bundleContext = bundleContext;
-    }
-
-    public void setFeaturesService(org.apache.karaf.features.FeaturesService featuresService) {
-        this.featuresService = featuresService;
-    }
-
-    public FeaturesListener getFeaturesListener() {
-        return new FeaturesListener() {
-            public void featureEvent(FeatureEvent event) {
-                if (!event.isReplay()) {
-                    Notification notification = new Notification(FEATURE_EVENT_TYPE, objectName, sequenceNumber++);
-                    notification.setUserData(new JmxFeatureEvent(event).asCompositeData());
-                    sendNotification(notification);
-                }
-            }
-
-            public void repositoryEvent(RepositoryEvent event) {
-                if (!event.isReplay()) {
-                    Notification notification = new Notification(REPOSITORY_EVENT_TYPE, objectName, sequenceNumber++);
-                    notification.setUserData(new JmxRepositoryEvent(event).asCompositeData());
-                    sendNotification(notification);
-                }
-            }
-
-            public boolean equals(Object o) {
-                if (this == o) {
-                    return true;
-                }
-                return o.equals(this);
-            }
-
-        };
-    }
-
-    public MBeanNotificationInfo[] getNotificationInfo() {
-        return getBroadcastInfo();
-    }
-
-    private static MBeanNotificationInfo[] getBroadcastInfo() {
-        String type = Notification.class.getCanonicalName();
-        MBeanNotificationInfo info1 = new MBeanNotificationInfo(new String[]{FEATURE_EVENT_EVENT_TYPE},
-                type, "Some features notification");
-        MBeanNotificationInfo info2 = new MBeanNotificationInfo(new String[]{REPOSITORY_EVENT_EVENT_TYPE},
-                type, "Some repository notification");
-        return new MBeanNotificationInfo[]{info1, info2};
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/core/src/main/java/org/apache/karaf/features/internal/management/StandardEmitterMBean.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/management/StandardEmitterMBean.java b/features/core/src/main/java/org/apache/karaf/features/internal/management/StandardEmitterMBean.java
deleted file mode 100644
index 13a4b6c..0000000
--- a/features/core/src/main/java/org/apache/karaf/features/internal/management/StandardEmitterMBean.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * 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.features.internal.management;
-
-import javax.management.*;
-
-public class StandardEmitterMBean extends StandardMBean implements NotificationEmitter {
-
-    private final NotificationBroadcasterSupport emitter;
-
-    @SuppressWarnings("rawtypes")
-	public StandardEmitterMBean(Class mbeanInterface) throws NotCompliantMBeanException {
-        super(mbeanInterface);
-        this.emitter = new NotificationBroadcasterSupport() {
-            @Override
-            public MBeanNotificationInfo[] getNotificationInfo() {
-                return StandardEmitterMBean.this.getNotificationInfo();
-            }
-        };
-    }
-
-    public void sendNotification(Notification notification) {
-        emitter.sendNotification(notification);
-    }
-
-
-    public void removeNotificationListener(NotificationListener listener, NotificationFilter filter, Object handback) throws ListenerNotFoundException {
-        emitter.removeNotificationListener(listener, filter, handback);
-    }
-
-    public void addNotificationListener(NotificationListener listener, NotificationFilter filter, Object handback) throws IllegalArgumentException {
-        emitter.addNotificationListener(listener, filter, handback);
-    }
-
-    public void removeNotificationListener(NotificationListener listener) throws ListenerNotFoundException {
-        emitter.removeNotificationListener(listener);
-    }
-
-    public MBeanNotificationInfo[] getNotificationInfo() {
-        return new MBeanNotificationInfo[0];
-    }
-
-    @Override
-    public MBeanInfo getMBeanInfo() {
-        MBeanInfo mbeanInfo = super.getMBeanInfo();
-        if (mbeanInfo != null) {
-            MBeanNotificationInfo[] notificationInfo = getNotificationInfo();
-            mbeanInfo = new MBeanInfo(mbeanInfo.getClassName(), mbeanInfo.getDescription(), mbeanInfo.getAttributes(),
-                    mbeanInfo.getConstructors(), mbeanInfo.getOperations(), notificationInfo);
-        }
-        return mbeanInfo;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/core/src/main/java/org/apache/karaf/features/internal/model/Bundle.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/model/Bundle.java b/features/core/src/main/java/org/apache/karaf/features/internal/model/Bundle.java
deleted file mode 100644
index 7eebbe5..0000000
--- a/features/core/src/main/java/org/apache/karaf/features/internal/model/Bundle.java
+++ /dev/null
@@ -1,198 +0,0 @@
-/*
- * 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.karaf.features.internal.model;
-
-import javax.xml.bind.annotation.XmlAccessType;
-import javax.xml.bind.annotation.XmlAccessorType;
-import javax.xml.bind.annotation.XmlAttribute;
-import javax.xml.bind.annotation.XmlSchemaType;
-import javax.xml.bind.annotation.XmlType;
-import javax.xml.bind.annotation.XmlValue;
-import org.apache.karaf.features.BundleInfo;
-
-
-/**
- * 
- * Deployable element to install.
- *             
- * 
- * <p>Java class for bundle complex type.
- * 
- * <p>The following schema fragment specifies the expected content contained within this class.
- * 
- * <pre>
- * &lt;complexType name="bundle">
- *   &lt;simpleContent>
- *     &lt;extension base="&lt;http://www.w3.org/2001/XMLSchema>anyURI">
- *       &lt;attribute name="start-level" type="{http://www.w3.org/2001/XMLSchema}int" />
- *       &lt;attribute name="start" type="{http://www.w3.org/2001/XMLSchema}boolean" />
- *       &lt;attribute name="dependency" type="{http://www.w3.org/2001/XMLSchema}boolean" />
- *     &lt;/extension>
- *   &lt;/simpleContent>
- * &lt;/complexType>
- * </pre>
- * 
- * 
- */
-@XmlAccessorType(XmlAccessType.FIELD)
-@XmlType(name = "bundle", propOrder = {
-    "value"
-})
-public class Bundle implements BundleInfo {
-
-    @XmlValue
-    @XmlSchemaType(name = "anyURI")
-    protected String value;
-    @XmlAttribute(name = "start-level")
-    protected Integer startLevel;
-    @XmlAttribute
-    protected Boolean start;// = true;
-    @XmlAttribute
-    protected Boolean dependency;
-
-
-    public Bundle() {
-    }
-
-    public Bundle(String value) {
-        this.value = value;
-    }
-
-    /**
-     * Gets the value of the value property.
-     * 
-     * @return
-     *     possible object is
-     *     {@link String }
-     *     
-     */
-    public String getLocation() {
-        return value;
-    }
-
-    /**
-     * Sets the value of the value property.
-     * 
-     * @param value
-     *     allowed object is
-     *     {@link String }
-     *     
-     */
-    public void setLocation(String value) {
-        this.value = value;
-    }
-
-    /**
-     * Gets the value of the startLevel property.
-     * 
-     * @return
-     *     possible object is
-     *     {@link Integer }
-     *     
-     */
-    public int getStartLevel() {
-        return startLevel == null? 0: startLevel;
-    }
-
-    /**
-     * Sets the value of the startLevel property.
-     * 
-     * @param value
-     *     allowed object is
-     *     {@link Integer }
-     *     
-     */
-    public void setStartLevel(Integer value) {
-        this.startLevel = value;
-    }
-
-    /**
-     * Gets the value of the start property.
-     * 
-     * @return
-     *     possible object is
-     *     {@link Boolean }
-     *     
-     */
-    public boolean isStart() {
-        return start == null? true: start;
-    }
-
-    /**
-     * Sets the value of the start property.
-     * 
-     * @param value
-     *     allowed object is
-     *     {@link Boolean }
-     *     
-     */
-    public void setStart(Boolean value) {
-        this.start = value;
-    }
-
-    /**
-     * Gets the value of the dependency property.
-     * 
-     * @return
-     *     possible object is
-     *     {@link Boolean }
-     *     
-     */
-    public boolean isDependency() {
-        return dependency == null? false: dependency;
-    }
-
-    /**
-     * Sets the value of the dependency property.
-     * 
-     * @param value
-     *     allowed object is
-     *     {@link Boolean }
-     *     
-     */
-    public void setDependency(Boolean value) {
-        this.dependency = value;
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) return true;
-        if (o == null || getClass() != o.getClass()) return false;
-
-        Bundle bundle = (Bundle) o;
-
-        if (dependency != bundle.dependency) return false;
-        if (start != bundle.start) return false;
-        if (startLevel != bundle.startLevel) return false;
-        if (value != null ? !value.equals(bundle.value) : bundle.value != null) return false;
-
-        return true;
-    }
-
-    @Override
-    public int hashCode() {
-        int result = value != null ? value.hashCode() : 0;
-        result = 31 * result + getStartLevel();
-        result = 31 * result + (isStart() ? 1 : 0);
-        result = 31 * result + (isDependency() ? 1 : 0);
-        return result;
-    }
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/core/src/main/java/org/apache/karaf/features/internal/model/Capability.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/model/Capability.java b/features/core/src/main/java/org/apache/karaf/features/internal/model/Capability.java
deleted file mode 100644
index b866151..0000000
--- a/features/core/src/main/java/org/apache/karaf/features/internal/model/Capability.java
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * 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.karaf.features.internal.model;
-
-import javax.xml.bind.annotation.XmlAccessType;
-import javax.xml.bind.annotation.XmlAccessorType;
-import javax.xml.bind.annotation.XmlAttribute;
-import javax.xml.bind.annotation.XmlSchemaType;
-import javax.xml.bind.annotation.XmlType;
-import javax.xml.bind.annotation.XmlValue;
-
-import org.apache.karaf.features.BundleInfo;
-
-
-/**
- * 
- * Additional capability for a feature.
- *             
- * 
- * <p>Java class for bundle complex type.
- * 
- * <p>The following schema fragment specifies the expected content contained within this class.
- * 
- * <pre>
- * &lt;complexType name="capability">
- *   &lt;simpleContent>
- *     &lt;extension base="&lt;http://www.w3.org/2001/XMLSchema>string">
- *     &lt;/extension>
- *   &lt;/simpleContent>
- * &lt;/complexType>
- * </pre>
- * 
- * 
- */
-@XmlAccessorType(XmlAccessType.FIELD)
-@XmlType(name = "capability", propOrder = {
-    "value"
-})
-public class Capability implements org.apache.karaf.features.Capability {
-
-    @XmlValue
-    protected String value;
-
-
-    public Capability() {
-    }
-
-    public Capability(String value) {
-        this.value = value;
-    }
-
-    public String getValue() {
-        return value;
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) return true;
-        if (o == null || getClass() != o.getClass()) return false;
-
-        Capability bundle = (Capability) o;
-
-        if (value != null ? !value.equals(bundle.value) : bundle.value != null) return false;
-
-        return true;
-    }
-
-    @Override
-    public int hashCode() {
-        int result = value != null ? value.hashCode() : 0;
-        return result;
-    }
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/core/src/main/java/org/apache/karaf/features/internal/model/Conditional.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/model/Conditional.java b/features/core/src/main/java/org/apache/karaf/features/internal/model/Conditional.java
deleted file mode 100644
index 5bc0b95..0000000
--- a/features/core/src/main/java/org/apache/karaf/features/internal/model/Conditional.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * 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.karaf.features.internal.model;
-
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-import javax.xml.bind.annotation.XmlAccessType;
-import javax.xml.bind.annotation.XmlAccessorType;
-import javax.xml.bind.annotation.XmlElement;
-import javax.xml.bind.annotation.XmlType;
-import org.apache.karaf.features.Feature;
-
-@XmlAccessorType(XmlAccessType.FIELD)
-@XmlType(name = "conditional", propOrder = {
-        "condition",
-        "config",
-        "configfile",
-        "feature",
-        "bundle"
-})
-public class Conditional extends Content implements org.apache.karaf.features.Conditional {
-
-    @XmlElement(name = "condition")
-    protected List<Dependency> condition;
-
-    public List<Dependency> getCondition() {
-        if (condition == null) {
-            this.condition = new ArrayList<Dependency>();
-        }
-        return condition;
-    }
-
-    @Override
-    public Feature asFeature(String name, String version) {
-        String conditionName = name + "-condition-" + getConditionId().replaceAll("[^A-Za-z0-9 ]", "_");
-        org.apache.karaf.features.internal.model.Feature f = new org.apache.karaf.features.internal.model.Feature(conditionName, version);
-        f.getBundle().addAll(getBundle());
-        f.getConfig().addAll(getConfig());
-        f.getConfigfile().addAll(getConfigfile());
-        f.getFeature().addAll(getFeature());
-        return f;
-    }
-
-    private String getConditionId() {
-        StringBuffer sb = new StringBuffer();
-        Iterator<Dependency> di = getCondition().iterator();
-        while (di.hasNext()) {
-            Dependency dependency = di.next();
-            sb.append(dependency.getName() + "_" + dependency.getVersion());
-            if (di.hasNext()) {
-                sb.append("_");
-            }
-        }
-        return sb.toString();
-    }
-}


[13/59] [abbrv] [KARAF-2852] Merge features/core and features/command

Posted by gn...@apache.org.
http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/core/src/main/java/org/apache/karaf/features/internal/resolver/ResourceBuilder.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/resolver/ResourceBuilder.java b/features/core/src/main/java/org/apache/karaf/features/internal/resolver/ResourceBuilder.java
deleted file mode 100644
index cb2c36a..0000000
--- a/features/core/src/main/java/org/apache/karaf/features/internal/resolver/ResourceBuilder.java
+++ /dev/null
@@ -1,1129 +0,0 @@
-/*
- * 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.karaf.features.internal.resolver;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import org.apache.felix.utils.version.VersionRange;
-import org.osgi.framework.BundleException;
-import org.osgi.framework.Constants;
-import org.osgi.framework.Version;
-import org.osgi.framework.namespace.IdentityNamespace;
-import org.osgi.framework.wiring.BundleCapability;
-import org.osgi.framework.wiring.BundleRevision;
-import org.osgi.resource.Capability;
-import org.osgi.resource.Requirement;
-import org.osgi.resource.Resource;
-
-public class ResourceBuilder {
-
-    public static final String RESOLUTION_DYNAMIC = "dynamic";
-
-    public static Resource build(String uri, Map<String, String> headerMap)
-            throws BundleException {
-
-        // Verify that only manifest version 2 is specified.
-        String manifestVersion = getManifestVersion(headerMap);
-        if (manifestVersion == null || !manifestVersion.equals("2")) {
-            throw new BundleException("Unsupported 'Bundle-ManifestVersion' value: " + manifestVersion);
-        }
-
-        //
-        // Parse bundle version.
-        //
-
-        Version bundleVersion = Version.emptyVersion;
-        if (headerMap.get(Constants.BUNDLE_VERSION) != null) {
-            bundleVersion = Version.parseVersion(headerMap.get(Constants.BUNDLE_VERSION));
-        }
-
-        //
-        // Parse bundle symbolic name.
-        //
-
-        String bundleSymbolicName = null;
-        ParsedHeaderClause bundleCap = parseBundleSymbolicName(headerMap);
-        if (bundleCap == null) {
-            throw new BundleException("Bundle manifest must include bundle symbolic name");
-        }
-        bundleSymbolicName = (String) bundleCap.attrs.get(BundleRevision.BUNDLE_NAMESPACE);
-
-        // Now that we have symbolic name and version, create the resource
-        String type = headerMap.get(Constants.FRAGMENT_HOST) == null ? IdentityNamespace.TYPE_BUNDLE : IdentityNamespace.TYPE_FRAGMENT;
-        ResourceImpl resource = new ResourceImpl(bundleSymbolicName, type, bundleVersion);
-        if (uri != null) {
-            Map<String, Object> attrs = new HashMap<String, Object>();
-            attrs.put(UriNamespace.URI_NAMESPACE, uri);
-            resource.addCapability(new CapabilityImpl(resource, UriNamespace.URI_NAMESPACE, Collections.<String, String>emptyMap(), attrs));
-        }
-
-        // Add a bundle and host capability to all
-        // non-fragment bundles. A host capability is the same
-        // as a require capability, but with a different capability
-        // namespace. Bundle capabilities resolve required-bundle
-        // dependencies, while host capabilities resolve fragment-host
-        // dependencies.
-        if (headerMap.get(Constants.FRAGMENT_HOST) == null) {
-            // All non-fragment bundles have bundle capability.
-            resource.addCapability(new CapabilityImpl(resource, BundleRevision.BUNDLE_NAMESPACE, bundleCap.dirs, bundleCap.attrs));
-            // A non-fragment bundle can choose to not have a host capability.
-            String attachment = bundleCap.dirs.get(Constants.FRAGMENT_ATTACHMENT_DIRECTIVE);
-            attachment = (attachment == null) ? Constants.FRAGMENT_ATTACHMENT_RESOLVETIME : attachment;
-            if (!attachment.equalsIgnoreCase(Constants.FRAGMENT_ATTACHMENT_NEVER)) {
-                Map<String, Object> hostAttrs = new HashMap<String, Object>(bundleCap.attrs);
-                Object value = hostAttrs.remove(BundleRevision.BUNDLE_NAMESPACE);
-                hostAttrs.put(BundleRevision.HOST_NAMESPACE, value);
-                resource.addCapability(new CapabilityImpl(
-                        resource, BundleRevision.HOST_NAMESPACE,
-                        bundleCap.dirs,
-                        hostAttrs));
-            }
-        }
-
-        //
-        // Parse Fragment-Host.
-        //
-
-        List<RequirementImpl> hostReqs = parseFragmentHost(resource, headerMap);
-
-        //
-        // Parse Require-Bundle
-        //
-
-        List<ParsedHeaderClause> rbClauses = parseStandardHeader(headerMap.get(Constants.REQUIRE_BUNDLE));
-        rbClauses = normalizeRequireClauses(rbClauses);
-        List<Requirement> rbReqs = convertRequires(rbClauses, resource);
-
-        //
-        // Parse Import-Package.
-        //
-
-        List<ParsedHeaderClause> importClauses = parseStandardHeader(headerMap.get(Constants.IMPORT_PACKAGE));
-        importClauses = normalizeImportClauses(importClauses);
-        List<Requirement> importReqs = convertImports(importClauses, resource);
-
-        //
-        // Parse DynamicImport-Package.
-        //
-
-        List<ParsedHeaderClause> dynamicClauses = parseStandardHeader(headerMap.get(Constants.DYNAMICIMPORT_PACKAGE));
-        dynamicClauses = normalizeDynamicImportClauses(dynamicClauses);
-        List<Requirement> dynamicReqs = convertImports(dynamicClauses, resource);
-
-        //
-        // Parse Require-Capability.
-        //
-
-        List<ParsedHeaderClause> requireClauses = parseStandardHeader(headerMap.get(Constants.REQUIRE_CAPABILITY));
-        requireClauses = normalizeRequireCapabilityClauses(requireClauses);
-        List<Requirement> requireReqs = convertRequireCapabilities(requireClauses, resource);
-
-        //
-        // Parse Export-Package.
-        //
-
-        List<ParsedHeaderClause> exportClauses = parseStandardHeader(headerMap.get(Constants.EXPORT_PACKAGE));
-        exportClauses = normalizeExportClauses(exportClauses, bundleSymbolicName, bundleVersion);
-        List<Capability> exportCaps = convertExports(exportClauses, resource);
-
-        //
-        // Parse Provide-Capability.
-        //
-
-        List<ParsedHeaderClause> provideClauses = parseStandardHeader(headerMap.get(Constants.PROVIDE_CAPABILITY));
-        provideClauses = normalizeProvideCapabilityClauses(provideClauses);
-        List<Capability> provideCaps = convertProvideCapabilities(provideClauses, resource);
-
-        //
-        // Parse Import-Service and Export-Service
-        // if Require-Capability and Provide-Capability are not set for services
-        //
-
-        boolean hasServiceReferenceCapability = false;
-        for (Capability cap : exportCaps) {
-            hasServiceReferenceCapability |= ServiceNamespace.SERVICE_NAMESPACE.equals(cap.getNamespace());
-        }
-        if (!hasServiceReferenceCapability) {
-            List<ParsedHeaderClause> exportServices = parseStandardHeader(headerMap.get(Constants.EXPORT_SERVICE));
-            List<Capability> caps = convertExportService(exportServices, resource);
-            provideCaps.addAll(caps);
-        }
-
-        boolean hasServiceReferenceRequirement = false;
-        for (Requirement req : requireReqs) {
-            hasServiceReferenceRequirement |= ServiceNamespace.SERVICE_NAMESPACE.equals(req.getNamespace());
-        }
-        if (!hasServiceReferenceRequirement) {
-            List<ParsedHeaderClause> importServices = parseStandardHeader(headerMap.get(Constants.IMPORT_SERVICE));
-            List<Requirement> reqs = convertImportService(importServices, resource);
-            requireReqs.addAll(reqs);
-        }
-
-        // Combine all capabilities.
-        resource.addCapabilities(exportCaps);
-        resource.addCapabilities(provideCaps);
-
-        // Combine all requirements.
-        resource.addRequirements(hostReqs);
-        resource.addRequirements(importReqs);
-        resource.addRequirements(rbReqs);
-        resource.addRequirements(requireReqs);
-        resource.addRequirements(dynamicReqs);
-
-        return resource;
-    }
-
-    public static List<Requirement> parseImport(Resource resource, String imports) throws BundleException {
-        List<ParsedHeaderClause> importClauses = parseStandardHeader(imports);
-        importClauses = normalizeImportClauses(importClauses);
-        List<Requirement> importReqs = convertImports(importClauses, resource);
-        return importReqs;
-    }
-
-    public static List<Requirement> parseRequirement(Resource resource, String requirement) throws BundleException {
-        List<ParsedHeaderClause> requireClauses = parseStandardHeader(requirement);
-        requireClauses = normalizeRequireCapabilityClauses(requireClauses);
-        List<Requirement> requireReqs = convertRequireCapabilities(requireClauses, resource);
-        return requireReqs;
-    }
-
-    public static List<Capability> parseExport(Resource resource, String bundleSymbolicName, Version bundleVersion, String exports) throws BundleException {
-        List<ParsedHeaderClause> exportClauses = parseStandardHeader(exports);
-        exportClauses = normalizeExportClauses(exportClauses, bundleSymbolicName, bundleVersion);
-        List<Capability> exportCaps = convertExports(exportClauses, resource);
-        return exportCaps;
-    }
-
-    public static List<Capability> parseCapability(Resource resource, String capability) throws BundleException {
-        List<ParsedHeaderClause> provideClauses = parseStandardHeader(capability);
-        provideClauses = normalizeProvideCapabilityClauses(provideClauses);
-        List<Capability> provideCaps = convertProvideCapabilities(provideClauses, resource);
-        return provideCaps;
-    }
-
-    @SuppressWarnings( "deprecation" )
-    private static List<ParsedHeaderClause> normalizeImportClauses(
-            List<ParsedHeaderClause> clauses)
-            throws BundleException {
-        // Verify that the values are equals if the package specifies
-        // both version and specification-version attributes.
-        Set<String> dupeSet = new HashSet<String>();
-        for (ParsedHeaderClause clause : clauses) {
-            // Check for "version" and "specification-version" attributes
-            // and verify they are the same if both are specified.
-            Object v = clause.attrs.get(Constants.VERSION_ATTRIBUTE);
-            Object sv = clause.attrs.get(Constants.PACKAGE_SPECIFICATION_VERSION);
-            if ((v != null) && (sv != null)) {
-                // Verify they are equal.
-                if (!((String) v).trim().equals(((String) sv).trim())) {
-                    throw new IllegalArgumentException(
-                            "Both version and specification-version are specified, but they are not equal.");
-                }
-            }
-
-            // Ensure that only the "version" attribute is used and convert
-            // it to the VersionRange type.
-            if ((v != null) || (sv != null)) {
-                clause.attrs.remove(Constants.PACKAGE_SPECIFICATION_VERSION);
-                v = (v == null) ? sv : v;
-                clause.attrs.put(Constants.VERSION_ATTRIBUTE, VersionRange.parseVersionRange(v.toString()));
-            }
-
-            // If bundle version is specified, then convert its type to VersionRange.
-            v = clause.attrs.get(Constants.BUNDLE_VERSION_ATTRIBUTE);
-            if (v != null) {
-                clause.attrs.put(Constants.BUNDLE_VERSION_ATTRIBUTE, VersionRange.parseVersionRange(v.toString()));
-            }
-
-            // Verify java.* is not imported, nor any duplicate imports.
-            for (String pkgName : clause.paths) {
-                if (!dupeSet.contains(pkgName)) {
-                    // Verify that java.* packages are not imported.
-                    if (pkgName.startsWith("java.")) {
-                        throw new BundleException("Importing java.* packages not allowed: " + pkgName);
-                    }
-                    // The character "." has no meaning in the OSGi spec except
-                    // when placed on the bundle class path. Some people, however,
-                    // mistakenly think it means the default package when imported
-                    // or exported. This is not correct. It is invalid.
-                    else if (pkgName.equals(".")) {
-                        throw new BundleException("Importing '.' is invalid.");
-                    }
-                    // Make sure a package name was specified.
-                    else if (pkgName.length() == 0) {
-                        throw new BundleException(
-                                "Imported package names cannot be zero length.");
-                    }
-                    dupeSet.add(pkgName);
-                } else {
-                    throw new BundleException("Duplicate import: " + pkgName);
-                }
-            }
-        }
-
-        return clauses;
-    }
-
-    private static List<Capability> convertExportService(List<ParsedHeaderClause> clauses, Resource resource) {
-        List<Capability> capList = new ArrayList<Capability>();
-        for (ParsedHeaderClause clause : clauses) {
-            for (String path : clause.paths) {
-                Map<String, String> dirs = new LinkedHashMap<String, String>();
-                dirs.put(ServiceNamespace.CAPABILITY_EFFECTIVE_DIRECTIVE, ServiceNamespace.EFFECTIVE_ACTIVE);
-                Map<String, Object> attrs = new LinkedHashMap<String, Object>();
-                attrs.put(Constants.OBJECTCLASS, path);
-                attrs.putAll(clause.attrs);
-                capList.add(new CapabilityImpl(
-                                resource,
-                                ServiceNamespace.SERVICE_NAMESPACE,
-                                dirs,
-                                attrs));
-            }
-        }
-        return capList;
-    }
-
-    private static List<Requirement> convertImportService(List<ParsedHeaderClause> clauses, Resource resource) throws BundleException {
-        try {
-            List<Requirement> reqList = new ArrayList<Requirement>();
-            for (ParsedHeaderClause clause : clauses) {
-                for (String path : clause.paths) {
-                    String multiple = clause.dirs.get("multiple");
-                    String avail    = clause.dirs.get("availability");
-                    String filter   = (String) clause.attrs.get("filter");
-                    Map<String, String> dirs = new LinkedHashMap<String, String>();
-                    dirs.put(ServiceNamespace.REQUIREMENT_EFFECTIVE_DIRECTIVE, ServiceNamespace.EFFECTIVE_ACTIVE);
-                    if ("optional".equals(avail)) {
-                        dirs.put(ServiceNamespace.REQUIREMENT_RESOLUTION_DIRECTIVE, ServiceNamespace.RESOLUTION_OPTIONAL);
-                    }
-                    if ("true".equals(multiple)) {
-                        dirs.put(ServiceNamespace.REQUIREMENT_CARDINALITY_DIRECTIVE, ServiceNamespace.CARDINALITY_MULTIPLE);
-                    }
-                    if (filter == null) {
-                        filter = "(" + Constants.OBJECTCLASS + "=" + path + ")";
-                    } else if (!filter.startsWith("(") && !filter.endsWith(")")) {
-                        filter = "(&(" + Constants.OBJECTCLASS + "=" + path + ")(" + filter + "))";
-                    } else {
-                        filter = "(&(" + Constants.OBJECTCLASS + "=" + path + ")" + filter + ")";
-                    }
-                    dirs.put(ServiceNamespace.REQUIREMENT_FILTER_DIRECTIVE, filter);
-                    reqList.add(new RequirementImpl(
-                                    resource,
-                                    ServiceNamespace.SERVICE_NAMESPACE,
-                                    dirs,
-                                    Collections.<String, Object>emptyMap(),
-                                    SimpleFilter.parse(filter)));
-                }
-            }
-            return reqList;
-        } catch (Exception ex) {
-            throw new BundleException("Error creating requirement: " + ex, ex);
-        }
-    }
-
-    private static List<Requirement> convertImports(List<ParsedHeaderClause> clauses, Resource resource) {
-        // Now convert generic header clauses into requirements.
-        List<Requirement> reqList = new ArrayList<Requirement>();
-        for (ParsedHeaderClause clause : clauses) {
-            for (String path : clause.paths) {
-                // Prepend the package name to the array of attributes.
-                Map<String, Object> attrs = clause.attrs;
-                // Note that we use a linked hash map here to ensure the
-                // package attribute is first, which will make indexing
-                // more efficient.
-    // TODO: OSGi R4.3 - This is ordering is kind of hacky.
-                // Prepend the package name to the array of attributes.
-                Map<String, Object> newAttrs = new LinkedHashMap<String, Object>(attrs.size() + 1);
-                // We want this first from an indexing perspective.
-                newAttrs.put(BundleRevision.PACKAGE_NAMESPACE, path);
-                newAttrs.putAll(attrs);
-                // But we need to put it again to make sure it wasn't overwritten.
-                newAttrs.put(BundleRevision.PACKAGE_NAMESPACE, path);
-
-                // Create filter now so we can inject filter directive.
-                SimpleFilter sf = SimpleFilter.convert(newAttrs);
-
-                // Inject filter directive.
-    // TODO: OSGi R4.3 - Can we insert this on demand somehow?
-                Map<String, String> dirs = clause.dirs;
-                Map<String, String> newDirs = new HashMap<String, String>(dirs.size() + 1);
-                newDirs.putAll(dirs);
-                newDirs.put(Constants.FILTER_DIRECTIVE, sf.toString());
-
-                // Create package requirement and add to requirement list.
-                reqList.add(
-                        new RequirementImpl(
-                                resource,
-                                BundleRevision.PACKAGE_NAMESPACE,
-                                newDirs,
-                                Collections.<String, Object>emptyMap(),
-                                sf));
-            }
-        }
-
-        return reqList;
-    }
-
-    @SuppressWarnings( "deprecation" )
-    private static List<ParsedHeaderClause> normalizeDynamicImportClauses(
-            List<ParsedHeaderClause> clauses)
-            throws BundleException {
-        // Verify that the values are equals if the package specifies
-        // both version and specification-version attributes.
-        for (ParsedHeaderClause clause : clauses) {
-            // Add the resolution directive to indicate that these are
-            // dynamic imports.
-            clause.dirs.put(Constants.RESOLUTION_DIRECTIVE, RESOLUTION_DYNAMIC);
-
-            // Check for "version" and "specification-version" attributes
-            // and verify they are the same if both are specified.
-            Object v = clause.attrs.get(Constants.VERSION_ATTRIBUTE);
-            Object sv = clause.attrs.get(Constants.PACKAGE_SPECIFICATION_VERSION);
-            if ((v != null) && (sv != null)) {
-                // Verify they are equal.
-                if (!((String) v).trim().equals(((String) sv).trim())) {
-                    throw new IllegalArgumentException(
-                            "Both version and specification-version are specified, but they are not equal.");
-                }
-            }
-
-            // Ensure that only the "version" attribute is used and convert
-            // it to the VersionRange type.
-            if ((v != null) || (sv != null)) {
-                clause.attrs.remove(Constants.PACKAGE_SPECIFICATION_VERSION);
-                v = (v == null) ? sv : v;
-                clause.attrs.put(Constants.VERSION_ATTRIBUTE, VersionRange.parseVersionRange(v.toString()));
-            }
-
-            // If bundle version is specified, then convert its type to VersionRange.
-            v = clause.attrs.get(Constants.BUNDLE_VERSION_ATTRIBUTE);
-            if (v != null) {
-                clause.attrs.put(Constants.BUNDLE_VERSION_ATTRIBUTE, VersionRange.parseVersionRange(v.toString()));
-            }
-
-            // Dynamic imports can have duplicates, so verify that java.*
-            // packages are not imported.
-            for (String pkgName : clause.paths) {
-                if (pkgName.startsWith("java.")) {
-                    throw new BundleException("Dynamically importing java.* packages not allowed: " + pkgName);
-                } else if (!pkgName.equals("*") && pkgName.endsWith("*") && !pkgName.endsWith(".*")) {
-                    throw new BundleException("Partial package name wild carding is not allowed: " + pkgName);
-                }
-            }
-        }
-
-        return clauses;
-    }
-
-    private static List<ParsedHeaderClause> normalizeRequireCapabilityClauses(
-            List<ParsedHeaderClause> clauses)
-            throws BundleException {
-
-        return clauses;
-    }
-
-    private static List<ParsedHeaderClause> normalizeProvideCapabilityClauses(
-            List<ParsedHeaderClause> clauses)
-            throws BundleException
-    {
-
-        // Convert attributes into specified types.
-        for (ParsedHeaderClause clause : clauses)
-        {
-            for (Map.Entry<String, String> entry : clause.types.entrySet())
-            {
-                String type = entry.getValue();
-                if (!type.equals("String"))
-                {
-                    if (type.equals("Double"))
-                    {
-                        clause.attrs.put(
-                                entry.getKey(),
-                                new Double(clause.attrs.get(entry.getKey()).toString().trim()));
-                    }
-                    else if (type.equals("Version"))
-                    {
-                        clause.attrs.put(
-                                entry.getKey(),
-                                new Version(clause.attrs.get(entry.getKey()).toString().trim()));
-                    }
-                    else if (type.equals("Long"))
-                    {
-                        clause.attrs.put(
-                                entry.getKey(),
-                                new Long(clause.attrs.get(entry.getKey()).toString().trim()));
-                    }
-                    else if (type.startsWith("List"))
-                    {
-                        int startIdx = type.indexOf('<');
-                        int endIdx = type.indexOf('>');
-                        if (((startIdx > 0) && (endIdx <= startIdx))
-                                || ((startIdx < 0) && (endIdx > 0)))
-                        {
-                            throw new BundleException(
-                                    "Invalid Provide-Capability attribute list type for '"
-                                            + entry.getKey()
-                                            + "' : "
-                                            + type);
-                        }
-
-                        String listType = "String";
-                        if (endIdx > startIdx)
-                        {
-                            listType = type.substring(startIdx + 1, endIdx).trim();
-                        }
-
-                        List<String> tokens = parseDelimitedString(
-                                clause.attrs.get(entry.getKey()).toString(), ",", false);
-                        List<Object> values = new ArrayList<Object>(tokens.size());
-                        for (String token : tokens)
-                        {
-                            if (listType.equals("String"))
-                            {
-                                values.add(token);
-                            }
-                            else if (listType.equals("Double"))
-                            {
-                                values.add(new Double(token.trim()));
-                            }
-                            else if (listType.equals("Version"))
-                            {
-                                values.add(new Version(token.trim()));
-                            }
-                            else if (listType.equals("Long"))
-                            {
-                                values.add(new Long(token.trim()));
-                            }
-                            else
-                            {
-                                throw new BundleException(
-                                        "Unknown Provide-Capability attribute list type for '"
-                                                + entry.getKey()
-                                                + "' : "
-                                                + type);
-                            }
-                        }
-                        clause.attrs.put(
-                                entry.getKey(),
-                                values);
-                    }
-                    else
-                    {
-                        throw new BundleException(
-                                "Unknown Provide-Capability attribute type for '"
-                                        + entry.getKey()
-                                        + "' : "
-                                        + type);
-                    }
-                }
-            }
-        }
-
-        return clauses;
-    }
-
-    private static List<Requirement> convertRequireCapabilities(
-            List<ParsedHeaderClause> clauses, Resource resource)
-            throws BundleException {
-        // Now convert generic header clauses into requirements.
-        List<Requirement> reqList = new ArrayList<Requirement>();
-        for (ParsedHeaderClause clause : clauses) {
-            try {
-                String filterStr = clause.dirs.get(Constants.FILTER_DIRECTIVE);
-                SimpleFilter sf = (filterStr != null)
-                        ? SimpleFilter.parse(filterStr)
-                        : new SimpleFilter(null, null, SimpleFilter.MATCH_ALL);
-                for (String path : clause.paths) {
-                    // Create requirement and add to requirement list.
-                    reqList.add(new RequirementImpl(
-                                    resource, path, clause.dirs, clause.attrs, sf));
-                }
-            } catch (Exception ex) {
-                throw new BundleException("Error creating requirement: " + ex, ex);
-            }
-        }
-
-        return reqList;
-    }
-
-    private static List<Capability> convertProvideCapabilities(
-            List<ParsedHeaderClause> clauses, Resource resource)
-            throws BundleException {
-        List<Capability> capList = new ArrayList<Capability>();
-        for (ParsedHeaderClause clause : clauses) {
-            for (String path : clause.paths) {
-                if (path.startsWith("osgi.wiring.")) {
-//                    throw new BundleException("Manifest cannot use Provide-Capability for '" + path + "' namespace.");
-                }
-
-                // Create package capability and add to capability list.
-                capList.add(new CapabilityImpl(resource, path, clause.dirs, clause.attrs));
-            }
-        }
-
-        return capList;
-    }
-
-    @SuppressWarnings( "deprecation" )
-    private static List<ParsedHeaderClause> normalizeExportClauses(
-            List<ParsedHeaderClause> clauses,
-            String bsn, Version bv)
-            throws BundleException {
-        // Verify that "java.*" packages are not exported.
-        for (ParsedHeaderClause clause : clauses) {
-            // Verify that the named package has not already been declared.
-            for (String pkgName : clause.paths) {
-                // Verify that java.* packages are not exported.
-                if (pkgName.startsWith("java.")) {
-                    throw new BundleException("Exporting java.* packages not allowed: " + pkgName);
-                }
-                // The character "." has no meaning in the OSGi spec except
-                // when placed on the bundle class path. Some people, however,
-                // mistakenly think it means the default package when imported
-                // or exported. This is not correct. It is invalid.
-                else if (pkgName.equals(".")) {
-                    throw new BundleException("Exporing '.' is invalid.");
-                }
-                // Make sure a package name was specified.
-                else if (pkgName.length() == 0) {
-                    throw new BundleException("Exported package names cannot be zero length.");
-                }
-            }
-
-            // Check for "version" and "specification-version" attributes
-            // and verify they are the same if both are specified.
-            Object v = clause.attrs.get(Constants.VERSION_ATTRIBUTE);
-            Object sv = clause.attrs.get(Constants.PACKAGE_SPECIFICATION_VERSION);
-            if ((v != null) && (sv != null)) {
-                // Verify they are equal.
-                if (!((String) v).trim().equals(((String) sv).trim())) {
-                    throw new IllegalArgumentException("Both version and specification-version are specified, but they are not equal.");
-                }
-            }
-
-            // Always add the default version if not specified.
-            if ((v == null) && (sv == null)) {
-                v = Version.emptyVersion;
-            }
-
-            // Ensure that only the "version" attribute is used and convert
-            // it to the appropriate type.
-            if ((v != null) || (sv != null)) {
-                // Convert version attribute to type Version.
-                clause.attrs.remove(Constants.PACKAGE_SPECIFICATION_VERSION);
-                v = (v == null) ? sv : v;
-                clause.attrs.put(Constants.VERSION_ATTRIBUTE, Version.parseVersion(v.toString()));
-            }
-
-            // Find symbolic name and version attribute, if present.
-            if (clause.attrs.containsKey(Constants.BUNDLE_VERSION_ATTRIBUTE)
-                    || clause.attrs.containsKey(Constants.BUNDLE_SYMBOLICNAME_ATTRIBUTE)) {
-                throw new BundleException("Exports must not specify bundle symbolic name or bundle version.");
-            }
-
-            // Now that we know that there are no bundle symbolic name and version
-            // attributes, add them since the spec says they are there implicitly.
-            clause.attrs.put(Constants.BUNDLE_SYMBOLICNAME_ATTRIBUTE, bsn);
-            clause.attrs.put(Constants.BUNDLE_VERSION_ATTRIBUTE, bv);
-        }
-
-        return clauses;
-    }
-
-    private static List<Capability> convertExports(
-            List<ParsedHeaderClause> clauses, Resource resource) {
-        List<Capability> capList = new ArrayList<Capability>();
-        for (ParsedHeaderClause clause : clauses) {
-            for (String pkgName : clause.paths) {
-                // Prepend the package name to the array of attributes.
-                Map<String, Object> attrs = clause.attrs;
-                Map<String, Object> newAttrs = new HashMap<String, Object>(attrs.size() + 1);
-                newAttrs.putAll(attrs);
-                newAttrs.put(BundleRevision.PACKAGE_NAMESPACE, pkgName);
-
-                // Create package capability and add to capability list.
-                capList.add(new CapabilityImpl(resource, BundleRevision.PACKAGE_NAMESPACE, clause.dirs, newAttrs));
-            }
-        }
-
-        return capList;
-    }
-
-    private static String getManifestVersion(Map<String, String> headerMap) {
-        String manifestVersion = headerMap.get(Constants.BUNDLE_MANIFESTVERSION);
-        return (manifestVersion == null) ? "1" : manifestVersion.trim();
-    }
-
-    private static List<ParsedHeaderClause> calculateImplicitImports(
-            List<BundleCapability> exports, List<ParsedHeaderClause> imports)
-            throws BundleException {
-        List<ParsedHeaderClause> clauseList = new ArrayList<ParsedHeaderClause>();
-
-        // Since all R3 exports imply an import, add a corresponding
-        // requirement for each existing export capability. Do not
-        // duplicate imports.
-        Map<String, String> map = new HashMap<String, String>();
-        // Add existing imports.
-        for (ParsedHeaderClause anImport : imports) {
-            for (int pathIdx = 0; pathIdx < anImport.paths.size(); pathIdx++) {
-                map.put(anImport.paths.get(pathIdx), anImport.paths.get(pathIdx));
-            }
-        }
-        // Add import requirement for each export capability.
-        for (BundleCapability export : exports) {
-            if (map.get(export.getAttributes().get(BundleRevision.PACKAGE_NAMESPACE).toString()) == null) {
-                // Convert Version to VersionRange.
-                Object version = export.getAttributes().get(Constants.VERSION_ATTRIBUTE);
-                ParsedHeaderClause clause = new ParsedHeaderClause();
-                if (version != null) {
-                    clause.attrs.put(Constants.VERSION_ATTRIBUTE, VersionRange.parseVersionRange(version.toString()));
-                }
-                clause.paths.add((String) export.getAttributes().get(BundleRevision.PACKAGE_NAMESPACE));
-                clauseList.add(clause);
-            }
-        }
-
-        return clauseList;
-    }
-
-    private static List<Capability> calculateImplicitUses(
-            List<Capability> exports, List<ParsedHeaderClause> imports)
-            throws BundleException {
-        // Add a "uses" directive onto each export of R3 bundles
-        // that references every other import (which will include
-        // exports, since export implies import); this is
-        // necessary since R3 bundles assumed a single class space,
-        // but R4 allows for multiple class spaces.
-        String usesValue = "";
-        for (ParsedHeaderClause anImport : imports) {
-            for (int pathIdx = 0; pathIdx < anImport.paths.size(); pathIdx++) {
-                usesValue = usesValue
-                        + ((usesValue.length() > 0) ? "," : "")
-                        + anImport.paths.get(pathIdx);
-            }
-        }
-        for (int i = 0; i < exports.size(); i++) {
-            Map<String, String> dirs = new HashMap<String, String>(1);
-            dirs.put(Constants.USES_DIRECTIVE, usesValue);
-            exports.set(i, new CapabilityImpl(
-                    exports.get(i).getResource(),
-                    BundleRevision.PACKAGE_NAMESPACE,
-                    dirs,
-                    exports.get(i).getAttributes()));
-        }
-
-        return exports;
-    }
-
-    private static ParsedHeaderClause parseBundleSymbolicName(Map<String, String> headerMap)
-            throws BundleException {
-        List<ParsedHeaderClause> clauses = parseStandardHeader(headerMap.get(Constants.BUNDLE_SYMBOLICNAME));
-        if (clauses.size() > 0) {
-            if (clauses.size() > 1 || clauses.get(0).paths.size() > 1) {
-                throw new BundleException("Cannot have multiple symbolic names: " + headerMap.get(Constants.BUNDLE_SYMBOLICNAME));
-            }
-
-            // Get bundle version.
-            Version bundleVersion = Version.emptyVersion;
-            if (headerMap.get(Constants.BUNDLE_VERSION) != null) {
-                bundleVersion = Version.parseVersion(headerMap.get(Constants.BUNDLE_VERSION));
-            }
-
-            // Create a require capability and return it.
-            ParsedHeaderClause clause = clauses.get(0);
-            String symName = clause.paths.get(0);
-            clause.attrs.put(BundleRevision.BUNDLE_NAMESPACE, symName);
-            clause.attrs.put(Constants.BUNDLE_VERSION_ATTRIBUTE, bundleVersion);
-            return clause;
-        }
-
-        return null;
-    }
-
-    private static List<RequirementImpl> parseFragmentHost(
-            Resource resource, Map<String, String> headerMap)
-            throws BundleException {
-        List<RequirementImpl> reqs = new ArrayList<RequirementImpl>();
-
-        List<ParsedHeaderClause> clauses = parseStandardHeader(headerMap.get(Constants.FRAGMENT_HOST));
-        if (clauses.size() > 0) {
-            // Make sure that only one fragment host symbolic name is specified.
-            if (clauses.size() > 1 || clauses.get(0).paths.size() > 1) {
-                throw new BundleException("Fragments cannot have multiple hosts: " + headerMap.get(Constants.FRAGMENT_HOST));
-            }
-
-            // If the bundle-version attribute is specified, then convert
-            // it to the proper type.
-            Object value = clauses.get(0).attrs.get(Constants.BUNDLE_VERSION_ATTRIBUTE);
-            value = (value == null) ? "0.0.0" : value;
-            clauses.get(0).attrs.put(Constants.BUNDLE_VERSION_ATTRIBUTE, VersionRange.parseVersionRange(value.toString()));
-
-            // Note that we use a linked hash map here to ensure the
-            // host symbolic name is first, which will make indexing
-            // more efficient.
-    // TODO: OSGi R4.3 - This is ordering is kind of hacky.
-            // Prepend the host symbolic name to the map of attributes.
-            Map<String, Object> attrs = clauses.get(0).attrs;
-            Map<String, Object> newAttrs = new LinkedHashMap<String, Object>(attrs.size() + 1);
-            // We want this first from an indexing perspective.
-            newAttrs.put(BundleRevision.HOST_NAMESPACE, clauses.get(0).paths.get(0));
-            newAttrs.putAll(attrs);
-            // But we need to put it again to make sure it wasn't overwritten.
-            newAttrs.put(BundleRevision.HOST_NAMESPACE, clauses.get(0).paths.get(0));
-
-            // Create filter now so we can inject filter directive.
-            SimpleFilter sf = SimpleFilter.convert(newAttrs);
-
-            // Inject filter directive.
-    // TODO: OSGi R4.3 - Can we insert this on demand somehow?
-            Map<String, String> dirs = clauses.get(0).dirs;
-            Map<String, String> newDirs = new HashMap<String, String>(dirs.size() + 1);
-            newDirs.putAll(dirs);
-            newDirs.put(Constants.FILTER_DIRECTIVE, sf.toString());
-
-            reqs.add(new RequirementImpl(
-                    resource, BundleRevision.HOST_NAMESPACE,
-                    newDirs,
-                    newAttrs));
-        }
-
-        return reqs;
-    }
-
-    private static List<ParsedHeaderClause> normalizeRequireClauses(List<ParsedHeaderClause> clauses) {
-        // Convert bundle version attribute to VersionRange type.
-        for (ParsedHeaderClause clause : clauses) {
-            Object value = clause.attrs.get(Constants.BUNDLE_VERSION_ATTRIBUTE);
-            if (value != null) {
-                clause.attrs.put(Constants.BUNDLE_VERSION_ATTRIBUTE, VersionRange.parseVersionRange(value.toString()));
-            }
-        }
-
-        return clauses;
-    }
-
-    private static List<Requirement> convertRequires(List<ParsedHeaderClause> clauses, Resource resource) {
-        List<Requirement> reqList = new ArrayList<Requirement>();
-        for (ParsedHeaderClause clause : clauses) {
-            for (String path : clause.paths) {
-                // Prepend the bundle symbolic name to the array of attributes.
-                Map<String, Object> attrs = clause.attrs;
-                // Note that we use a linked hash map here to ensure the
-                // symbolic name attribute is first, which will make indexing
-                // more efficient.
-    // TODO: OSGi R4.3 - This is ordering is kind of hacky.
-                // Prepend the symbolic name to the array of attributes.
-                Map<String, Object> newAttrs = new LinkedHashMap<String, Object>(attrs.size() + 1);
-                // We want this first from an indexing perspective.
-                newAttrs.put(BundleRevision.BUNDLE_NAMESPACE, path);
-                newAttrs.putAll(attrs);
-                // But we need to put it again to make sure it wasn't overwritten.
-                newAttrs.put(BundleRevision.BUNDLE_NAMESPACE, path);
-
-                // Create filter now so we can inject filter directive.
-                SimpleFilter sf = SimpleFilter.convert(newAttrs);
-
-                // Inject filter directive.
-    // TODO: OSGi R4.3 - Can we insert this on demand somehow?
-                Map<String, String> dirs = clause.dirs;
-                Map<String, String> newDirs = new HashMap<String, String>(dirs.size() + 1);
-                newDirs.putAll(dirs);
-                newDirs.put(Constants.FILTER_DIRECTIVE, sf.toString());
-
-                // Create package requirement and add to requirement list.
-                reqList.add(new RequirementImpl(resource, BundleRevision.BUNDLE_NAMESPACE, newDirs, newAttrs));
-            }
-        }
-
-        return reqList;
-    }
-
-    private static final char EOF = (char) -1;
-
-    private static char charAt(int pos, String headers, int length)
-    {
-        if (pos >= length)
-        {
-            return EOF;
-        }
-        return headers.charAt(pos);
-    }
-
-    private static final int CLAUSE_START = 0;
-    private static final int PARAMETER_START = 1;
-    private static final int KEY = 2;
-    private static final int DIRECTIVE_OR_TYPEDATTRIBUTE = 4;
-    private static final int ARGUMENT = 8;
-    private static final int VALUE = 16;
-
-    @SuppressWarnings({ "unchecked", "rawtypes" })
-    private static List<ParsedHeaderClause> parseStandardHeader(String header)
-    {
-        List<ParsedHeaderClause> clauses = new ArrayList<ParsedHeaderClause>();
-        if (header == null)
-        {
-            return clauses;
-        }
-        ParsedHeaderClause clause = null;
-        String key = null;
-        Map targetMap = null;
-        int state = CLAUSE_START;
-        int currentPosition = 0;
-        int startPosition = 0;
-        int length = header.length();
-        boolean quoted = false;
-        boolean escaped = false;
-
-        char currentChar = EOF;
-        do
-        {
-            currentChar = charAt(currentPosition, header, length);
-            switch (state)
-            {
-                case CLAUSE_START:
-                    clause = new ParsedHeaderClause();
-                    clauses.add(clause);
-                    state = PARAMETER_START;
-                case PARAMETER_START:
-                    startPosition = currentPosition;
-                    state = KEY;
-                case KEY:
-                    switch (currentChar)
-                    {
-                        case ':':
-                        case '=':
-                            key = header.substring(startPosition, currentPosition).trim();
-                            startPosition = currentPosition + 1;
-                            targetMap = clause.attrs;
-                            state = currentChar == ':' ? DIRECTIVE_OR_TYPEDATTRIBUTE : ARGUMENT;
-                            break;
-                        case EOF:
-                        case ',':
-                        case ';':
-                            clause.paths.add(header.substring(startPosition, currentPosition).trim());
-                            state = currentChar == ',' ? CLAUSE_START : PARAMETER_START;
-                            break;
-                        default:
-                            break;
-                    }
-                    currentPosition++;
-                    break;
-                case DIRECTIVE_OR_TYPEDATTRIBUTE:
-                    switch(currentChar)
-                    {
-                        case '=':
-                            if (startPosition != currentPosition)
-                            {
-                                clause.types.put(key, header.substring(startPosition, currentPosition).trim());
-                            }
-                            else
-                            {
-                                targetMap = clause.dirs;
-                            }
-                            state = ARGUMENT;
-                            startPosition = currentPosition + 1;
-                            break;
-                        default:
-                            break;
-                    }
-                    currentPosition++;
-                    break;
-                case ARGUMENT:
-                    if (currentChar == '\"')
-                    {
-                        quoted = true;
-                        currentPosition++;
-                    }
-                    else
-                    {
-                        quoted = false;
-                    }
-                    if (!Character.isWhitespace(currentChar)) {
-                        state = VALUE;
-                    }
-                    else {
-                        currentPosition++;
-                    }
-                    break;
-                case VALUE:
-                    if (escaped)
-                    {
-                        escaped = false;
-                    }
-                    else
-                    {
-                        if (currentChar == '\\' )
-                        {
-                            escaped = true;
-                        }
-                        else if (quoted && currentChar == '\"')
-                        {
-                            quoted = false;
-                        }
-                        else if (!quoted)
-                        {
-                            String value = null;
-                            switch(currentChar)
-                            {
-                                case EOF:
-                                case ';':
-                                case ',':
-                                    value = header.substring(startPosition, currentPosition).trim();
-                                    if (value.startsWith("\"") && value.endsWith("\""))
-                                    {
-                                        value = value.substring(1, value.length() - 1);
-                                    }
-                                    if (targetMap.put(key, value) != null)
-                                    {
-                                        throw new IllegalArgumentException(
-                                                "Duplicate '" + key + "' in: " + header);
-                                    }
-                                    state = currentChar == ';' ? PARAMETER_START : CLAUSE_START;
-                                    break;
-                                default:
-                                    break;
-                            }
-                        }
-                    }
-                    currentPosition++;
-                    break;
-                default:
-                    break;
-            }
-        } while ( currentChar != EOF);
-
-        if (state > PARAMETER_START)
-        {
-            throw new IllegalArgumentException("Unable to parse header: " + header);
-        }
-        return clauses;
-    }
-
-    public static List<String> parseDelimitedString(String value, String delim)
-    {
-        return parseDelimitedString(value, delim, true);
-    }
-
-    /**
-     * Parses delimited string and returns an array containing the tokens. This
-     * parser obeys quotes, so the delimiter character will be ignored if it is
-     * inside of a quote. This method assumes that the quote character is not
-     * included in the set of delimiter characters.
-     * @param value the delimited string to parse.
-     * @param delim the characters delimiting the tokens.
-     * @return a list of string or an empty list if there are none.
-     **/
-    public static List<String> parseDelimitedString(String value, String delim, boolean trim)
-    {
-        if (value == null)
-        {
-            value = "";
-        }
-
-        List<String> list = new ArrayList();
-
-        int CHAR = 1;
-        int DELIMITER = 2;
-        int STARTQUOTE = 4;
-        int ENDQUOTE = 8;
-
-        StringBuffer sb = new StringBuffer();
-
-        int expecting = (CHAR | DELIMITER | STARTQUOTE);
-
-        boolean isEscaped = false;
-        for (int i = 0; i < value.length(); i++)
-        {
-            char c = value.charAt(i);
-
-            boolean isDelimiter = (delim.indexOf(c) >= 0);
-
-            if (!isEscaped && (c == '\\'))
-            {
-                isEscaped = true;
-                continue;
-            }
-
-            if (isEscaped)
-            {
-                sb.append(c);
-            }
-            else if (isDelimiter && ((expecting & DELIMITER) > 0))
-            {
-                if (trim)
-                {
-                    list.add(sb.toString().trim());
-                }
-                else
-                {
-                    list.add(sb.toString());
-                }
-                sb.delete(0, sb.length());
-                expecting = (CHAR | DELIMITER | STARTQUOTE);
-            }
-            else if ((c == '"') && ((expecting & STARTQUOTE) > 0))
-            {
-                sb.append(c);
-                expecting = CHAR | ENDQUOTE;
-            }
-            else if ((c == '"') && ((expecting & ENDQUOTE) > 0))
-            {
-                sb.append(c);
-                expecting = (CHAR | STARTQUOTE | DELIMITER);
-            }
-            else if ((expecting & CHAR) > 0)
-            {
-                sb.append(c);
-            }
-            else
-            {
-                throw new IllegalArgumentException("Invalid delimited string: " + value);
-            }
-
-            isEscaped = false;
-        }
-
-        if (sb.length() > 0)
-        {
-            if (trim)
-            {
-                list.add(sb.toString().trim());
-            }
-            else
-            {
-                list.add(sb.toString());
-            }
-        }
-
-        return list;
-    }
-
-
-    static class ParsedHeaderClause {
-        public final List<String> paths = new ArrayList<String>();
-        public final Map<String, String> dirs = new LinkedHashMap<String, String>();
-        public final Map<String, Object> attrs = new LinkedHashMap<String, Object>();
-        public final Map<String, String> types = new LinkedHashMap<String, String>();
-    }
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/core/src/main/java/org/apache/karaf/features/internal/resolver/ResourceImpl.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/resolver/ResourceImpl.java b/features/core/src/main/java/org/apache/karaf/features/internal/resolver/ResourceImpl.java
deleted file mode 100644
index 18e0dc3..0000000
--- a/features/core/src/main/java/org/apache/karaf/features/internal/resolver/ResourceImpl.java
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * 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.karaf.features.internal.resolver;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import org.osgi.framework.Version;
-import org.osgi.framework.namespace.IdentityNamespace;
-import org.osgi.resource.Capability;
-import org.osgi.resource.Requirement;
-import org.osgi.resource.Resource;
-
-/**
- */
-public class ResourceImpl implements Resource {
-
-    private final List<Capability> m_caps;
-    private final List<Requirement> m_reqs;
-
-    public ResourceImpl(String name, Version version) {
-        this(name, IdentityNamespace.TYPE_BUNDLE, version);
-    }
-
-    public ResourceImpl(String name, String type, Version version)
-    {
-        m_caps = new ArrayList<Capability>();
-        m_caps.add(0, new IdentityCapability(this, name, type, version));
-        m_reqs = new ArrayList<Requirement>();
-    }
-
-    public void addCapability(Capability capability) {
-        assert capability.getResource() == this;
-        m_caps.add(capability);
-    }
-
-    public void addCapabilities(Iterable<? extends Capability> capabilities) {
-        for (Capability cap : capabilities) {
-            addCapability(cap);
-        }
-    }
-
-    public void addRequirement(Requirement requirement) {
-        assert requirement.getResource() == this;
-        m_reqs.add(requirement);
-    }
-
-    public void addRequirements(Iterable<? extends Requirement> requirements) {
-        for (Requirement req : requirements) {
-            addRequirement(req);
-        }
-    }
-
-    public List<Capability> getCapabilities(String namespace)
-    {
-        List<Capability> result = m_caps;
-        if (namespace != null)
-        {
-            result = new ArrayList<Capability>();
-            for (Capability cap : m_caps)
-            {
-                if (cap.getNamespace().equals(namespace))
-                {
-                    result.add(cap);
-                }
-            }
-        }
-        return result;
-    }
-
-    public List<Requirement> getRequirements(String namespace)
-    {
-        List<Requirement> result = m_reqs;
-        if (namespace != null)
-        {
-            result = new ArrayList<Requirement>();
-            for (Requirement req : m_reqs)
-            {
-                if (req.getNamespace().equals(namespace))
-                {
-                    result.add(req);
-                }
-            }
-        }
-        return result;
-    }
-
-    @Override
-    public String toString()
-    {
-        Capability cap = getCapabilities(IdentityNamespace.IDENTITY_NAMESPACE).get(0);
-        return cap.getAttributes().get(IdentityNamespace.IDENTITY_NAMESPACE) + "/"
-                + cap.getAttributes().get(IdentityNamespace.CAPABILITY_VERSION_ATTRIBUTE);
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/core/src/main/java/org/apache/karaf/features/internal/resolver/ServiceNamespace.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/resolver/ServiceNamespace.java b/features/core/src/main/java/org/apache/karaf/features/internal/resolver/ServiceNamespace.java
deleted file mode 100644
index 4fe3bf8..0000000
--- a/features/core/src/main/java/org/apache/karaf/features/internal/resolver/ServiceNamespace.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * 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.karaf.features.internal.resolver;
-
-import org.osgi.resource.Namespace;
-
-/**
- */
-public final class ServiceNamespace extends Namespace {
-
-    public static final String SERVICE_NAMESPACE = "service-reference";
-
-    private ServiceNamespace() {
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/core/src/main/java/org/apache/karaf/features/internal/resolver/SimpleFilter.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/resolver/SimpleFilter.java b/features/core/src/main/java/org/apache/karaf/features/internal/resolver/SimpleFilter.java
deleted file mode 100644
index ae10441..0000000
--- a/features/core/src/main/java/org/apache/karaf/features/internal/resolver/SimpleFilter.java
+++ /dev/null
@@ -1,649 +0,0 @@
-/*
- * 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.karaf.features.internal.resolver;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-
-import org.apache.felix.utils.version.VersionRange;
-
-public class SimpleFilter
-{
-    public static final int MATCH_ALL = 0;
-    public static final int AND = 1;
-    public static final int OR = 2;
-    public static final int NOT = 3;
-    public static final int EQ = 4;
-    public static final int LTE = 5;
-    public static final int GTE = 6;
-    public static final int SUBSTRING = 7;
-    public static final int PRESENT = 8;
-    public static final int APPROX = 9;
-
-    private final String m_name;
-    private final Object m_value;
-    private final int m_op;
-
-    public SimpleFilter(String attr, Object value, int op)
-    {
-        m_name = attr;
-        m_value = value;
-        m_op = op;
-    }
-
-    public String getName()
-    {
-        return m_name;
-    }
-
-    public Object getValue()
-    {
-        return m_value;
-    }
-
-    public int getOperation()
-    {
-        return m_op;
-    }
-
-    public String toString()
-    {
-        String s = null;
-        switch (m_op)
-        {
-            case AND:
-                s = "(&" + toString((List) m_value) + ")";
-                break;
-            case OR:
-                s = "(|" + toString((List) m_value) + ")";
-                break;
-            case NOT:
-                s = "(!" + toString((List) m_value) + ")";
-                break;
-            case EQ:
-                s = "(" + m_name + "=" + toEncodedString(m_value) + ")";
-                break;
-            case LTE:
-                s = "(" + m_name + "<=" + toEncodedString(m_value) + ")";
-                break;
-            case GTE:
-                s = "(" + m_name + ">=" + toEncodedString(m_value) + ")";
-                break;
-            case SUBSTRING:
-                s = "(" + m_name + "=" + unparseSubstring((List<String>) m_value) + ")";
-                break;
-            case PRESENT:
-                s = "(" + m_name + "=*)";
-                break;
-            case APPROX:
-                s = "(" + m_name + "~=" + toEncodedString(m_value) + ")";
-                break;
-            case MATCH_ALL:
-                s = "(*)";
-                break;
-        }
-        return s;
-    }
-
-    private static String toString(List list)
-    {
-        StringBuffer sb = new StringBuffer();
-        for (int i = 0; i < list.size(); i++)
-        {
-            sb.append(list.get(i).toString());
-        }
-        return sb.toString();
-    }
-
-    private static String toDecodedString(String s, int startIdx, int endIdx)
-    {
-        StringBuffer sb = new StringBuffer(endIdx - startIdx);
-        boolean escaped = false;
-        for (int i = 0; i < (endIdx - startIdx); i++)
-        {
-            char c = s.charAt(startIdx + i);
-            if (!escaped && (c == '\\'))
-            {
-                escaped = true;
-            }
-            else
-            {
-                escaped = false;
-                sb.append(c);
-            }
-        }
-
-        return sb.toString();
-    }
-
-    private static String toEncodedString(Object o)
-    {
-        if (o instanceof String)
-        {
-            String s = (String) o;
-            StringBuffer sb = new StringBuffer();
-            for (int i = 0; i < s.length(); i++)
-            {
-                char c = s.charAt(i);
-                if ((c == '\\') || (c == '(') || (c == ')') || (c == '*'))
-                {
-                    sb.append('\\');
-                }
-                sb.append(c);
-            }
-
-            o = sb.toString();
-        }
-
-        return o.toString();
-    }
-
-    public static SimpleFilter parse(String filter)
-    {
-        int idx = skipWhitespace(filter, 0);
-
-        if ((filter == null) || (filter.length() == 0) || (idx >= filter.length()))
-        {
-            throw new IllegalArgumentException("Null or empty filter.");
-        }
-        else if (filter.charAt(idx) != '(')
-        {
-            throw new IllegalArgumentException("Missing opening parenthesis: " + filter);
-        }
-
-        SimpleFilter sf = null;
-        List stack = new ArrayList();
-        boolean isEscaped = false;
-        while (idx < filter.length())
-        {
-            if (sf != null)
-            {
-                throw new IllegalArgumentException(
-                        "Only one top-level operation allowed: " + filter);
-            }
-
-            if (!isEscaped && (filter.charAt(idx) == '('))
-            {
-                // Skip paren and following whitespace.
-                idx = skipWhitespace(filter, idx + 1);
-
-                if (filter.charAt(idx) == '&')
-                {
-                    int peek = skipWhitespace(filter, idx + 1);
-                    if (filter.charAt(peek) == '(')
-                    {
-                        idx = peek - 1;
-                        stack.add(0, new SimpleFilter(null, new ArrayList(), SimpleFilter.AND));
-                    }
-                    else
-                    {
-                        stack.add(0, new Integer(idx));
-                    }
-                }
-                else if (filter.charAt(idx) == '|')
-                {
-                    int peek = skipWhitespace(filter, idx + 1);
-                    if (filter.charAt(peek) == '(')
-                    {
-                        idx = peek - 1;
-                        stack.add(0, new SimpleFilter(null, new ArrayList(), SimpleFilter.OR));
-                    }
-                    else
-                    {
-                        stack.add(0, new Integer(idx));
-                    }
-                }
-                else if (filter.charAt(idx) == '!')
-                {
-                    int peek = skipWhitespace(filter, idx + 1);
-                    if (filter.charAt(peek) == '(')
-                    {
-                        idx = peek - 1;
-                        stack.add(0, new SimpleFilter(null, new ArrayList(), SimpleFilter.NOT));
-                    }
-                    else
-                    {
-                        stack.add(0, new Integer(idx));
-                    }
-                }
-                else
-                {
-                    stack.add(0, new Integer(idx));
-                }
-            }
-            else if (!isEscaped && (filter.charAt(idx) == ')'))
-            {
-                Object top = stack.remove(0);
-                if (top instanceof SimpleFilter)
-                {
-                    if (!stack.isEmpty() && (stack.get(0) instanceof SimpleFilter))
-                    {
-                        ((List) ((SimpleFilter) stack.get(0)).m_value).add(top);
-                    }
-                    else
-                    {
-                        sf = (SimpleFilter) top;
-                    }
-                }
-                else if (!stack.isEmpty() && (stack.get(0) instanceof SimpleFilter))
-                {
-                    ((List) ((SimpleFilter) stack.get(0)).m_value).add(
-                            SimpleFilter.subfilter(filter, ((Integer) top).intValue(), idx));
-                }
-                else
-                {
-                    sf = SimpleFilter.subfilter(filter, ((Integer) top).intValue(), idx);
-                }
-            }
-            else if (!isEscaped && (filter.charAt(idx) == '\\'))
-            {
-                isEscaped = true;
-            }
-            else
-            {
-                isEscaped = false;
-            }
-
-            idx = skipWhitespace(filter, idx + 1);
-        }
-
-        if (sf == null)
-        {
-            throw new IllegalArgumentException("Missing closing parenthesis: " + filter);
-        }
-
-        return sf;
-    }
-
-    private static SimpleFilter subfilter(String filter, int startIdx, int endIdx)
-    {
-        final String opChars = "=<>~";
-
-        // Determine the ending index of the attribute name.
-        int attrEndIdx = startIdx;
-        for (int i = 0; i < (endIdx - startIdx); i++)
-        {
-            char c = filter.charAt(startIdx + i);
-            if (opChars.indexOf(c) >= 0)
-            {
-                break;
-            }
-            else if (!Character.isWhitespace(c))
-            {
-                attrEndIdx = startIdx + i + 1;
-            }
-        }
-        if (attrEndIdx == startIdx)
-        {
-            throw new IllegalArgumentException(
-                    "Missing attribute name: " + filter.substring(startIdx, endIdx));
-        }
-        String attr = filter.substring(startIdx, attrEndIdx);
-
-        // Skip the attribute name and any following whitespace.
-        startIdx = skipWhitespace(filter, attrEndIdx);
-
-        // Determine the operator type.
-        int op = -1;
-        switch (filter.charAt(startIdx))
-        {
-            case '=':
-                op = EQ;
-                startIdx++;
-                break;
-            case '<':
-                if (filter.charAt(startIdx + 1) != '=')
-                {
-                    throw new IllegalArgumentException(
-                            "Unknown operator: " + filter.substring(startIdx, endIdx));
-                }
-                op = LTE;
-                startIdx += 2;
-                break;
-            case '>':
-                if (filter.charAt(startIdx + 1) != '=')
-                {
-                    throw new IllegalArgumentException(
-                            "Unknown operator: " + filter.substring(startIdx, endIdx));
-                }
-                op = GTE;
-                startIdx += 2;
-                break;
-            case '~':
-                if (filter.charAt(startIdx + 1) != '=')
-                {
-                    throw new IllegalArgumentException(
-                            "Unknown operator: " + filter.substring(startIdx, endIdx));
-                }
-                op = APPROX;
-                startIdx += 2;
-                break;
-            default:
-                throw new IllegalArgumentException(
-                        "Unknown operator: " + filter.substring(startIdx, endIdx));
-        }
-
-        // Parse value.
-        Object value = toDecodedString(filter, startIdx, endIdx);
-
-        // Check if the equality comparison is actually a substring
-        // or present operation.
-        if (op == EQ)
-        {
-            String valueStr = filter.substring(startIdx, endIdx);
-            List<String> values = parseSubstring(valueStr);
-            if ((values.size() == 2)
-                    && (values.get(0).length() == 0)
-                    && (values.get(1).length() == 0))
-            {
-                op = PRESENT;
-            }
-            else if (values.size() > 1)
-            {
-                op = SUBSTRING;
-                value = values;
-            }
-        }
-
-        return new SimpleFilter(attr, value, op);
-    }
-
-    public static List<String> parseSubstring(String value)
-    {
-        List<String> pieces = new ArrayList();
-        StringBuffer ss = new StringBuffer();
-        // int kind = SIMPLE; // assume until proven otherwise
-        boolean wasStar = false; // indicates last piece was a star
-        boolean leftstar = false; // track if the initial piece is a star
-        boolean rightstar = false; // track if the final piece is a star
-
-        int idx = 0;
-
-        // We assume (sub)strings can contain leading and trailing blanks
-        boolean escaped = false;
-        loop:   for (;;)
-        {
-            if (idx >= value.length())
-            {
-                if (wasStar)
-                {
-                    // insert last piece as "" to handle trailing star
-                    rightstar = true;
-                }
-                else
-                {
-                    pieces.add(ss.toString());
-                    // accumulate the last piece
-                    // note that in the case of
-                    // (cn=); this might be
-                    // the string "" (!=null)
-                }
-                ss.setLength(0);
-                break loop;
-            }
-
-            // Read the next character and account for escapes.
-            char c = value.charAt(idx++);
-            if (!escaped && (c == '*'))
-            {
-                // If we have successive '*' characters, then we can
-                // effectively collapse them by ignoring succeeding ones.
-                if (!wasStar)
-                {
-                    if (ss.length() > 0)
-                    {
-                        pieces.add(ss.toString()); // accumulate the pieces
-                        // between '*' occurrences
-                    }
-                    ss.setLength(0);
-                    // if this is a leading star, then track it
-                    if (pieces.isEmpty())
-                    {
-                        leftstar = true;
-                    }
-                    wasStar = true;
-                }
-            }
-            else if (!escaped && (c == '\\'))
-            {
-                escaped = true;
-            }
-            else
-            {
-                escaped = false;
-                wasStar = false;
-                ss.append(c);
-            }
-        }
-        if (leftstar || rightstar || pieces.size() > 1)
-        {
-            // insert leading and/or trailing "" to anchor ends
-            if (rightstar)
-            {
-                pieces.add("");
-            }
-            if (leftstar)
-            {
-                pieces.add(0, "");
-            }
-        }
-        return pieces;
-    }
-
-    public static String unparseSubstring(List<String> pieces)
-    {
-        StringBuffer sb = new StringBuffer();
-        for (int i = 0; i < pieces.size(); i++)
-        {
-            if (i > 0)
-            {
-                sb.append("*");
-            }
-            sb.append(toEncodedString(pieces.get(i)));
-        }
-        return sb.toString();
-    }
-
-    public static boolean compareSubstring(List<String> pieces, String s)
-    {
-        // Walk the pieces to match the string
-        // There are implicit stars between each piece,
-        // and the first and last pieces might be "" to anchor the match.
-        // assert (pieces.length > 1)
-        // minimal case is <string>*<string>
-
-        boolean result = true;
-        int len = pieces.size();
-
-        // Special case, if there is only one piece, then
-        // we must perform an equality test.
-        if (len == 1)
-        {
-            return s.equals(pieces.get(0));
-        }
-
-        // Otherwise, check whether the pieces match
-        // the specified string.
-
-        int index = 0;
-
-        loop:   for (int i = 0; i < len; i++)
-        {
-            String piece = pieces.get(i);
-
-            // If this is the first piece, then make sure the
-            // string starts with it.
-            if (i == 0)
-            {
-                if (!s.startsWith(piece))
-                {
-                    result = false;
-                    break loop;
-                }
-            }
-
-            // If this is the last piece, then make sure the
-            // string ends with it.
-            if (i == (len - 1))
-            {
-                if (s.endsWith(piece) && (s.length() >= (index + piece.length())))
-                {
-                    result = true;
-                }
-                else
-                {
-                    result = false;
-                }
-                break loop;
-            }
-
-            // If this is neither the first or last piece, then
-            // make sure the string contains it.
-            if ((i > 0) && (i < (len - 1)))
-            {
-                index = s.indexOf(piece, index);
-                if (index < 0)
-                {
-                    result = false;
-                    break loop;
-                }
-            }
-
-            // Move string index beyond the matching piece.
-            index += piece.length();
-        }
-
-        return result;
-    }
-
-    private static int skipWhitespace(String s, int startIdx)
-    {
-        int len = s.length();
-        while ((startIdx < len) && Character.isWhitespace(s.charAt(startIdx)))
-        {
-            startIdx++;
-        }
-        return startIdx;
-    }
-
-    /**
-     * Converts a attribute map to a filter. The filter is created by iterating
-     * over the map's entry set. If ordering of attributes is important (e.g.,
-     * for hitting attribute indices), then the map's entry set should iterate
-     * in the desired order. Equality testing is assumed for all attribute types
-     * other than version ranges, which are handled appropriated. If the attribute
-     * map is empty, then a filter that matches anything is returned.
-     * @param attrs Map of attributes to convert to a filter.
-     * @return A filter corresponding to the attributes.
-     */
-    public static SimpleFilter convert(Map<String, Object> attrs)
-    {
-        // Rather than building a filter string to be parsed into a SimpleFilter,
-        // we will just create the parsed SimpleFilter directly.
-
-        List<SimpleFilter> filters = new ArrayList<SimpleFilter>();
-
-        for (Entry<String, Object> entry : attrs.entrySet())
-        {
-            if (entry.getValue() instanceof VersionRange)
-            {
-                VersionRange vr = (VersionRange) entry.getValue();
-                if (!vr.isOpenFloor())
-                {
-                    filters.add(
-                            new SimpleFilter(
-                                    entry.getKey(),
-                                    vr.getFloor().toString(),
-                                    SimpleFilter.GTE));
-                }
-                else
-                {
-                    SimpleFilter not =
-                            new SimpleFilter(null, new ArrayList(), SimpleFilter.NOT);
-                    ((List) not.getValue()).add(
-                            new SimpleFilter(
-                                    entry.getKey(),
-                                    vr.getFloor().toString(),
-                                    SimpleFilter.LTE));
-                    filters.add(not);
-                }
-
-                if (vr.getCeiling() != null)
-                {
-                    if (!vr.isOpenCeiling())
-                    {
-                        filters.add(
-                                new SimpleFilter(
-                                        entry.getKey(),
-                                        vr.getCeiling().toString(),
-                                        SimpleFilter.LTE));
-                    }
-                    else
-                    {
-                        SimpleFilter not =
-                                new SimpleFilter(null, new ArrayList(), SimpleFilter.NOT);
-                        ((List) not.getValue()).add(
-                                new SimpleFilter(
-                                        entry.getKey(),
-                                        vr.getCeiling().toString(),
-                                        SimpleFilter.GTE));
-                        filters.add(not);
-                    }
-                }
-            }
-            else
-            {
-                List<String> values = SimpleFilter.parseSubstring(entry.getValue().toString());
-                if (values.size() > 1)
-                {
-                    filters.add(
-                            new SimpleFilter(
-                                    entry.getKey(),
-                                    values,
-                                    SimpleFilter.SUBSTRING));
-                }
-                else
-                {
-                    filters.add(
-                            new SimpleFilter(
-                                    entry.getKey(),
-                                    values.get(0),
-                                    SimpleFilter.EQ));
-                }
-            }
-        }
-
-        SimpleFilter sf = null;
-
-        if (filters.size() == 1)
-        {
-            sf = filters.get(0);
-        }
-        else if (attrs.size() > 1)
-        {
-            sf = new SimpleFilter(null, filters, SimpleFilter.AND);
-        }
-        else if (filters.isEmpty())
-        {
-            sf = new SimpleFilter(null, null, SimpleFilter.MATCH_ALL);
-        }
-
-        return sf;
-    }
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/core/src/main/java/org/apache/karaf/features/internal/resolver/Slf4jResolverLog.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/resolver/Slf4jResolverLog.java b/features/core/src/main/java/org/apache/karaf/features/internal/resolver/Slf4jResolverLog.java
deleted file mode 100644
index 2f4a1f3..0000000
--- a/features/core/src/main/java/org/apache/karaf/features/internal/resolver/Slf4jResolverLog.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * 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.karaf.features.internal.resolver;
-
-import org.slf4j.Logger;
-
-/**
- */
-public class Slf4jResolverLog extends org.apache.felix.resolver.Logger {
-
-    private final Logger logger;
-
-    public Slf4jResolverLog(Logger logger) {
-        super(LOG_DEBUG);
-        this.logger = logger;
-    }
-
-    @Override
-    protected void doLog(int level, String msg, Throwable throwable) {
-        switch (level) {
-            case LOG_ERROR:
-                logger.error(msg, throwable);
-                break;
-            case LOG_WARNING:
-                logger.warn(msg, throwable);
-                break;
-            case LOG_INFO:
-                logger.info(msg, throwable);
-                break;
-            case LOG_DEBUG:
-                logger.debug(msg, throwable);
-                break;
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/core/src/main/java/org/apache/karaf/features/internal/resolver/UriNamespace.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/resolver/UriNamespace.java b/features/core/src/main/java/org/apache/karaf/features/internal/resolver/UriNamespace.java
deleted file mode 100644
index b5158bf..0000000
--- a/features/core/src/main/java/org/apache/karaf/features/internal/resolver/UriNamespace.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * 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.karaf.features.internal.resolver;
-
-import java.util.List;
-
-import org.osgi.resource.Capability;
-import org.osgi.resource.Namespace;
-import org.osgi.resource.Resource;
-
-/**
- */
-public final class UriNamespace extends Namespace {
-
-    public static final String URI_NAMESPACE = "karaf.uri";
-
-    public static String getUri(Resource resource)
-    {
-        List<Capability> caps = resource.getCapabilities(null);
-        for (Capability cap : caps)
-        {
-            if (cap.getNamespace().equals(UriNamespace.URI_NAMESPACE))
-            {
-                return cap.getAttributes().get(UriNamespace.URI_NAMESPACE).toString();
-            }
-        }
-        return null;
-    }
-
-
-    private UriNamespace() {
-    }
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/core/src/main/java/org/apache/karaf/features/internal/service/Artifact.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/service/Artifact.java b/features/core/src/main/java/org/apache/karaf/features/internal/service/Artifact.java
deleted file mode 100644
index 44e9a7c..0000000
--- a/features/core/src/main/java/org/apache/karaf/features/internal/service/Artifact.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * 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.karaf.features.internal.service;
-
-import java.net.URI;
-
-/**
- * Simple abstraction of a maven artifact to avoid external deps
- */
-public class Artifact {
-    String groupId;
-    String artifactId;
-    String version;
-    String extension;
-    String classifier;
-    
-    public Artifact(String coords) {
-        String[] coordsAr = coords.split(":");
-        if (coordsAr.length != 5) {
-            throw new IllegalArgumentException("Maven URL " + coords + " is malformed or not complete");
-        }
-        this.groupId = coordsAr[0];
-        this.artifactId = coordsAr[1];
-        this.version = coordsAr[4];
-        this.extension = coordsAr[2];
-        this.classifier = coordsAr[3];
-    }
-    
-    public Artifact(String coords, String version) {
-        this(coords);
-        this.version = version;
-    }
-    
-    public URI getMavenUrl(String version) {
-        String uriSt = "mvn:" + this.groupId + "/" + this.artifactId + "/" + version + "/" + this.extension + "/" + this.classifier;
-        try {
-            return new URI(uriSt);
-        } catch (Exception e) {
-            return null;
-        }
-    }
-}


[31/59] [abbrv] [KARAF-2852] Merge diagnostic/core and diagnostic/command

Posted by gn...@apache.org.
http://git-wip-us.apache.org/repos/asf/karaf/blob/886863a2/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/core/internal/osgi/Activator.java
----------------------------------------------------------------------
diff --git a/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/core/internal/osgi/Activator.java b/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/core/internal/osgi/Activator.java
deleted file mode 100644
index 7a01daf..0000000
--- a/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/core/internal/osgi/Activator.java
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * 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.karaf.diagnostic.core.internal.osgi;
-
-import java.util.ArrayList;
-import java.util.Hashtable;
-import java.util.List;
-
-import org.apache.karaf.diagnostic.core.DumpProvider;
-import org.apache.karaf.diagnostic.core.internal.BundleDumpProvider;
-import org.apache.karaf.diagnostic.core.internal.DiagnosticDumpMBeanImpl;
-import org.apache.karaf.diagnostic.core.internal.EnvironmentDumpProvider;
-import org.apache.karaf.diagnostic.core.internal.FeaturesDumpProvider;
-import org.apache.karaf.diagnostic.core.internal.HeapDumpProvider;
-import org.apache.karaf.diagnostic.core.internal.LogDumpProvider;
-import org.apache.karaf.diagnostic.core.internal.MemoryDumpProvider;
-import org.apache.karaf.diagnostic.core.internal.ThreadDumpProvider;
-import org.apache.karaf.features.FeaturesService;
-import org.apache.karaf.util.tracker.SingleServiceTracker;
-import org.osgi.framework.BundleActivator;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.ServiceReference;
-import org.osgi.framework.ServiceRegistration;
-import org.osgi.util.tracker.ServiceTracker;
-import org.osgi.util.tracker.ServiceTrackerCustomizer;
-
-public class Activator implements BundleActivator {
-
-    private List<ServiceRegistration<DumpProvider>> registrations;
-    private ServiceRegistration<DumpProvider> featuresProviderRegistration;
-    private ServiceRegistration mbeanRegistration;
-    private SingleServiceTracker<FeaturesService> featuresServiceTracker;
-    private ServiceTracker<DumpProvider, DumpProvider> providersTracker;
-
-    @Override
-    public void start(final BundleContext context) throws Exception {
-        registrations = new ArrayList<ServiceRegistration<DumpProvider>>();
-        registrations.add(context.registerService(DumpProvider.class, new BundleDumpProvider(context), null));
-        registrations.add(context.registerService(DumpProvider.class, new EnvironmentDumpProvider(context), null));
-        registrations.add(context.registerService(DumpProvider.class, new HeapDumpProvider(), null));
-        registrations.add(context.registerService(DumpProvider.class, new LogDumpProvider(context), null));
-        registrations.add(context.registerService(DumpProvider.class, new MemoryDumpProvider(), null));
-        registrations.add(context.registerService(DumpProvider.class, new ThreadDumpProvider(), null));
-
-        featuresServiceTracker = new SingleServiceTracker<FeaturesService>(context, FeaturesService.class, new SingleServiceTracker.SingleServiceListener() {
-            @Override
-            public void serviceFound() {
-                featuresProviderRegistration =
-                        context.registerService(
-                                DumpProvider.class,
-                                new FeaturesDumpProvider(featuresServiceTracker.getService()),
-                                null);
-            }
-            @Override
-            public void serviceLost() {
-            }
-            @Override
-            public void serviceReplaced() {
-                featuresProviderRegistration.unregister();
-            }
-        });
-
-        final DiagnosticDumpMBeanImpl diagnostic = new DiagnosticDumpMBeanImpl();
-        providersTracker = new ServiceTracker<DumpProvider, DumpProvider>(
-                context, DumpProvider.class, new ServiceTrackerCustomizer<DumpProvider, DumpProvider>() {
-            @Override
-            public DumpProvider addingService(ServiceReference<DumpProvider> reference) {
-                DumpProvider service = context.getService(reference);
-                diagnostic.registerProvider(service);
-                return service;
-            }
-            @Override
-            public void modifiedService(ServiceReference<DumpProvider> reference, DumpProvider service) {
-            }
-            @Override
-            public void removedService(ServiceReference<DumpProvider> reference, DumpProvider service) {
-                diagnostic.unregisterProvider(service);
-                context.ungetService(reference);
-            }
-        });
-        providersTracker.open();
-
-        Hashtable<String, Object> props = new Hashtable<String, Object>();
-        props.put("jmx.objectname", "org.apache.karaf:type=diagnostic,name=" + System.getProperty("karaf.name"));
-        mbeanRegistration = context.registerService(
-                getInterfaceNames(diagnostic),
-                diagnostic,
-                props
-        );
-    }
-
-    @Override
-    public void stop(BundleContext context) throws Exception {
-        mbeanRegistration.unregister();
-        featuresServiceTracker.close();
-        providersTracker.close();
-        for (ServiceRegistration<DumpProvider> reg : registrations) {
-            reg.unregister();
-        }
-    }
-
-    private String[] getInterfaceNames(Object object) {
-        List<String> names = new ArrayList<String>();
-        for (Class cl = object.getClass(); cl != Object.class; cl = cl.getSuperclass()) {
-            addSuperInterfaces(names, cl);
-        }
-        return names.toArray(new String[names.size()]);
-    }
-
-    private void addSuperInterfaces(List<String> names, Class clazz) {
-        for (Class cl : clazz.getInterfaces()) {
-            names.add(cl.getName());
-            addSuperInterfaces(names, cl);
-        }
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/886863a2/diagnostic/core/src/main/resources/OSGI-INF/bundle.info
----------------------------------------------------------------------
diff --git a/diagnostic/core/src/main/resources/OSGI-INF/bundle.info b/diagnostic/core/src/main/resources/OSGI-INF/bundle.info
deleted file mode 100644
index 15bc3cb..0000000
--- a/diagnostic/core/src/main/resources/OSGI-INF/bundle.info
+++ /dev/null
@@ -1,18 +0,0 @@
-h1. Synopsis
-
-${project.name}
-
-${project.description}
-
-Maven URL:
-[mvn:${project.groupId}/${project.artifactId}/${project.version}]
-
-h1. Description
-
-The diagnostic core bundle is the diagnostic core implementation.
-
-It's used by the diagnostic commands bundle and is responsible of the dump generation (environment, features, logs, bundles, threads).
-
-h1. See also
-
-Diagnostic - section of the Karaf User Guide.

http://git-wip-us.apache.org/repos/asf/karaf/blob/886863a2/diagnostic/pom.xml
----------------------------------------------------------------------
diff --git a/diagnostic/pom.xml b/diagnostic/pom.xml
index c40d93c..db61e04 100644
--- a/diagnostic/pom.xml
+++ b/diagnostic/pom.xml
@@ -29,13 +29,90 @@
     </parent>
 
     <groupId>org.apache.karaf.diagnostic</groupId>
-    <artifactId>diagnostic</artifactId>
-    <packaging>pom</packaging>
-    <name>Apache Karaf :: Diagnostic</name>
-
-    <modules>
-        <module>core</module>
-        <module>command</module>
-    </modules>
+    <artifactId>org.apache.karaf.diagnostic.core</artifactId>
+    <packaging>bundle</packaging>
+    <name>Apache Karaf :: Diagnostic :: Core</name>
+    <description>Core implementation using Karaf diagnostic using the diagnostic common services</description>
+
+    <properties>
+        <appendedResourcesDirectory>${basedir}/../../etc/appended-resources</appendedResourcesDirectory>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>org.osgi.core</artifactId>
+            <scope>provided</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>org.osgi.compendium</artifactId>
+            <scope>provided</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.karaf</groupId>
+            <artifactId>org.apache.karaf.util</artifactId>
+            <scope>provided</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.karaf.features</groupId>
+            <artifactId>org.apache.karaf.features.core</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.karaf.shell</groupId>
+            <artifactId>org.apache.karaf.shell.core</artifactId>
+            <optional>true</optional>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <resources>
+            <resource>
+                <directory>${project.basedir}/src/main/resources</directory>
+                <includes>
+                    <include>**/*</include>
+                </includes>
+            </resource>
+            <resource>
+                <directory>${project.basedir}/src/main/resources</directory>
+                <filtering>true</filtering>
+                <includes>
+                    <include>**/*.info</include>
+                </includes>
+            </resource>
+        </resources>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+                <configuration>
+                    <instructions>
+                        <Export-Package>
+                            org.apache.karaf.diagnostic.command,
+                        	org.apache.karaf.diagnostic.core,
+                            org.apache.karaf.diagnostic.core.common
+                       	</Export-Package>
+                        <Import-Package>
+                            com.sun.management*;resolution:=optional,
+                            *
+                        </Import-Package>
+                        <Private-Package>
+                            org.apache.karaf.diagnostic.core.internal,
+                            org.apache.karaf.diagnostic.core.internal.osgi,
+                            org.apache.karaf.util.tracker
+                        </Private-Package>
+                        <Bundle-Activator>
+                            org.apache.karaf.diagnostic.core.internal.osgi.Activator
+                        </Bundle-Activator>
+                        <Karaf-Commands>*</Karaf-Commands>
+                    </instructions>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
 
 </project>

http://git-wip-us.apache.org/repos/asf/karaf/blob/886863a2/diagnostic/src/main/java/org/apache/karaf/diagnostic/command/DumpCommand.java
----------------------------------------------------------------------
diff --git a/diagnostic/src/main/java/org/apache/karaf/diagnostic/command/DumpCommand.java b/diagnostic/src/main/java/org/apache/karaf/diagnostic/command/DumpCommand.java
new file mode 100644
index 0000000..3f6c607
--- /dev/null
+++ b/diagnostic/src/main/java/org/apache/karaf/diagnostic/command/DumpCommand.java
@@ -0,0 +1,97 @@
+/*
+ * 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.karaf.diagnostic.command;
+
+import java.io.File;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.LinkedList;
+import java.util.List;
+
+import org.apache.karaf.diagnostic.core.DumpDestination;
+import org.apache.karaf.diagnostic.core.DumpProvider;
+import org.apache.karaf.diagnostic.core.common.DirectoryDumpDestination;
+import org.apache.karaf.diagnostic.core.common.ZipDumpDestination;
+import org.apache.karaf.shell.api.action.Action;
+import org.apache.karaf.shell.api.action.Argument;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.Option;
+import org.apache.karaf.shell.api.action.lifecycle.Reference;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+
+/**
+ * Command to create dump from shell.
+ */
+@Command(scope = "dev", name = "dump-create", description = "Creates zip archive with diagnostic info.")
+@Service
+public class DumpCommand implements Action {
+
+    /**
+     * Output format of the filename if not defined otherwise
+     */
+    private SimpleDateFormat dumpFormat = new SimpleDateFormat("yyyy-MM-dd_HHmmss");
+
+    /**
+     * Directory switch.
+     */
+    @Option(name = "-d", aliases = "--directory", description = "Creates dump in a directory in place of a ZIP archive")
+    boolean directory;
+
+    /**
+     * Name of created directory or archive.
+     */
+    @Argument(name = "name", description = "Name of created zip or directory", required = false)
+    String fileName;
+
+    @Reference
+    List<DumpProvider> providers;
+
+    @Override
+    public Object execute() throws Exception {
+        DumpDestination destination;
+
+        if (providers.isEmpty()) {
+            System.out.println("Unable to create dump. No providers were found");
+            return null;
+        }
+
+        // create default file name if none provided
+        if (fileName == null || fileName.trim().length() == 0) {
+            fileName = dumpFormat.format(new Date());
+            if (!directory) {
+                fileName += ".zip";
+            }
+        }
+        File target = new File(fileName);
+
+        // if directory switch is on, create dump in directory
+        if (directory) {
+            destination = new DirectoryDumpDestination(target);
+        } else {
+            destination = new ZipDumpDestination(target);
+        }
+
+        for (DumpProvider provider : providers) {
+            provider.createDump(destination);
+        }
+        destination.save();
+        System.out.println("Diagnostic dump created at " + target.getAbsolutePath() + ".");
+
+        return null;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/886863a2/diagnostic/src/main/java/org/apache/karaf/diagnostic/core/DiagnosticDumpMBean.java
----------------------------------------------------------------------
diff --git a/diagnostic/src/main/java/org/apache/karaf/diagnostic/core/DiagnosticDumpMBean.java b/diagnostic/src/main/java/org/apache/karaf/diagnostic/core/DiagnosticDumpMBean.java
new file mode 100644
index 0000000..f59982a
--- /dev/null
+++ b/diagnostic/src/main/java/org/apache/karaf/diagnostic/core/DiagnosticDumpMBean.java
@@ -0,0 +1,42 @@
+/*
+ * 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.karaf.diagnostic.core;
+
+import javax.management.MBeanException;
+
+/**
+ * Diagnostic MBean which allows to create dumps over JMX.
+ */
+public interface DiagnosticDumpMBean {
+
+    /**
+     * Creates dump over JMX.
+     * 
+     * @param name Name of the dump.
+     * @throws Exception In case of any problems.
+     */
+    void createDump(String name) throws MBeanException;
+
+    /**
+     * Create dump with directory switch and name.
+     * 
+     * @param directory Should dump be created in directory.
+     * @param name Name of the dump.
+     * @throws Exception In case of any problems.
+     */
+    void createDump(boolean directory, String name) throws MBeanException;
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/886863a2/diagnostic/src/main/java/org/apache/karaf/diagnostic/core/DumpDestination.java
----------------------------------------------------------------------
diff --git a/diagnostic/src/main/java/org/apache/karaf/diagnostic/core/DumpDestination.java b/diagnostic/src/main/java/org/apache/karaf/diagnostic/core/DumpDestination.java
new file mode 100644
index 0000000..39c4edc
--- /dev/null
+++ b/diagnostic/src/main/java/org/apache/karaf/diagnostic/core/DumpDestination.java
@@ -0,0 +1,42 @@
+/*
+ * 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.karaf.diagnostic.core;
+
+import java.io.OutputStream;
+
+/**
+ * Destination for created dumps.
+ */
+public interface DumpDestination {
+
+    /**
+     * Creates new entry in dump destination.
+     * 
+     * Destination does not close returned output stream by default, dump
+     * provider should do this after completing write operation.
+     * 
+     * @param name Name of file in destination.
+     * @return Output stream ready to write.
+     * @throws Exception When entry cannot be added.
+     */
+    OutputStream add(String name) throws Exception;
+
+    /**
+     * Complete creation of the dump.
+     */
+    void save() throws Exception;
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/886863a2/diagnostic/src/main/java/org/apache/karaf/diagnostic/core/DumpProvider.java
----------------------------------------------------------------------
diff --git a/diagnostic/src/main/java/org/apache/karaf/diagnostic/core/DumpProvider.java b/diagnostic/src/main/java/org/apache/karaf/diagnostic/core/DumpProvider.java
new file mode 100644
index 0000000..ec7724c
--- /dev/null
+++ b/diagnostic/src/main/java/org/apache/karaf/diagnostic/core/DumpProvider.java
@@ -0,0 +1,29 @@
+/*
+ * 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.karaf.diagnostic.core;
+
+/**
+ * Interface which represents instance of tool which can provide dump
+ * information.
+ */
+public interface DumpProvider {
+
+    /**
+     * Creates dump in given entry.
+     */
+    void createDump(DumpDestination destination) throws Exception;
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/886863a2/diagnostic/src/main/java/org/apache/karaf/diagnostic/core/common/ClosingEntryOutputStreamWrapper.java
----------------------------------------------------------------------
diff --git a/diagnostic/src/main/java/org/apache/karaf/diagnostic/core/common/ClosingEntryOutputStreamWrapper.java b/diagnostic/src/main/java/org/apache/karaf/diagnostic/core/common/ClosingEntryOutputStreamWrapper.java
new file mode 100644
index 0000000..0c4f9db
--- /dev/null
+++ b/diagnostic/src/main/java/org/apache/karaf/diagnostic/core/common/ClosingEntryOutputStreamWrapper.java
@@ -0,0 +1,75 @@
+/*
+ * 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.karaf.diagnostic.core.common;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.zip.ZipOutputStream;
+
+/**
+ * Output stream which closes entry instead closing whole stream.
+ */
+public class ClosingEntryOutputStreamWrapper extends OutputStream {
+
+    /**
+     * Wrapped ZIP output stream. 
+     */
+    private ZipOutputStream outputStream;
+
+    /**
+     * Creates new OutputStream.
+     * 
+     * @param outputStream Wrapped output stream.
+     */
+    public ClosingEntryOutputStreamWrapper(ZipOutputStream outputStream) {
+        this.outputStream = outputStream;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void write(int b) throws IOException {
+        outputStream.write(b);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void write(byte[] b) throws IOException {
+        outputStream.write(b);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void write(byte[] b, int off, int len)
+        throws IOException {
+        outputStream.write(b, off, len);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void close() throws IOException {
+        // close entry instead of closing zip stream.
+        outputStream.closeEntry();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/886863a2/diagnostic/src/main/java/org/apache/karaf/diagnostic/core/common/DirectoryDumpDestination.java
----------------------------------------------------------------------
diff --git a/diagnostic/src/main/java/org/apache/karaf/diagnostic/core/common/DirectoryDumpDestination.java b/diagnostic/src/main/java/org/apache/karaf/diagnostic/core/common/DirectoryDumpDestination.java
new file mode 100644
index 0000000..37ae72e
--- /dev/null
+++ b/diagnostic/src/main/java/org/apache/karaf/diagnostic/core/common/DirectoryDumpDestination.java
@@ -0,0 +1,55 @@
+/*
+ * 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.karaf.diagnostic.core.common;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.OutputStream;
+
+import org.apache.karaf.diagnostic.core.DumpDestination;
+
+/**
+ * Class which packages dumps to given directory.
+ */
+public class DirectoryDumpDestination implements DumpDestination {
+
+	/**
+	 * Directory where dump files will be created.
+	 */
+	private File directory;
+
+	public DirectoryDumpDestination(File file) {
+		this.directory = file;
+
+		if (!file.exists()) {
+			file.mkdirs();
+		} 
+	}
+
+	public OutputStream add(String name) throws Exception {
+		File destination = new File(directory, name);
+		if (name.contains("/") || name.contains("\\")) {
+			// if name contains slashes we need to create sub directory
+			destination.getParentFile().mkdirs();
+		}
+		return new FileOutputStream(destination);
+	}
+
+	public void save() throws Exception {
+		// do nothing, all should be written to output streams
+	}
+	
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/886863a2/diagnostic/src/main/java/org/apache/karaf/diagnostic/core/common/TextDumpProvider.java
----------------------------------------------------------------------
diff --git a/diagnostic/src/main/java/org/apache/karaf/diagnostic/core/common/TextDumpProvider.java b/diagnostic/src/main/java/org/apache/karaf/diagnostic/core/common/TextDumpProvider.java
new file mode 100644
index 0000000..0b97d6f
--- /dev/null
+++ b/diagnostic/src/main/java/org/apache/karaf/diagnostic/core/common/TextDumpProvider.java
@@ -0,0 +1,66 @@
+/*
+ * 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.karaf.diagnostic.core.common;
+
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+
+import org.apache.karaf.diagnostic.core.DumpDestination;
+import org.apache.karaf.diagnostic.core.DumpProvider;
+
+/**
+ * Base class for dump providers which writes text to destination.
+ */
+public abstract class TextDumpProvider implements DumpProvider {
+
+    /**
+     * Name of the file.
+     */
+    private final String name;
+
+    /**
+     * Creates new dump provider.
+     * 
+     * @param name Name of the file.
+     */
+    protected TextDumpProvider(String name) {
+        this.name = name;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public final void createDump(DumpDestination destination) throws Exception {
+        OutputStream outputStream = destination.add(name);
+        OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream);
+        try {
+            writeDump(outputStreamWriter);
+        } finally {
+            outputStreamWriter.close();
+            outputStream.close();
+        }
+    }
+
+    /**
+     * This method should create output.
+     * 
+     * @param outputStreamWriter Stream which points to file specified in constructor.
+     * @throws Exception If any problem occur.
+     */
+    protected abstract void writeDump(OutputStreamWriter outputStreamWriter) throws Exception;
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/886863a2/diagnostic/src/main/java/org/apache/karaf/diagnostic/core/common/ZipDumpDestination.java
----------------------------------------------------------------------
diff --git a/diagnostic/src/main/java/org/apache/karaf/diagnostic/core/common/ZipDumpDestination.java b/diagnostic/src/main/java/org/apache/karaf/diagnostic/core/common/ZipDumpDestination.java
new file mode 100644
index 0000000..bafd38d
--- /dev/null
+++ b/diagnostic/src/main/java/org/apache/karaf/diagnostic/core/common/ZipDumpDestination.java
@@ -0,0 +1,79 @@
+/*
+ * 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.karaf.diagnostic.core.common;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.OutputStream;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipOutputStream;
+
+import org.apache.karaf.diagnostic.core.DumpDestination;
+
+/**
+ * Class which packages dumps to ZIP archive.
+ */
+public class ZipDumpDestination implements DumpDestination {
+
+    /**
+     * Destination streem.
+     */
+    private ZipOutputStream outputStream;
+
+    /**
+     * Creates new dump in given directory.
+     * 
+     * @param directory Target directory.
+     * @param name Name of the archive.
+     */
+    public ZipDumpDestination(File directory, String name) {
+        this(new File(directory, name));
+    }
+
+    /**
+     * Creates new dump in given file (zip archive). 
+     * 
+     * @param file Destination file.
+     */
+    public ZipDumpDestination(File file) {
+        try {
+            outputStream = new ZipOutputStream(new FileOutputStream(
+                file));
+        } catch (FileNotFoundException e) {
+            // sometimes this can occur, but we simply re throw and let 
+            // caller handle exception
+            throw new RuntimeException("Unable to create dump destination", e);
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public OutputStream add(String name) throws Exception {
+        ZipEntry zipEntry = new ZipEntry(name);
+        outputStream.putNextEntry(zipEntry);
+        return new ClosingEntryOutputStreamWrapper(outputStream);
+    }
+
+    /**
+     * Closes archive handle.
+     */
+    public void save() throws Exception {
+        outputStream.close();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/886863a2/diagnostic/src/main/java/org/apache/karaf/diagnostic/core/internal/BundleDumpProvider.java
----------------------------------------------------------------------
diff --git a/diagnostic/src/main/java/org/apache/karaf/diagnostic/core/internal/BundleDumpProvider.java b/diagnostic/src/main/java/org/apache/karaf/diagnostic/core/internal/BundleDumpProvider.java
new file mode 100644
index 0000000..774dc1f
--- /dev/null
+++ b/diagnostic/src/main/java/org/apache/karaf/diagnostic/core/internal/BundleDumpProvider.java
@@ -0,0 +1,85 @@
+/*
+ * 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.karaf.diagnostic.core.internal;
+
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.karaf.diagnostic.core.common.TextDumpProvider;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+
+/**
+ * Dump provider which produces file named bundles.txt with list of
+ * installed bundles and it's state.
+ */
+public class BundleDumpProvider extends TextDumpProvider {
+
+    /**
+     * Static map with state mask to string representation.
+     */
+    private static Map<Integer, String> stateMap = new HashMap<Integer, String>();
+
+    /**
+     * Map bundle states to string representation.
+     */
+    static {
+        stateMap.put(0x00000001, "UNINSTALLED");
+        stateMap.put(0x00000002, "INSTALLED");
+        stateMap.put(0x00000004, "RESOLVED");
+        stateMap.put(0x00000008, "STARTING");
+        stateMap.put(0x00000010, "STOPPING");
+        stateMap.put(0x00000020, "ACTIVE");
+    }
+
+    /**
+     * Bundle context.
+     */
+    private BundleContext bundleContext;
+
+    /**
+     * Creates new bundle information file.
+     *  
+     * @param context Bundle context to access framework state.
+     */
+    public BundleDumpProvider(BundleContext context) {
+        super("bundles.txt");
+        this.bundleContext = context;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    protected void writeDump(OutputStreamWriter writer) throws IOException {
+        // get bundle states
+        Bundle[] bundles = bundleContext.getBundles();
+
+        writer.write("Number of installed bundles " + bundles.length + "\n");
+
+        // create file header
+        writer.write("Id\tSymbolic name\tVersion\tState\n");
+        for (Bundle bundle : bundles) {
+            // write row :)
+            writer.write(bundle.getBundleId() + "\t" + bundle.getSymbolicName() + '\t' + bundle.getVersion()
+                + "\t" + stateMap.get(bundle.getState()) + "\n");
+        }
+
+        writer.flush();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/886863a2/diagnostic/src/main/java/org/apache/karaf/diagnostic/core/internal/DiagnosticDumpMBeanImpl.java
----------------------------------------------------------------------
diff --git a/diagnostic/src/main/java/org/apache/karaf/diagnostic/core/internal/DiagnosticDumpMBeanImpl.java b/diagnostic/src/main/java/org/apache/karaf/diagnostic/core/internal/DiagnosticDumpMBeanImpl.java
new file mode 100644
index 0000000..22e09c9
--- /dev/null
+++ b/diagnostic/src/main/java/org/apache/karaf/diagnostic/core/internal/DiagnosticDumpMBeanImpl.java
@@ -0,0 +1,89 @@
+/*
+ * 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.diagnostic.core.internal;
+
+import java.io.File;
+import java.util.List;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+import javax.management.MBeanException;
+import javax.management.NotCompliantMBeanException;
+import javax.management.StandardMBean;
+
+import org.apache.karaf.diagnostic.core.DiagnosticDumpMBean;
+import org.apache.karaf.diagnostic.core.DumpDestination;
+import org.apache.karaf.diagnostic.core.DumpProvider;
+import org.apache.karaf.diagnostic.core.common.DirectoryDumpDestination;
+import org.apache.karaf.diagnostic.core.common.ZipDumpDestination;
+
+/**
+ * Implementation of diagnostic MBean.
+ */
+public class DiagnosticDumpMBeanImpl extends StandardMBean implements DiagnosticDumpMBean {
+
+    /**
+     * Dump providers.
+     */
+    private final List<DumpProvider> providers = new CopyOnWriteArrayList<DumpProvider>();
+
+    /**
+     * Creates new diagnostic mbean.
+     *
+     * @throws NotCompliantMBeanException
+     */
+    public DiagnosticDumpMBeanImpl() throws NotCompliantMBeanException {
+        super(DiagnosticDumpMBean.class);
+    }
+
+    /**
+     * Creates dump witch given name
+     *
+     * @param name Name of the dump.
+     */
+    public void createDump(String name) throws MBeanException {
+        createDump(false, name);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void createDump(boolean directory, String name) throws MBeanException {
+        try {
+            File target = new File(name);
+
+            DumpDestination destination;
+            if (directory) {
+                destination = new DirectoryDumpDestination(target);
+            } else {
+                destination = new ZipDumpDestination(target);
+            }
+
+            for (DumpProvider provider : providers) {
+                provider.createDump(destination);
+            }
+
+            destination.save();
+        } catch (Exception e) {
+            throw new MBeanException(null, e.getMessage());
+        }
+    }
+
+    public void registerProvider(DumpProvider provider) {
+        providers.add(provider);
+    }
+
+    public void unregisterProvider(DumpProvider provider) {
+        providers.add(provider);
+    }
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/886863a2/diagnostic/src/main/java/org/apache/karaf/diagnostic/core/internal/EnvironmentDumpProvider.java
----------------------------------------------------------------------
diff --git a/diagnostic/src/main/java/org/apache/karaf/diagnostic/core/internal/EnvironmentDumpProvider.java b/diagnostic/src/main/java/org/apache/karaf/diagnostic/core/internal/EnvironmentDumpProvider.java
new file mode 100644
index 0000000..3328067
--- /dev/null
+++ b/diagnostic/src/main/java/org/apache/karaf/diagnostic/core/internal/EnvironmentDumpProvider.java
@@ -0,0 +1,291 @@
+/*
+ * 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.karaf.diagnostic.core.internal;
+
+import java.io.OutputStreamWriter;
+import java.io.PrintWriter;
+import java.lang.management.ClassLoadingMXBean;
+import java.lang.management.CompilationMXBean;
+import java.lang.management.GarbageCollectorMXBean;
+import java.lang.management.ManagementFactory;
+import java.lang.management.MemoryMXBean;
+import java.lang.management.MemoryUsage;
+import java.lang.management.OperatingSystemMXBean;
+import java.lang.management.RuntimeMXBean;
+import java.lang.management.ThreadMXBean;
+import java.text.DateFormat;
+import java.text.DecimalFormat;
+import java.text.DecimalFormatSymbols;
+import java.text.NumberFormat;
+import java.util.Date;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import org.apache.karaf.diagnostic.core.common.TextDumpProvider;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Version;
+
+/**
+ * Provider which dumps runtime environment information to file named environment.txt.
+ */
+public class EnvironmentDumpProvider extends TextDumpProvider {
+    
+    private static final String KEY_VALUE_FORMAT = "%1$s\t: %2$s";
+    private static final String INDENT_KEY_VALUE_FORMAT = "    "+KEY_VALUE_FORMAT;
+    private final BundleContext bundleContext;
+
+    /**
+     * Creates new dump entry which contains information about the runtime environment.
+     */
+    public EnvironmentDumpProvider(final BundleContext context) {
+        super("environment.txt");
+        this.bundleContext = context;
+    }
+
+    @Override
+    protected void writeDump(final OutputStreamWriter outputStream) throws Exception {
+    if( null == outputStream) {
+        return;
+    }
+    final PrintWriter outPW = new PrintWriter(outputStream);
+    // current date/time
+    final DateFormat dateTimeFormatInstance = DateFormat.getDateTimeInstance(DateFormat.FULL, DateFormat.FULL, Locale.ENGLISH);
+    outPW.printf(KEY_VALUE_FORMAT,"Dump timestamp", dateTimeFormatInstance.format(new Date(System.currentTimeMillis()))).println();
+    outPW.println();
+    // karaf information
+    dumpKarafInformation(outPW);
+    outPW.println();
+    // OSGi information
+    dumpOSGiInformation(outPW);
+    outPW.println();
+    // OS information
+    dumpOSInformation(outPW);
+    outPW.println();
+    // general information about JVM
+    dumpVMInformation(outPW, dateTimeFormatInstance);
+    outPW.println();
+    // threads
+    dumpThreadsInformation(outPW);
+    outPW.println();
+    // classes
+    dumpClassesInformation(outPW);
+    outPW.println();
+    // memory
+    dumpMemoryInformation(outPW);
+    outPW.println();
+    // garbage collector
+    dumpGCInformation(outPW);
+    }
+
+    private void dumpKarafInformation(final PrintWriter outPW) {
+        outPW.printf(KEY_VALUE_FORMAT, "Karaf", System.getProperty("karaf.name", "root") + ' ' + System.getProperty("karaf.version", "")).println();
+        outPW.printf(INDENT_KEY_VALUE_FORMAT, "home", System.getProperty("karaf.home", "")).println();
+        outPW.printf(INDENT_KEY_VALUE_FORMAT, "base", System.getProperty("karaf.base", "")).println();
+    }
+
+    private void dumpOSGiInformation(final PrintWriter outPW) {
+        if( null == bundleContext ) {
+            return;
+        }
+        outPW.println("OSGi:");
+        final Bundle[] bundles = bundleContext.getBundles();
+        for (final Bundle bundle : bundles) {
+            if( null == bundle || !!!"osgi.core".equals(bundle.getSymbolicName())) {
+                continue;
+            }
+            outPW.printf(INDENT_KEY_VALUE_FORMAT, "version", bundle.getVersion()).println();
+            break;
+        }
+        outPW.printf(INDENT_KEY_VALUE_FORMAT, "framework", bundleContext.getBundle(0).getSymbolicName() + " - " +
+                bundleContext.getBundle(0).getVersion()).println();
+    }
+
+    private void dumpOSInformation(final PrintWriter outPW) {
+        final OperatingSystemMXBean mxBean = ManagementFactory.getOperatingSystemMXBean();
+        if( null == mxBean) {
+            return;
+        }
+        outPW.printf(KEY_VALUE_FORMAT, "Operating System", mxBean.getName() + ' ' + mxBean.getVersion()).println();
+        outPW.printf(INDENT_KEY_VALUE_FORMAT, "architecture", mxBean.getArch()).println();
+        outPW.printf(INDENT_KEY_VALUE_FORMAT, "processors", mxBean.getAvailableProcessors()).println();
+//        outPW.printf(INDENT_KEY_VALUE_FORMAT, "current system load average", mxBean.getSystemLoadAverage()).println();
+    }
+
+    private void dumpVMInformation(final PrintWriter outPW,
+        final DateFormat dateTimeFormatInstance) {
+        final RuntimeMXBean mxBean = ManagementFactory.getRuntimeMXBean();
+        if( mxBean == null ) {
+            return;
+        }
+        outPW.printf(KEY_VALUE_FORMAT,"Instance name", mxBean.getName()).println();
+        outPW.printf(KEY_VALUE_FORMAT,"Start time", dateTimeFormatInstance.format(new Date(mxBean.getStartTime()))).println();
+        outPW.printf(KEY_VALUE_FORMAT,"Uptime", printDuration(mxBean.getUptime())).println();
+        outPW.println();
+        outPW.printf(KEY_VALUE_FORMAT, "Java VM", mxBean.getVmName() + " " + mxBean.getVmVersion()).println();
+        outPW.printf(INDENT_KEY_VALUE_FORMAT, "vendor", mxBean.getVmVendor()).println();
+        outPW.printf(INDENT_KEY_VALUE_FORMAT, "version", System.getProperty("java.version")).println();
+        outPW.println();
+        outPW.println("Input arguments:");
+        final List<String> inputArguments = mxBean.getInputArguments();
+        for (final String argument : inputArguments) {
+            if( argument != null && argument.contains("=")) {
+                final String[] split = argument.split("=");
+                outPW.printf(INDENT_KEY_VALUE_FORMAT, split[0], split[1]).println();
+            } else {
+                outPW.printf(INDENT_KEY_VALUE_FORMAT, argument,"").println();
+            }
+        }
+        outPW.println("Classpath:");
+        outPW.printf(INDENT_KEY_VALUE_FORMAT, "boot classpath", mxBean.getBootClassPath()).println();
+        outPW.printf(INDENT_KEY_VALUE_FORMAT, "library path", mxBean.getLibraryPath()).println();
+        outPW.printf(INDENT_KEY_VALUE_FORMAT, "classpath", mxBean.getClassPath()).println();
+        outPW.println("System properties:");
+        final Map<String, String> systemProperties = mxBean.getSystemProperties();
+        for (final Entry<String, String> property : systemProperties.entrySet()) {
+            outPW.printf(INDENT_KEY_VALUE_FORMAT, property.getKey(), property.getValue()).println();
+        }
+        outPW.println();
+        // JIT information
+        final CompilationMXBean compilationMXBean = ManagementFactory.getCompilationMXBean();
+        if( compilationMXBean != null ) {
+            outPW.printf(KEY_VALUE_FORMAT, "JIT compiler", compilationMXBean.getName()).println();
+            outPW.printf(INDENT_KEY_VALUE_FORMAT, "total compile time", printDuration(compilationMXBean.getTotalCompilationTime())).println();
+        }
+    }
+
+    private void dumpThreadsInformation(final PrintWriter outPW) {
+        final ThreadMXBean mxBean = ManagementFactory.getThreadMXBean();
+        if( null == mxBean) {
+            return;
+        }
+        outPW.println("Threads:");
+        outPW.printf(INDENT_KEY_VALUE_FORMAT, "live", formatLong(mxBean.getThreadCount())).println();
+        outPW.printf(INDENT_KEY_VALUE_FORMAT, "daemon", formatLong(mxBean.getDaemonThreadCount())).println();
+        outPW.printf(INDENT_KEY_VALUE_FORMAT, "peak", formatLong(mxBean.getPeakThreadCount())).println();
+        outPW.printf(INDENT_KEY_VALUE_FORMAT, "total", formatLong(mxBean.getTotalStartedThreadCount())).println();
+    }
+
+    private void dumpClassesInformation(final PrintWriter outPW) {
+        final ClassLoadingMXBean mxBean = ManagementFactory.getClassLoadingMXBean();
+        if( null == mxBean) {
+            return;
+        }
+        outPW.println("Classes:");
+        outPW.printf(INDENT_KEY_VALUE_FORMAT, "loaded", formatLong(mxBean.getLoadedClassCount())).println();
+        outPW.printf(INDENT_KEY_VALUE_FORMAT, "total", formatLong(mxBean.getTotalLoadedClassCount())).println();
+        outPW.printf(INDENT_KEY_VALUE_FORMAT, "unloaded", formatLong(mxBean.getUnloadedClassCount())).println();
+    }
+
+    private void dumpMemoryInformation(final PrintWriter outPW) {
+        final MemoryMXBean mxBean = ManagementFactory.getMemoryMXBean();
+        if( null == mxBean) {
+            return;
+        }
+        final MemoryUsage heapMemoryUsage = mxBean.getHeapMemoryUsage();
+        final MemoryUsage nonHeapMemoryUsage = mxBean.getNonHeapMemoryUsage();
+        if( heapMemoryUsage != null ) {
+            outPW.println("HEAP Memory:");
+            outPW.printf(INDENT_KEY_VALUE_FORMAT, "commited", printMemory(heapMemoryUsage.getCommitted())).println();
+            outPW.printf(INDENT_KEY_VALUE_FORMAT, "init", printMemory(heapMemoryUsage.getInit())).println();
+            outPW.printf(INDENT_KEY_VALUE_FORMAT, "used", printMemory(heapMemoryUsage.getUsed())).println();
+            outPW.printf(INDENT_KEY_VALUE_FORMAT, "maximal", printMemory(heapMemoryUsage.getMax())).println();
+        }
+        if( nonHeapMemoryUsage != null ) {
+            outPW.println("NON-HEAP Memory:");
+            outPW.printf(INDENT_KEY_VALUE_FORMAT, "commited", printMemory(nonHeapMemoryUsage.getCommitted())).println();
+            outPW.printf(INDENT_KEY_VALUE_FORMAT, "init", printMemory(nonHeapMemoryUsage.getInit())).println();
+            outPW.printf(INDENT_KEY_VALUE_FORMAT, "used", printMemory(nonHeapMemoryUsage.getUsed())).println();
+            outPW.printf(INDENT_KEY_VALUE_FORMAT, "maximal", printMemory(nonHeapMemoryUsage.getMax())).println();
+        }
+    }
+
+    private void dumpGCInformation(final PrintWriter outPW) {
+        final List<GarbageCollectorMXBean> mxBeans = ManagementFactory.getGarbageCollectorMXBeans();
+        if( null == mxBeans || mxBeans.isEmpty()) {
+            return;
+        }
+        final MemoryMXBean memoryMxBean = ManagementFactory.getMemoryMXBean();
+        if( memoryMxBean != null ) {
+            outPW.printf(INDENT_KEY_VALUE_FORMAT, "pending objects", formatLong(memoryMxBean.getObjectPendingFinalizationCount())).println();
+        }
+        final String gcFormat ="'%1$s' collections: %2$s\ttime: %3$s";
+        outPW.println();
+        for (final GarbageCollectorMXBean mxBean : mxBeans) {
+            if( null == mxBean) {
+                continue;
+            }
+            outPW.printf(KEY_VALUE_FORMAT, "Garbage Collectors", String.format(gcFormat, mxBean.getName(), formatLong(mxBean.getCollectionCount()), printDuration(mxBean.getCollectionTime()))).println();
+        }
+    }
+
+
+    private String formatLong(final long longValue) {
+        final NumberFormat fmtI = new DecimalFormat("###,###", new DecimalFormatSymbols(Locale.ENGLISH));
+        return fmtI.format(longValue);
+    }
+
+    private String printMemory(final long bytes) {
+        if( bytes <= 1024) {
+            return formatLong(bytes)+" bytes";
+        }
+        return formatLong(bytes/1024)+" kbytes";
+    }
+
+    /**
+     * Prints the duration in a human readable format as X days Y hours Z minutes etc.
+     *
+     * @param uptime the uptime in millis
+     * @return the time used for displaying on screen or in logs
+     */
+    private String printDuration(double uptime) {
+        // Code based on code taken from Karaf
+        // https://svn.apache.org/repos/asf/karaf/trunk/shell/commands/src/main/java/org/apache/karaf/shell/commands/impl/InfoAction.java
+
+        uptime /= 1000;
+        if (uptime < 60) {
+            final NumberFormat fmtD = new DecimalFormat("###,##0.000", new DecimalFormatSymbols(Locale.ENGLISH));
+            return fmtD.format(uptime) + " seconds";
+        }
+        uptime /= 60;
+        if (uptime < 60) {
+            final long minutes = (long) uptime;
+            final String s = formatLong(minutes) + (minutes > 1 ? " minutes" : " minute");
+            return s;
+        }
+        uptime /= 60;
+        if (uptime < 24) {
+            final long hours = (long) uptime;
+            final long minutes = (long) ((uptime - hours) * 60);
+            String s = formatLong(hours) + (hours > 1 ? " hours" : " hour");
+            if (minutes != 0) {
+                s += " " + formatLong(minutes) + (minutes > 1 ? " minutes" : " minute");
+            }
+            return s;
+        }
+        uptime /= 24;
+        final long days = (long) uptime;
+        final long hours = (long) ((uptime - days) * 24);
+        String s = formatLong(days) + (days > 1 ? " days" : " day");
+        if (hours != 0) {
+            s += " " + formatLong(hours) + (hours > 1 ? " hours" : " hour");
+        }
+        return s;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/886863a2/diagnostic/src/main/java/org/apache/karaf/diagnostic/core/internal/FeaturesDumpProvider.java
----------------------------------------------------------------------
diff --git a/diagnostic/src/main/java/org/apache/karaf/diagnostic/core/internal/FeaturesDumpProvider.java b/diagnostic/src/main/java/org/apache/karaf/diagnostic/core/internal/FeaturesDumpProvider.java
new file mode 100644
index 0000000..e5fa55e
--- /dev/null
+++ b/diagnostic/src/main/java/org/apache/karaf/diagnostic/core/internal/FeaturesDumpProvider.java
@@ -0,0 +1,79 @@
+/*
+ * 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.karaf.diagnostic.core.internal;
+
+import java.io.OutputStreamWriter;
+
+import org.apache.karaf.diagnostic.core.common.TextDumpProvider;
+import org.apache.karaf.features.BundleInfo;
+import org.apache.karaf.features.Feature;
+import org.apache.karaf.features.FeaturesService;
+import org.apache.karaf.features.Repository;
+
+/**
+ * Dump provider which add file named features.txt with informations
+ * about installed features and repositories.
+ */
+public class FeaturesDumpProvider extends TextDumpProvider {
+
+    /**
+     * Feature service.
+     */
+    private final FeaturesService features;
+
+    /**
+     * Creates new dump entry witch contains information about
+     * karaf features.
+     * 
+     * @param features Feature service.
+     */
+    public FeaturesDumpProvider(FeaturesService features) {
+        super("features.txt");
+        this.features = features;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    protected void writeDump(OutputStreamWriter outputStreamWriter) throws Exception {
+        // creates header
+        outputStreamWriter.write("Repositories:\n");
+
+        // list repositories
+        for (Repository repo : features.listRepositories()) {
+            outputStreamWriter.write(repo.getURI() + " (" + repo.getName() + ")\n");
+        }
+
+        // list features
+        outputStreamWriter.write("\nfeatures:\n");
+        for (Feature feature : features.listFeatures()) {
+            outputStreamWriter.write(feature.getName() + " " + feature.getVersion());
+            outputStreamWriter.write(" installed: " + features.isInstalled(feature));
+            outputStreamWriter.write("\nBundles:\n");
+            for (BundleInfo bundle : feature.getBundles()) {
+                outputStreamWriter.write("\t" + bundle.getLocation());
+                if (bundle.getStartLevel() != 0) {
+                    outputStreamWriter.write(" start level " + bundle.getStartLevel());
+                }
+                outputStreamWriter.write("\n\n");
+            }
+        }
+
+        // flush & close stream
+        outputStreamWriter.close();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/886863a2/diagnostic/src/main/java/org/apache/karaf/diagnostic/core/internal/HeapDumpProvider.java
----------------------------------------------------------------------
diff --git a/diagnostic/src/main/java/org/apache/karaf/diagnostic/core/internal/HeapDumpProvider.java b/diagnostic/src/main/java/org/apache/karaf/diagnostic/core/internal/HeapDumpProvider.java
new file mode 100644
index 0000000..b86f57b
--- /dev/null
+++ b/diagnostic/src/main/java/org/apache/karaf/diagnostic/core/internal/HeapDumpProvider.java
@@ -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.karaf.diagnostic.core.internal;
+
+import com.sun.management.HotSpotDiagnosticMXBean;
+import org.apache.karaf.diagnostic.core.DumpDestination;
+import org.apache.karaf.diagnostic.core.DumpProvider;
+
+import javax.management.MBeanServer;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.OutputStream;
+import java.lang.management.ManagementFactory;
+
+/**
+ * Create a heap dump.
+ */
+public class HeapDumpProvider implements DumpProvider {
+
+    @Override
+    public void createDump(DumpDestination destination) throws Exception {
+        FileInputStream in = null;
+        OutputStream out = null;
+        try {
+            MBeanServer mBeanServer = ManagementFactory.getPlatformMBeanServer();
+            HotSpotDiagnosticMXBean diagnosticMXBean = ManagementFactory.newPlatformMXBeanProxy(mBeanServer,
+                    "com.sun.management:type=HotSpotDiagnostic", HotSpotDiagnosticMXBean.class);
+            diagnosticMXBean.dumpHeap("heapdump.txt", false);
+            // copy the dump in the destination
+            File heapDumpFile = new File("heapdump.txt");
+            in = new FileInputStream(heapDumpFile);
+            out = destination.add("heapdump.txt");
+            byte[] buffer = new byte[2048];
+            while ((in.read(buffer) != -1)) {
+                out.write(buffer);
+            }
+            // remove the original dump
+            if (heapDumpFile.exists()) {
+                heapDumpFile.delete();
+            }
+        } catch (Exception e) {
+            // nothing to do
+        } finally {
+            if (in != null) {
+                in.close();
+            }
+            if (out != null) {
+                out.flush();
+                out.close();
+            }
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/886863a2/diagnostic/src/main/java/org/apache/karaf/diagnostic/core/internal/LogDumpProvider.java
----------------------------------------------------------------------
diff --git a/diagnostic/src/main/java/org/apache/karaf/diagnostic/core/internal/LogDumpProvider.java b/diagnostic/src/main/java/org/apache/karaf/diagnostic/core/internal/LogDumpProvider.java
new file mode 100644
index 0000000..64b45f1
--- /dev/null
+++ b/diagnostic/src/main/java/org/apache/karaf/diagnostic/core/internal/LogDumpProvider.java
@@ -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.karaf.diagnostic.core.internal;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Dictionary;
+import java.util.Enumeration;
+
+import org.apache.karaf.diagnostic.core.DumpDestination;
+import org.apache.karaf.diagnostic.core.DumpProvider;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.cm.Configuration;
+import org.osgi.service.cm.ConfigurationAdmin;
+
+/**
+ * Dump provider which copies log files from data/log directory to
+ * destination.
+ */
+public class LogDumpProvider implements DumpProvider {
+
+    private final BundleContext bundleContext;
+
+    public LogDumpProvider(BundleContext bundleContext) {
+        this.bundleContext = bundleContext;
+    }
+
+    /**
+     * Attach log entries from directory.
+     */
+    public void createDump(DumpDestination destination) throws Exception {
+        // get the ConfigAdmin service
+        ServiceReference ref = bundleContext.getServiceReference(ConfigurationAdmin.class.getName());
+        if (ref == null) {
+            return;
+        }
+
+        // get the PAX Logging configuration
+        ConfigurationAdmin configurationAdmin = (ConfigurationAdmin) bundleContext.getService(ref);
+        try {
+            Configuration configuration = configurationAdmin.getConfiguration("org.ops4j.pax.logging");
+
+            // get the ".file" Pax Logging properties
+            Dictionary dictionary = configuration.getProperties();
+            for (Enumeration e = dictionary.keys(); e.hasMoreElements(); ) {
+                String property = (String) e.nextElement();
+                if (property.endsWith(".file")) {
+                    // it's a file appender, get the file location
+                    String location = (String) dictionary.get(property);
+                    File file = new File(location);
+                    if (file.exists()) {
+                        FileInputStream inputStream = new FileInputStream(file);
+                        OutputStream outputStream = destination.add("log/" + file.getName());
+                        copy(inputStream, outputStream);
+                    }
+                }
+            }
+        } catch (Exception e) {
+            throw e;
+        } finally {
+            bundleContext.ungetService(ref);
+        }
+    }
+
+    /**
+     * Rewrites data from input stream to output stream. This code is very common
+     * but we would avoid additional dependencies in diagnostic stuff.
+     *
+     * @param inputStream  Source stream.
+     * @param outputStream Destination stream.
+     * @throws IOException When IO operation fails.
+     */
+    private void copy(InputStream inputStream, OutputStream outputStream) throws IOException {
+        byte[] buffer = new byte[4096];
+        int n = 0;
+        while (-1 != (n = inputStream.read(buffer))) {
+            outputStream.write(buffer, 0, n);
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/886863a2/diagnostic/src/main/java/org/apache/karaf/diagnostic/core/internal/MemoryDumpProvider.java
----------------------------------------------------------------------
diff --git a/diagnostic/src/main/java/org/apache/karaf/diagnostic/core/internal/MemoryDumpProvider.java b/diagnostic/src/main/java/org/apache/karaf/diagnostic/core/internal/MemoryDumpProvider.java
new file mode 100644
index 0000000..ff23f9d
--- /dev/null
+++ b/diagnostic/src/main/java/org/apache/karaf/diagnostic/core/internal/MemoryDumpProvider.java
@@ -0,0 +1,54 @@
+/*
+ * 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.karaf.diagnostic.core.internal;
+
+import org.apache.karaf.diagnostic.core.common.TextDumpProvider;
+
+import java.io.OutputStreamWriter;
+import java.lang.management.ManagementFactory;
+import java.lang.management.MemoryMXBean;
+
+/**
+ * Provider which dump the memory information in the memory.txt file.
+ */
+public class MemoryDumpProvider extends TextDumpProvider {
+
+    public MemoryDumpProvider() {
+        super("memory.txt");
+    }
+
+    @Override
+    protected void writeDump(OutputStreamWriter outputStream) throws Exception {
+        MemoryMXBean memoryMXBean = ManagementFactory.getMemoryMXBean();
+
+        outputStream.write("Number of objects waiting finalization: " + memoryMXBean.getObjectPendingFinalizationCount() + "\n\n");
+
+        outputStream.write("Heap:\n");
+        outputStream.write("\tInit:      " + memoryMXBean.getHeapMemoryUsage().getInit() + "\n");
+        outputStream.write("\tUser:      " + memoryMXBean.getHeapMemoryUsage().getUsed() + "\n");
+        outputStream.write("\tCommitted: " + memoryMXBean.getHeapMemoryUsage().getCommitted() + "\n");
+        outputStream.write("\tMax:       " + memoryMXBean.getHeapMemoryUsage().getMax() + "\n");
+
+        outputStream.write("Non-Heap: \n");
+        outputStream.write("\tInit:      " + memoryMXBean.getNonHeapMemoryUsage().getInit() + "\n");
+        outputStream.write("\tUser:      " + memoryMXBean.getNonHeapMemoryUsage().getUsed() + "\n");
+        outputStream.write("\tCommitted: " + memoryMXBean.getNonHeapMemoryUsage().getCommitted() + "\n");
+        outputStream.write("\tMax:       " + memoryMXBean.getNonHeapMemoryUsage().getMax() + "\n");
+
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/886863a2/diagnostic/src/main/java/org/apache/karaf/diagnostic/core/internal/ThreadDumpProvider.java
----------------------------------------------------------------------
diff --git a/diagnostic/src/main/java/org/apache/karaf/diagnostic/core/internal/ThreadDumpProvider.java b/diagnostic/src/main/java/org/apache/karaf/diagnostic/core/internal/ThreadDumpProvider.java
new file mode 100644
index 0000000..31edad6
--- /dev/null
+++ b/diagnostic/src/main/java/org/apache/karaf/diagnostic/core/internal/ThreadDumpProvider.java
@@ -0,0 +1,118 @@
+/*
+ * 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.karaf.diagnostic.core.internal;
+
+import java.io.OutputStreamWriter;
+import java.lang.management.LockInfo;
+import java.lang.management.ManagementFactory;
+import java.lang.management.MonitorInfo;
+import java.lang.management.ThreadInfo;
+import java.lang.management.ThreadMXBean;
+
+import org.apache.karaf.diagnostic.core.common.TextDumpProvider;
+
+/**
+ * Provider which dumps thread info to file named threads.txt.
+ */
+public class ThreadDumpProvider extends TextDumpProvider {
+
+    /**
+     * Creates new dump entry which contains information about threads.
+     */
+    public ThreadDumpProvider() {
+        super("threads.txt");
+    }
+
+    @Override
+    protected void writeDump(OutputStreamWriter outputStream) throws Exception {
+        ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
+
+        outputStream.write("Number of threads: " + threadMXBean.getThreadCount() + "\n");
+
+        for (ThreadInfo threadInfo : threadMXBean.getThreadInfo(threadMXBean.getAllThreadIds(), Integer.MAX_VALUE)) {
+            outputStream.write(getDumpThreadString(threadInfo) + "\n\n");
+        }
+
+    }
+
+    protected String getDumpThreadString(ThreadInfo threadInfo) {
+        StringBuilder sb = new StringBuilder("\"" + threadInfo.getThreadName() + "\"" + " Id=" + threadInfo.getThreadId() + " "
+                                             + threadInfo.getThreadState());
+        if (threadInfo.getLockName() != null) {
+            sb.append(" on " + threadInfo.getLockName());
+        }
+        if (threadInfo.getLockOwnerName() != null) {
+            sb.append(" owned by \"" + threadInfo.getLockOwnerName() + "\" Id=" + threadInfo.getLockOwnerId());
+        }
+        if (threadInfo.isSuspended()) {
+            sb.append(" (suspended)");
+        }
+        if (threadInfo.isInNative()) {
+            sb.append(" (in native)");
+        }
+        sb.append('\n');
+        int i = 0;
+        StackTraceElement[] stackTrace = threadInfo.getStackTrace();
+        for (; i < stackTrace.length; i++) {
+            StackTraceElement ste = stackTrace[i];
+            sb.append("\tat " + ste.toString());
+            sb.append('\n');
+            if (i == 0 && threadInfo.getLockInfo() != null) {
+                Thread.State ts = threadInfo.getThreadState();
+                switch (ts) {
+                case BLOCKED:
+                    sb.append("\t-  blocked on " + threadInfo.getLockInfo());
+                    sb.append('\n');
+                    break;
+                case WAITING:
+                    sb.append("\t-  waiting on " + threadInfo.getLockInfo());
+                    sb.append('\n');
+                    break;
+                case TIMED_WAITING:
+                    sb.append("\t-  waiting on " + threadInfo.getLockInfo());
+                    sb.append('\n');
+                    break;
+                default:
+                }
+            }
+
+            for (MonitorInfo mi : threadInfo.getLockedMonitors()) {
+                if (mi.getLockedStackDepth() == i) {
+                    sb.append("\t-  locked " + mi);
+                    sb.append('\n');
+                }
+            }
+        }
+        if (i < stackTrace.length) {
+            sb.append("\t...");
+            sb.append('\n');
+        }
+
+        LockInfo[] locks = threadInfo.getLockedSynchronizers();
+        if (locks.length > 0) {
+            sb.append("\n\tNumber of locked synchronizers = " + locks.length);
+            sb.append('\n');
+            for (LockInfo li : locks) {
+                sb.append("\t- " + li);
+                sb.append('\n');
+            }
+        }
+        sb.append('\n');
+        return sb.toString();
+    }
+
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/886863a2/diagnostic/src/main/java/org/apache/karaf/diagnostic/core/internal/osgi/Activator.java
----------------------------------------------------------------------
diff --git a/diagnostic/src/main/java/org/apache/karaf/diagnostic/core/internal/osgi/Activator.java b/diagnostic/src/main/java/org/apache/karaf/diagnostic/core/internal/osgi/Activator.java
new file mode 100644
index 0000000..7a01daf
--- /dev/null
+++ b/diagnostic/src/main/java/org/apache/karaf/diagnostic/core/internal/osgi/Activator.java
@@ -0,0 +1,131 @@
+/*
+ * 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.karaf.diagnostic.core.internal.osgi;
+
+import java.util.ArrayList;
+import java.util.Hashtable;
+import java.util.List;
+
+import org.apache.karaf.diagnostic.core.DumpProvider;
+import org.apache.karaf.diagnostic.core.internal.BundleDumpProvider;
+import org.apache.karaf.diagnostic.core.internal.DiagnosticDumpMBeanImpl;
+import org.apache.karaf.diagnostic.core.internal.EnvironmentDumpProvider;
+import org.apache.karaf.diagnostic.core.internal.FeaturesDumpProvider;
+import org.apache.karaf.diagnostic.core.internal.HeapDumpProvider;
+import org.apache.karaf.diagnostic.core.internal.LogDumpProvider;
+import org.apache.karaf.diagnostic.core.internal.MemoryDumpProvider;
+import org.apache.karaf.diagnostic.core.internal.ThreadDumpProvider;
+import org.apache.karaf.features.FeaturesService;
+import org.apache.karaf.util.tracker.SingleServiceTracker;
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.ServiceRegistration;
+import org.osgi.util.tracker.ServiceTracker;
+import org.osgi.util.tracker.ServiceTrackerCustomizer;
+
+public class Activator implements BundleActivator {
+
+    private List<ServiceRegistration<DumpProvider>> registrations;
+    private ServiceRegistration<DumpProvider> featuresProviderRegistration;
+    private ServiceRegistration mbeanRegistration;
+    private SingleServiceTracker<FeaturesService> featuresServiceTracker;
+    private ServiceTracker<DumpProvider, DumpProvider> providersTracker;
+
+    @Override
+    public void start(final BundleContext context) throws Exception {
+        registrations = new ArrayList<ServiceRegistration<DumpProvider>>();
+        registrations.add(context.registerService(DumpProvider.class, new BundleDumpProvider(context), null));
+        registrations.add(context.registerService(DumpProvider.class, new EnvironmentDumpProvider(context), null));
+        registrations.add(context.registerService(DumpProvider.class, new HeapDumpProvider(), null));
+        registrations.add(context.registerService(DumpProvider.class, new LogDumpProvider(context), null));
+        registrations.add(context.registerService(DumpProvider.class, new MemoryDumpProvider(), null));
+        registrations.add(context.registerService(DumpProvider.class, new ThreadDumpProvider(), null));
+
+        featuresServiceTracker = new SingleServiceTracker<FeaturesService>(context, FeaturesService.class, new SingleServiceTracker.SingleServiceListener() {
+            @Override
+            public void serviceFound() {
+                featuresProviderRegistration =
+                        context.registerService(
+                                DumpProvider.class,
+                                new FeaturesDumpProvider(featuresServiceTracker.getService()),
+                                null);
+            }
+            @Override
+            public void serviceLost() {
+            }
+            @Override
+            public void serviceReplaced() {
+                featuresProviderRegistration.unregister();
+            }
+        });
+
+        final DiagnosticDumpMBeanImpl diagnostic = new DiagnosticDumpMBeanImpl();
+        providersTracker = new ServiceTracker<DumpProvider, DumpProvider>(
+                context, DumpProvider.class, new ServiceTrackerCustomizer<DumpProvider, DumpProvider>() {
+            @Override
+            public DumpProvider addingService(ServiceReference<DumpProvider> reference) {
+                DumpProvider service = context.getService(reference);
+                diagnostic.registerProvider(service);
+                return service;
+            }
+            @Override
+            public void modifiedService(ServiceReference<DumpProvider> reference, DumpProvider service) {
+            }
+            @Override
+            public void removedService(ServiceReference<DumpProvider> reference, DumpProvider service) {
+                diagnostic.unregisterProvider(service);
+                context.ungetService(reference);
+            }
+        });
+        providersTracker.open();
+
+        Hashtable<String, Object> props = new Hashtable<String, Object>();
+        props.put("jmx.objectname", "org.apache.karaf:type=diagnostic,name=" + System.getProperty("karaf.name"));
+        mbeanRegistration = context.registerService(
+                getInterfaceNames(diagnostic),
+                diagnostic,
+                props
+        );
+    }
+
+    @Override
+    public void stop(BundleContext context) throws Exception {
+        mbeanRegistration.unregister();
+        featuresServiceTracker.close();
+        providersTracker.close();
+        for (ServiceRegistration<DumpProvider> reg : registrations) {
+            reg.unregister();
+        }
+    }
+
+    private String[] getInterfaceNames(Object object) {
+        List<String> names = new ArrayList<String>();
+        for (Class cl = object.getClass(); cl != Object.class; cl = cl.getSuperclass()) {
+            addSuperInterfaces(names, cl);
+        }
+        return names.toArray(new String[names.size()]);
+    }
+
+    private void addSuperInterfaces(List<String> names, Class clazz) {
+        for (Class cl : clazz.getInterfaces()) {
+            names.add(cl.getName());
+            addSuperInterfaces(names, cl);
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/886863a2/diagnostic/src/main/resources/OSGI-INF/bundle.info
----------------------------------------------------------------------
diff --git a/diagnostic/src/main/resources/OSGI-INF/bundle.info b/diagnostic/src/main/resources/OSGI-INF/bundle.info
new file mode 100644
index 0000000..15bc3cb
--- /dev/null
+++ b/diagnostic/src/main/resources/OSGI-INF/bundle.info
@@ -0,0 +1,18 @@
+h1. Synopsis
+
+${project.name}
+
+${project.description}
+
+Maven URL:
+[mvn:${project.groupId}/${project.artifactId}/${project.version}]
+
+h1. Description
+
+The diagnostic core bundle is the diagnostic core implementation.
+
+It's used by the diagnostic commands bundle and is responsible of the dump generation (environment, features, logs, bundles, threads).
+
+h1. See also
+
+Diagnostic - section of the Karaf User Guide.


[19/59] [abbrv] [KARAF-2852] Merge bundle/command into bundle/core

Posted by gn...@apache.org.
http://git-wip-us.apache.org/repos/asf/karaf/blob/d0180939/bundle/core/src/main/java/org/apache/karaf/bundle/command/BundlesCommandWithConfirmation.java
----------------------------------------------------------------------
diff --git a/bundle/core/src/main/java/org/apache/karaf/bundle/command/BundlesCommandWithConfirmation.java b/bundle/core/src/main/java/org/apache/karaf/bundle/command/BundlesCommandWithConfirmation.java
new file mode 100644
index 0000000..271fc42
--- /dev/null
+++ b/bundle/core/src/main/java/org/apache/karaf/bundle/command/BundlesCommandWithConfirmation.java
@@ -0,0 +1,62 @@
+/*
+ * 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.karaf.bundle.command;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.karaf.shell.api.action.Option;
+import org.apache.karaf.shell.support.MultiException;
+import org.osgi.framework.Bundle;
+
+/**
+ * Command related to bundles requiring read-write access to the bundle (including system bundle).
+ */
+public abstract class BundlesCommandWithConfirmation extends BundlesCommand {
+
+    @Option(name = "--force", aliases = {"-f"}, description = "Forces the command to execute", required = false, multiValued = false)
+    boolean force;
+    
+    protected String errorMessage = "Unable to execute command on bundle ";
+    
+    public BundlesCommandWithConfirmation() {
+        super(false);
+    }
+
+    protected Object doExecute() throws Exception {
+        doExecute(force);
+        return null;
+    }
+
+    protected void doExecute(List<Bundle> bundles) throws Exception {
+        if (bundles.isEmpty()) {
+            System.err.println("No bundles specified.");
+            return;
+        }
+        List<Exception> exceptions = new ArrayList<Exception>();
+        for (Bundle bundle : bundles) {
+            try {
+                executeOnBundle(bundle);
+            } catch (Exception e) {
+                exceptions.add(new Exception(errorMessage + bundle.getBundleId() + ": " + e.getMessage(), e));
+            }
+        }
+        MultiException.throwIf("Error executing command on bundles", exceptions);
+    }
+    
+    protected abstract void executeOnBundle(Bundle bundle) throws Exception;
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d0180939/bundle/core/src/main/java/org/apache/karaf/bundle/command/Capabilities.java
----------------------------------------------------------------------
diff --git a/bundle/core/src/main/java/org/apache/karaf/bundle/command/Capabilities.java b/bundle/core/src/main/java/org/apache/karaf/bundle/command/Capabilities.java
new file mode 100644
index 0000000..de83a1d
--- /dev/null
+++ b/bundle/core/src/main/java/org/apache/karaf/bundle/command/Capabilities.java
@@ -0,0 +1,239 @@
+/*
+ * 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.karaf.bundle.command;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Pattern;
+
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.Option;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.apache.karaf.shell.support.ShellUtil;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.wiring.BundleCapability;
+import org.osgi.framework.wiring.BundleWire;
+import org.osgi.framework.wiring.BundleWiring;
+
+@Command(scope = "bundle", name = "capabilities", description = "Displays OSGi capabilities of a given bundles.")
+@Service
+public class Capabilities extends BundlesCommand {
+    public static final String NONSTANDARD_SERVICE_NAMESPACE = "service";
+
+    private static final String EMPTY_MESSAGE = "[EMPTY]";
+    private static final String UNUSED_MESSAGE = "[UNUSED]";
+
+    @Option(name = "--namespace")
+    String namespace = "*";
+
+    public Capabilities() {
+        super(true);
+    }
+    
+    @Override
+    protected void doExecute(List<Bundle> bundles) throws Exception {
+        boolean separatorNeeded = false;
+        Pattern ns = Pattern.compile(namespace.replaceAll("\\.", "\\\\.").replaceAll("\\*", ".*"));
+        for (Bundle b : bundles)
+        {
+            if (separatorNeeded)
+            {
+                System.out.println("");
+            }
+
+            // Print out any matching generic capabilities.
+            BundleWiring wiring = b.adapt(BundleWiring.class);
+            if (wiring != null)
+            {
+                String title = b + " provides:";
+                System.out.println(title);
+                System.out.println(ShellUtil.getUnderlineString(title));
+
+                // Print generic capabilities for matching namespaces.
+                boolean matches = printMatchingCapabilities(wiring, ns);
+
+                // Handle service capabilities separately, since they aren't part
+                // of the generic model in OSGi.
+                if (matchNamespace(ns, NONSTANDARD_SERVICE_NAMESPACE))
+                {
+                    matches |= printServiceCapabilities(b);
+                }
+
+                // If there were no capabilities for the specified namespace,
+                // then say so.
+                if (!matches)
+                {
+                    System.out.println(namespace + " " + EMPTY_MESSAGE);
+                }
+            }
+            else
+            {
+                System.out.println("Bundle " + b.getBundleId() + " is not resolved.");
+            }
+            separatorNeeded = true;
+        }
+    }
+
+    private static boolean printMatchingCapabilities(BundleWiring wiring, Pattern namespace)
+    {
+        List<BundleWire> wires = wiring.getProvidedWires(null);
+        Map<BundleCapability, List<BundleWire>> aggregateCaps =
+            aggregateCapabilities(namespace, wires);
+        List<BundleCapability> allCaps = wiring.getCapabilities(null);
+        boolean matches = false;
+        for (BundleCapability cap : allCaps)
+        {
+            if (matchNamespace(namespace, cap.getNamespace()))
+            {
+                matches = true;
+                List<BundleWire> dependents = aggregateCaps.get(cap);
+                Object keyAttr =
+                    cap.getAttributes().get(cap.getNamespace());
+                if (dependents != null)
+                {
+                    String msg;
+                    if (keyAttr != null)
+                    {
+                        msg = cap.getNamespace()
+                            + "; "
+                            + keyAttr
+                            + " "
+                            + getVersionFromCapability(cap);
+                    }
+                    else
+                    {
+                        msg = cap.toString();
+                    }
+                    msg = msg + " required by:";
+                    System.out.println(msg);
+                    for (BundleWire wire : dependents)
+                    {
+                        System.out.println("   " + wire.getRequirerWiring().getBundle());
+                    }
+                }
+                else if (keyAttr != null)
+                {
+                    System.out.println(cap.getNamespace()
+                        + "; "
+                        + cap.getAttributes().get(cap.getNamespace())
+                        + " "
+                        + getVersionFromCapability(cap)
+                        + " "
+                        + UNUSED_MESSAGE);
+                }
+                else
+                {
+                    System.out.println(cap + " " + UNUSED_MESSAGE);
+                }
+            }
+        }
+        return matches;
+    }
+
+    private static Map<BundleCapability, List<BundleWire>> aggregateCapabilities(
+        Pattern namespace, List<BundleWire> wires)
+    {
+        // Aggregate matching capabilities.
+        Map<BundleCapability, List<BundleWire>> map =
+            new HashMap<BundleCapability, List<BundleWire>>();
+        for (BundleWire wire : wires)
+        {
+            if (matchNamespace(namespace, wire.getCapability().getNamespace()))
+            {
+                List<BundleWire> dependents = map.get(wire.getCapability());
+                if (dependents == null)
+                {
+                    dependents = new ArrayList<BundleWire>();
+                    map.put(wire.getCapability(), dependents);
+                }
+                dependents.add(wire);
+            }
+        }
+        return map;
+    }
+
+    static boolean printServiceCapabilities(Bundle b)
+    {
+        boolean matches = false;
+
+        try
+        {
+            ServiceReference<?>[] refs = b.getRegisteredServices();
+
+            if ((refs != null) && (refs.length > 0))
+            {
+                matches = true;
+                // Print properties for each service.
+                for (ServiceReference<?> ref : refs)
+                {
+                    // Print object class with "namespace".
+                    System.out.println(
+                        NONSTANDARD_SERVICE_NAMESPACE
+                        + "; "
+                        + ShellUtil.getValueString(ref.getProperty("objectClass"))
+                        + " with properties:");
+                    // Print service properties.
+                    String[] keys = ref.getPropertyKeys();
+                    for (String key : keys)
+                    {
+                        if (!key.equalsIgnoreCase(Constants.OBJECTCLASS))
+                        {
+                            Object v = ref.getProperty(key);
+                            System.out.println("   "
+                                + key + " = " + ShellUtil.getValueString(v));
+                        }
+                    }
+                    Bundle[] users = ref.getUsingBundles();
+                    if ((users != null) && (users.length > 0))
+                    {
+                        System.out.println("   Used by:");
+                        for (Bundle user : users)
+                        {
+                            System.out.println("      " + user);
+                        }
+                    }
+                }
+            }
+        }
+        catch (Exception ex)
+        {
+            System.err.println(ex.toString());
+        }
+
+        return matches;
+    }
+
+    private static String getVersionFromCapability(BundleCapability c)
+    {
+        Object o = c.getAttributes().get(Constants.VERSION_ATTRIBUTE);
+        if (o == null)
+        {
+            o = c.getAttributes().get(Constants.BUNDLE_VERSION_ATTRIBUTE);
+        }
+        return (o == null) ? "" : o.toString();
+    }
+
+    private static boolean matchNamespace(Pattern namespace, String actual)
+    {
+        return namespace.matcher(actual).matches();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d0180939/bundle/core/src/main/java/org/apache/karaf/bundle/command/Classes.java
----------------------------------------------------------------------
diff --git a/bundle/core/src/main/java/org/apache/karaf/bundle/command/Classes.java b/bundle/core/src/main/java/org/apache/karaf/bundle/command/Classes.java
new file mode 100644
index 0000000..b0f80ff
--- /dev/null
+++ b/bundle/core/src/main/java/org/apache/karaf/bundle/command/Classes.java
@@ -0,0 +1,63 @@
+/*
+ * 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.karaf.bundle.command;
+
+import java.util.Collection;
+import java.util.List;
+
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.Option;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.wiring.BundleWiring;
+
+@Command(scope = "bundle", name = "classes", description = "Displays a list of classes contained in the bundle")
+@Service
+public class Classes extends BundlesCommand {
+
+    @Option(name = "-a", aliases={"--display-all-files"}, description="List all classes and files in the bundle", required = false, multiValued = false)
+    boolean displayAllFiles;
+
+    public Classes() {
+        super(true);
+    }
+
+    protected void doExecute(List<Bundle> bundles) throws Exception {
+        for (Bundle bundle : bundles) {
+            printResources(bundle);
+        }
+    }
+
+    protected void printResources(Bundle bundle) {
+        BundleWiring wiring = bundle.adapt(BundleWiring.class);
+        if (wiring != null){
+            Collection<String> resources;
+            if (displayAllFiles){
+                resources = wiring.listResources("/", null, BundleWiring.LISTRESOURCES_RECURSE);
+            }else{
+                resources = wiring.listResources("/", "*class", BundleWiring.LISTRESOURCES_RECURSE);
+            }
+            for (String resource:resources){
+                System.out.println(resource);
+            }
+        } else {
+            System.out.println("Bundle " + bundle.getBundleId() + " is not resolved.");
+        }
+    }
+
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d0180939/bundle/core/src/main/java/org/apache/karaf/bundle/command/Diag.java
----------------------------------------------------------------------
diff --git a/bundle/core/src/main/java/org/apache/karaf/bundle/command/Diag.java b/bundle/core/src/main/java/org/apache/karaf/bundle/command/Diag.java
new file mode 100644
index 0000000..1e8e11b
--- /dev/null
+++ b/bundle/core/src/main/java/org/apache/karaf/bundle/command/Diag.java
@@ -0,0 +1,51 @@
+/*
+ * 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.karaf.bundle.command;
+
+import java.util.List;
+
+import org.apache.karaf.bundle.core.BundleInfo;
+import org.apache.karaf.bundle.core.BundleState;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.apache.karaf.shell.support.ShellUtil;
+import org.osgi.framework.Bundle;
+
+@Command(scope = "bundle", name = "diag", description = "Displays diagnostic information why a bundle is not Active")
+@Service
+public class Diag extends BundlesCommand {
+
+    public Diag() {
+        super(true);
+    }
+
+    protected void doExecute(List<Bundle> bundles) throws Exception {
+        for (Bundle bundle : bundles) {
+            BundleInfo info = bundleService.getInfo(bundle);
+            if (info.getState() == BundleState.Failure || info.getState() == BundleState.Waiting
+                || info.getState() == BundleState.GracePeriod || info.getState() == BundleState.Installed) {
+                String title = ShellUtil.getBundleName(bundle);
+                System.out.println(title);
+                System.out.println(ShellUtil.getUnderlineString(title));
+                System.out.println("Status: " + info.getState().toString());
+                System.out.println(this.bundleService.getDiag(bundle));
+                System.out.println();
+            }
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d0180939/bundle/core/src/main/java/org/apache/karaf/bundle/command/DynamicImport.java
----------------------------------------------------------------------
diff --git a/bundle/core/src/main/java/org/apache/karaf/bundle/command/DynamicImport.java b/bundle/core/src/main/java/org/apache/karaf/bundle/command/DynamicImport.java
new file mode 100644
index 0000000..74fc20a
--- /dev/null
+++ b/bundle/core/src/main/java/org/apache/karaf/bundle/command/DynamicImport.java
@@ -0,0 +1,46 @@
+/*
+ * 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.karaf.bundle.command;
+
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.osgi.framework.Bundle;
+
+/**
+ * Command for enabling/disabling debug logging on a bundle and calculating the difference in
+ * wired imports.
+ */
+@Command(scope = "bundle", name = "dynamic-import", description = "Enables/disables dynamic-import for a given bundle.")
+@Service
+public class DynamicImport extends BundleCommand {
+
+    public DynamicImport() {
+        super(true);
+    }
+
+    @Override
+    protected void doExecute(Bundle bundle) throws Exception {
+        if (bundleService.isDynamicImport(bundle)) {
+            System.out.printf("Disabling dynamic imports on bundle %s%n", bundle);
+            bundleService.disableDynamicImports(bundle);
+        } else {
+            System.out.printf("Enabling dynamic imports on bundle %s%n", bundle);
+            bundleService.enableDynamicImports(bundle);
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d0180939/bundle/core/src/main/java/org/apache/karaf/bundle/command/FindClass.java
----------------------------------------------------------------------
diff --git a/bundle/core/src/main/java/org/apache/karaf/bundle/command/FindClass.java b/bundle/core/src/main/java/org/apache/karaf/bundle/command/FindClass.java
new file mode 100644
index 0000000..4a9fc75
--- /dev/null
+++ b/bundle/core/src/main/java/org/apache/karaf/bundle/command/FindClass.java
@@ -0,0 +1,68 @@
+package org.apache.karaf.bundle.command;
+
+/*
+ * 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.
+ */
+
+import java.util.Collection;
+
+import org.apache.karaf.shell.api.action.Action;
+import org.apache.karaf.shell.api.action.Argument;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.lifecycle.Reference;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.apache.karaf.shell.support.ShellUtil;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.wiring.BundleWiring;
+
+@Command(scope = "bundle", name = "find-class", description = "Locates a specified class in any deployed bundle")
+@Service
+public class FindClass implements Action {
+
+    @Argument(index = 0, name = "className", description = "Class name or partial class name to be found", required = true, multiValued = false)
+    String className;
+
+    @Reference
+    BundleContext bundleContext;
+
+    @Override
+    public Object execute() throws Exception {
+        findResource();
+        return null;
+    }
+
+    protected void findResource() {
+        Bundle[] bundles = bundleContext.getBundles();
+        String filter = "*" + className + "*";
+        for (Bundle bundle:bundles){
+            BundleWiring wiring = bundle.adapt(BundleWiring.class);
+            if (wiring != null){
+                Collection<String> resources = wiring.listResources("/", filter, BundleWiring.LISTRESOURCES_RECURSE);
+                if (resources.size() > 0){
+                    String title = ShellUtil.getBundleName(bundle);
+                    System.out.println("\n" + title);
+                }
+                for (String resource:resources){
+                    System.out.println(resource);
+                }
+            } else {
+                System.out.println("Bundle " + bundle.getBundleId() + " is not resolved.");
+            }
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d0180939/bundle/core/src/main/java/org/apache/karaf/bundle/command/Headers.java
----------------------------------------------------------------------
diff --git a/bundle/core/src/main/java/org/apache/karaf/bundle/command/Headers.java b/bundle/core/src/main/java/org/apache/karaf/bundle/command/Headers.java
new file mode 100644
index 0000000..16083ff
--- /dev/null
+++ b/bundle/core/src/main/java/org/apache/karaf/bundle/command/Headers.java
@@ -0,0 +1,333 @@
+/*
+ * 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.karaf.bundle.command;
+
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.Dictionary;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.felix.utils.manifest.Attribute;
+import org.apache.felix.utils.manifest.Clause;
+import org.apache.felix.utils.manifest.Directive;
+import org.apache.felix.utils.manifest.Parser;
+import org.apache.felix.utils.version.VersionRange;
+import org.apache.felix.utils.version.VersionTable;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.Option;
+import org.apache.karaf.shell.api.action.lifecycle.Reference;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.apache.karaf.shell.api.console.Terminal;
+import org.apache.karaf.shell.support.ShellUtil;
+import org.fusesource.jansi.Ansi;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.Constants;
+import org.osgi.framework.wiring.BundleCapability;
+import org.osgi.framework.wiring.BundleRevision;
+import org.osgi.framework.wiring.BundleWiring;
+
+@Command(scope = "bundle", name = "headers", description = "Displays OSGi headers of a given bundles.")
+@Service
+public class Headers extends BundlesCommand {
+
+    protected final static String BUNDLE_PREFIX = "Bundle-";
+    protected final static String PACKAGE_SUFFFIX = "-Package";
+    protected final static String SERVICE_SUFFIX = "-Service";
+    protected final static String CAPABILITY_SUFFIX = "-Capability";
+    protected final static String IMPORT_PACKAGES_ATTRIB = "Import-Package";
+    protected final static String REQUIRE_BUNDLE_ATTRIB = "Require-Bundle";
+
+    @Option(name = "--indent", description = "Indentation method")
+    int indent = -1;
+
+    @Reference
+    Terminal terminal;
+    
+    public Headers() {
+        super(true);
+    }
+
+    protected void doExecute(List<Bundle> bundles) throws Exception {
+        for (Bundle bundle : bundles) {
+            printHeaders(bundle);
+        }
+    }
+
+    protected void printHeaders(Bundle bundle) throws Exception {
+        String title = ShellUtil.getBundleName(bundle);
+        System.out.println("\n" + title);
+        System.out.println(ShellUtil.getUnderlineString(title));
+        if (indent == 0) {
+            Dictionary<String, String> dict = bundle.getHeaders();
+            Enumeration<String> keys = dict.keys();
+            while (keys.hasMoreElements()) {
+                Object k = keys.nextElement();
+                Object v = dict.get(k);
+                System.out.println(k + " = " + ShellUtil.getValueString(v));
+            }
+        } else {
+            System.out.println(generateFormattedOutput(bundle));
+        }
+    }
+
+    protected String generateFormattedOutput(Bundle bundle) {
+        StringBuilder output = new StringBuilder();
+        Map<String, Object> otherAttribs = new HashMap<String, Object>();
+        Map<String, Object> bundleAttribs = new HashMap<String, Object>();
+        Map<String, Object> serviceAttribs = new HashMap<String, Object>();
+        Map<String, Object> packagesAttribs = new HashMap<String, Object>();
+        Dictionary<String, String> dict = bundle.getHeaders();
+        Enumeration<String> keys = dict.keys();
+
+        // do an initial loop and separate the attributes in different groups
+        while (keys.hasMoreElements()) {
+            String k = (String) keys.nextElement();
+            Object v = dict.get(k);
+            if (k.startsWith(BUNDLE_PREFIX)) {
+                // starts with Bundle-xxx
+                bundleAttribs.put(k, v);
+            } else if (k.endsWith(SERVICE_SUFFIX) || k.endsWith(CAPABILITY_SUFFIX)) {
+                // ends with xxx-Service
+                serviceAttribs.put(k, v);
+            } else if (k.endsWith(PACKAGE_SUFFFIX)) {
+                // ends with xxx-Package
+                packagesAttribs.put(k, v);
+            } else if (k.endsWith(REQUIRE_BUNDLE_ATTRIB)) {
+                // require bundle statement
+                packagesAttribs.put(k, v);
+            } else {
+                // the remaining attribs
+                otherAttribs.put(k, v);
+            }
+        }
+
+        // we will display the formatted result like this:
+        // Bundle-Name (ID)
+        // -----------------------
+        // all other attributes
+        //
+        // all Bundle attributes
+        //
+        // all Service attributes
+        //
+        // all Package attributes
+        Iterator<Map.Entry<String, Object>> it = otherAttribs.entrySet().iterator();
+        while (it.hasNext()) {
+            Map.Entry<String, Object> e = it.next();
+            output.append(String.format("%s = %s\n", e.getKey(), ShellUtil.getValueString(e.getValue())));
+        }
+        if (otherAttribs.size() > 0) {
+            output.append('\n');
+        }
+
+        it = bundleAttribs.entrySet().iterator();
+        while (it.hasNext()) {
+            Map.Entry<String, Object> e = it.next();
+            output.append(String.format("%s = %s\n", e.getKey(), ShellUtil.getValueString(e.getValue())));
+        }
+        if (bundleAttribs.size() > 0) {
+            output.append('\n');
+        }
+
+        it = serviceAttribs.entrySet().iterator();
+        while (it.hasNext()) {
+            Map.Entry<String, Object> e = it.next();
+            output.append(e.getKey());
+            output.append(" = \n");
+            formatHeader(ShellUtil.getValueString(e.getValue()), null, output, indent);
+            output.append("\n");
+        }
+        if (serviceAttribs.size() > 0) {
+            output.append('\n');
+        }
+
+        Map<String, ClauseFormatter> formatters = new HashMap<String, ClauseFormatter>();
+        formatters.put(REQUIRE_BUNDLE_ATTRIB, new ClauseFormatter() {
+            public void pre(Clause clause, StringBuilder output) {
+                boolean isSatisfied = checkBundle(clause.getName(), clause.getAttribute("bundle-version"));
+                Ansi.ansi(output).fg(isSatisfied ? Ansi.Color.DEFAULT : Ansi.Color.RED).a("");
+            }
+            public void post(Clause clause, StringBuilder output) {
+                Ansi.ansi(output).reset().a("");
+            }
+        });
+        formatters.put(IMPORT_PACKAGES_ATTRIB, new ClauseFormatter() {
+            public void pre(Clause clause, StringBuilder output) {
+                boolean isSatisfied = checkPackage(clause.getName(), clause.getAttribute("version"));
+                boolean isOptional = "optional".equals(clause.getDirective("resolution"));
+                Ansi.ansi(output).fg(isSatisfied ? Ansi.Color.DEFAULT : Ansi.Color.RED)
+                                 .a(isSatisfied || isOptional ? Ansi.Attribute.INTENSITY_BOLD_OFF : Ansi.Attribute.INTENSITY_BOLD)
+                                 .a("");
+            }
+            public void post(Clause clause, StringBuilder output) {
+                Ansi.ansi(output).reset().a("");
+            }
+        });
+
+        it = packagesAttribs.entrySet().iterator();
+        while (it.hasNext()) {
+            Map.Entry<String, Object> e = it.next();
+            output.append(e.getKey());
+            output.append(" = \n");
+            formatHeader(ShellUtil.getValueString(e.getValue()), formatters.get(e.getKey()), output, indent);
+            output.append("\n");
+        }
+        if (packagesAttribs.size() > 0) {
+            output.append('\n');
+        }
+
+        return output.toString();
+    }
+
+    protected interface ClauseFormatter {
+        void pre(Clause clause, StringBuilder output);
+        void post(Clause clause, StringBuilder output);
+    }
+
+    protected void formatHeader(String header, ClauseFormatter formatter, StringBuilder builder, int indent) {
+        Clause[] clauses = Parser.parseHeader(header);
+        formatClauses(clauses, formatter, builder, indent);
+    }
+
+    protected void formatClauses(Clause[] clauses, ClauseFormatter formatter, StringBuilder builder, int indent) {
+        boolean first = true;
+        for (Clause clause : clauses) {
+            if (first) {
+                first = false;
+            } else {
+                builder.append(",\n");
+            }
+            formatClause(clause, formatter, builder, indent);
+        }
+    }
+
+    protected void formatClause(Clause clause, ClauseFormatter formatter, StringBuilder builder, int indent) {
+        builder.append("\t");
+        if (formatter != null) {
+            formatter.pre(clause, builder);
+        }
+        formatClause(clause, builder, indent);
+        if (formatter != null) {
+            formatter.post(clause, builder);
+        }
+    }
+
+    protected int getTermWidth() {
+        return terminal.getWidth();
+
+    }
+
+    protected void formatClause(Clause clause, StringBuilder builder, int indent) {
+        if (indent < 0) {
+            if (clause.toString().length() < getTermWidth() - 8) { // -8 for tabs
+                indent = 1;
+            } else {
+                indent = 3;
+            }
+        }
+        String name = clause.getName();
+        Directive[] directives = clause.getDirectives();
+        Attribute[] attributes = clause.getAttributes();
+        Arrays.sort(directives, new Comparator<Directive>() {
+            public int compare(Directive o1, Directive o2) {
+                return o1.getName().compareTo(o2.getName());
+            }
+        });
+        Arrays.sort(attributes, new Comparator<Attribute>() {
+            public int compare(Attribute o1, Attribute o2) {
+                return o1.getName().compareTo(o2.getName());
+            }
+        });
+        builder.append(name);
+        for (int i = 0; directives != null && i < directives.length; i++) {
+            builder.append(";");
+            if (indent > 1) {
+                builder.append("\n\t\t");
+            }
+            builder.append(directives[i].getName()).append(":=");
+            String v = directives[i].getValue();
+            if (v.contains(",")) {
+                if (indent > 2 && v.length() > 20) {
+                    v = v.replace(",", ",\n\t\t\t");
+                }
+                builder.append("\"").append(v).append("\"");
+            } else {
+                builder.append(v);
+            }
+        }
+        for (int i = 0; attributes != null && i < attributes.length; i++) {
+            builder.append(";");
+            if (indent > 1) {
+                builder.append("\n\t\t");
+            }
+            builder.append(attributes[i].getName()).append("=");
+            String v = attributes[i].getValue();
+            if (v.contains(",")) {
+                if (indent > 2 && v.length() > 20) {
+                    v = v.replace(",", ",\n\t\t\t");
+                }
+                builder.append("\"").append(v).append("\"");
+            } else {
+                builder.append(v);
+            }
+        }
+    }
+
+
+    private boolean checkBundle(String bundleName, String version) {
+        VersionRange vr = VersionRange.parseVersionRange(version);
+        Bundle[] bundles = bundleContext.getBundles();
+        for (int i = 0; (bundles != null) && (i < bundles.length); i++) {
+            String sym = bundles[i].getSymbolicName();
+            if ((sym != null) && sym.equals(bundleName)) {
+                if (vr.contains(bundles[i].getVersion())) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    private boolean checkPackage(String packageName, String version) {
+        VersionRange range = VersionRange.parseVersionRange(version);
+        Bundle[] bundles = bundleContext.getBundles();
+        for (int i = 0; (bundles != null) && (i < bundles.length); i++) {
+            BundleWiring wiring = bundles[i].adapt(BundleWiring.class);
+            List<BundleCapability> caps = wiring != null ? wiring.getCapabilities(BundleRevision.PACKAGE_NAMESPACE) : null;
+            if (caps != null) {
+                for (BundleCapability cap : caps) {
+                    String n = getAttribute(cap, BundleRevision.PACKAGE_NAMESPACE);
+                    String v = getAttribute(cap, Constants.VERSION_ATTRIBUTE);
+                    if (packageName.equals(n) && range.contains(VersionTable.getVersion(v))) {
+                        return true;
+                    }
+                }
+            }
+        }
+        return false;
+    }
+    
+    private String getAttribute(BundleCapability cap, String name)  {
+        Object obj = cap.getAttributes().get(name);
+        return obj != null ? obj.toString() : null;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d0180939/bundle/core/src/main/java/org/apache/karaf/bundle/command/Info.java
----------------------------------------------------------------------
diff --git a/bundle/core/src/main/java/org/apache/karaf/bundle/command/Info.java b/bundle/core/src/main/java/org/apache/karaf/bundle/command/Info.java
new file mode 100644
index 0000000..451ec87
--- /dev/null
+++ b/bundle/core/src/main/java/org/apache/karaf/bundle/command/Info.java
@@ -0,0 +1,79 @@
+/*
+ * 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.karaf.bundle.command;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.net.URL;
+import java.util.List;
+
+import org.apache.karaf.bundle.command.wikidoc.AnsiPrintingWikiVisitor;
+import org.apache.karaf.bundle.command.wikidoc.WikiParser;
+import org.apache.karaf.bundle.command.wikidoc.WikiVisitor;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.apache.karaf.shell.support.ShellUtil;
+import org.osgi.framework.Bundle;
+
+@Command(scope = "bundle", name = "info", description = "Displays detailed information of a given bundles.")
+@Service
+public class Info extends BundlesCommand {
+
+    public Info() {
+        super(true);
+    }
+
+    protected void doExecute(List<Bundle> bundles) throws Exception {
+        for (Bundle bundle : bundles) {
+          printInfo(bundle);
+        }
+    }
+
+    /**
+     * <p>
+     * Get the OSGI-INF/bundle.info entry from the bundle and display it.
+     * </p>
+     *
+     * @param bundle the bundle.
+     */
+    protected void printInfo(Bundle bundle) {
+        String title = ShellUtil.getBundleName(bundle);
+        System.out.println("\n" + title);
+        System.out.println(ShellUtil.getUnderlineString(title));
+        URL bundleInfo = bundle.getEntry("OSGI-INF/bundle.info");
+        if (bundleInfo != null) {
+        	BufferedReader reader = null;
+            try {
+                reader = new BufferedReader(new InputStreamReader(bundleInfo.openStream()));
+                WikiVisitor visitor = new AnsiPrintingWikiVisitor(System.out);
+                WikiParser parser = new WikiParser(visitor);
+                parser.parse(reader);
+            } catch (Exception e) {
+                // ignore
+            } finally {
+            	if (reader != null) {
+            		try {
+						reader.close();
+					} catch (IOException e) {
+					}
+            	}
+            }
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d0180939/bundle/core/src/main/java/org/apache/karaf/bundle/command/Install.java
----------------------------------------------------------------------
diff --git a/bundle/core/src/main/java/org/apache/karaf/bundle/command/Install.java b/bundle/core/src/main/java/org/apache/karaf/bundle/command/Install.java
new file mode 100644
index 0000000..11fba89
--- /dev/null
+++ b/bundle/core/src/main/java/org/apache/karaf/bundle/command/Install.java
@@ -0,0 +1,81 @@
+/*
+ * 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.karaf.bundle.command;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.karaf.shell.api.action.Action;
+import org.apache.karaf.shell.api.action.Argument;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.Option;
+import org.apache.karaf.shell.api.action.lifecycle.Reference;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.apache.karaf.shell.support.MultiException;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+
+@Command(scope = "bundle", name = "install", description = "Installs one or more bundles.")
+@Service
+public class Install implements Action {
+
+    @Argument(index = 0, name = "urls", description = "Bundle URLs separated by whitespaces", required = true, multiValued = true)
+    List<String> urls;
+
+    @Option(name = "-s", aliases={"--start"}, description="Starts the bundles after installation", required = false, multiValued = false)
+    boolean start;
+
+    @Reference
+    BundleContext bundleContext;
+
+    @Override
+    public Object execute() throws Exception {
+        List<Exception> exceptions = new ArrayList<Exception>();
+        List<Bundle> bundles = new ArrayList<Bundle>();
+        for (String url : urls) {
+            try {
+                bundles.add(bundleContext.installBundle(url, null));
+            } catch (Exception e) {
+                exceptions.add(new Exception("Unable to install bundle " + url, e));
+            }
+        }
+        if (start) {
+            for (Bundle bundle : bundles) {
+                try {
+                    bundle.start();
+                } catch (Exception e) {
+                    exceptions.add(new Exception("Unable to start bundle " + bundle.getLocation(), e));
+                }
+            }
+        }
+        if (bundles.size() == 1) {
+            System.out.println("Bundle ID: " + bundles.get(0).getBundleId());
+        } else {
+            StringBuffer sb = new StringBuffer("Bundle IDs: ");
+            for (Bundle bundle : bundles) {
+                if (sb.length() > 0) {
+                    sb.append(", ");
+                }
+                sb.append(bundle.getBundleId());
+            }
+            System.out.println(sb);
+        }
+        MultiException.throwIf("Error installing bundles", exceptions);
+        return null;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d0180939/bundle/core/src/main/java/org/apache/karaf/bundle/command/ListBundleServices.java
----------------------------------------------------------------------
diff --git a/bundle/core/src/main/java/org/apache/karaf/bundle/command/ListBundleServices.java b/bundle/core/src/main/java/org/apache/karaf/bundle/command/ListBundleServices.java
new file mode 100644
index 0000000..28f8264
--- /dev/null
+++ b/bundle/core/src/main/java/org/apache/karaf/bundle/command/ListBundleServices.java
@@ -0,0 +1,116 @@
+/*
+ * 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.karaf.bundle.command;
+
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.Option;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.apache.karaf.shell.support.ShellUtil;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceReference;
+
+@Command(scope = "bundle", name = "services", description = "Lists OSGi services per Bundle")
+@Service
+public class ListBundleServices extends BundlesCommand {
+
+    @Option(name = "-a", aliases = {}, description = "Shows all services. (By default Karaf commands are hidden)", required = false, multiValued = false)
+    boolean showAll;
+
+    @Option(name = "-u", aliases = {}, description = "Shows the services each bundle uses. (By default the provided services are shown)", required = false, multiValued = false)
+    boolean inUse;
+    
+    @Option(name = "-p", aliases = {}, description = "Shows the properties of the services", required = false, multiValued = false)
+    boolean showProperties = false;
+
+    Set<String> hidden = new HashSet<String>(Arrays.asList(new String[] {
+        "org.apache.felix.service.command.Function",
+        "org.apache.karaf.shell.console.Completer"
+    }));
+    
+    public ListBundleServices() {
+        super(true);
+    }
+    
+    @Override
+    protected void doExecute(List<Bundle> bundles) throws Exception {
+        for (Bundle bundle : bundles) {
+            ServiceReference<?>[] refs = (inUse) ? bundle.getServicesInUse() : bundle.getRegisteredServices();
+            printServices(bundle, refs, showProperties);
+        }
+    }
+    
+    private void printServices(Bundle bundle, ServiceReference<?>[] refs, boolean showProperties) {
+        boolean headerPrinted = false;
+        boolean needSeparator = false;
+        
+        if (refs == null) {
+            return;
+        }
+
+        for (ServiceReference<?> serviceRef : refs) {
+            String[] objectClass = (String[]) serviceRef.getProperty(Constants.OBJECTCLASS);
+
+            boolean print = showAll || !isCommandOrCompleter(objectClass);
+
+            // Print header if we have not already done so.
+            if (!headerPrinted) {
+                headerPrinted = true;
+                System.out.println("");
+                String title = ShellUtil.getBundleName(bundle) + ((inUse) ? " uses:" : " provides:");
+                System.out.println(title);
+                System.out.println(ShellUtil.getUnderlineString(title));
+            }
+
+            if (print) {
+                // Print service separator if necessary.
+                if (needSeparator && showProperties) {
+                    System.out.println("----");
+                }
+
+                if (showProperties) {
+                    printProperties(serviceRef);
+                } else {
+                    System.out.println(ShellUtil.getValueString(objectClass));
+                }
+
+                needSeparator = true;
+            }
+        }
+    }
+
+    private boolean isCommandOrCompleter(String[] objectClasses) {
+        for (String objectClass : objectClasses) {
+            if (hidden.contains(objectClass)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private void printProperties(ServiceReference<?> serviceRef) {
+        for (String key : serviceRef.getPropertyKeys()) {
+            System.out.println(key + " = " + ShellUtil.getValueString(serviceRef.getProperty(key)));
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d0180939/bundle/core/src/main/java/org/apache/karaf/bundle/command/ListBundles.java
----------------------------------------------------------------------
diff --git a/bundle/core/src/main/java/org/apache/karaf/bundle/command/ListBundles.java b/bundle/core/src/main/java/org/apache/karaf/bundle/command/ListBundles.java
new file mode 100644
index 0000000..107e578
--- /dev/null
+++ b/bundle/core/src/main/java/org/apache/karaf/bundle/command/ListBundles.java
@@ -0,0 +1,176 @@
+/*
+ * 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.karaf.bundle.command;
+
+import org.apache.karaf.bundle.core.BundleInfo;
+import org.apache.karaf.bundle.core.BundleService;
+import org.apache.karaf.bundle.core.BundleState;
+import org.apache.karaf.shell.api.action.Action;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.Option;
+import org.apache.karaf.shell.api.action.lifecycle.Reference;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.apache.karaf.shell.support.table.ShellTable;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.startlevel.FrameworkStartLevel;
+
+@Command(scope = "bundle", name = "list", description = "Lists all installed bundles.")
+@Service
+public class ListBundles implements Action {
+
+    @Option(name = "-l", aliases = {}, description = "Show the locations", required = false, multiValued = false)
+    boolean showLoc;
+
+    @Option(name = "-s", description = "Shows the symbolic name", required = false, multiValued = false)
+    boolean showSymbolic;
+
+    @Option(name = "-u", description = "Shows the update locations", required = false, multiValued = false)
+    boolean showUpdate;
+
+    @Option(name = "-t", valueToShowInHelp = "", description = "Specifies the bundle threshold; bundles with a start-level less than this value will not get printed out.", required = false, multiValued = false)
+    int bundleLevelThreshold = -1;
+
+    @Option(name = "--no-format", description = "Disable table rendered output", required = false, multiValued = false)
+    boolean noFormat;
+
+    @Reference
+    BundleContext bundleContext;
+
+    @Reference
+    private BundleService bundleService;
+
+    public void setBundleService(BundleService bundleService) {
+        this.bundleService = bundleService;
+    }
+
+    @Override
+    public Object execute() throws Exception {
+        Bundle[] bundles = bundleContext.getBundles();
+        if (bundles == null) {
+            System.out.println("There are no installed bundles.");
+            return null;
+        }
+
+        determineBundleLevelThreshold();
+        
+        // Display active start level.
+        FrameworkStartLevel fsl = bundleContext.getBundle(0).adapt(FrameworkStartLevel.class);
+        if (fsl != null) {
+            System.out.println("START LEVEL " + fsl.getStartLevel() + " , List Threshold: " + bundleLevelThreshold);
+        }
+
+        ShellTable table = new ShellTable();
+        table.column("ID").alignRight();
+        table.column("State");
+        table.column("Lvl").alignRight();
+        table.column("Version");
+        table.column(getNameHeader());
+        
+        for (int i = 0; i < bundles.length; i++) {
+            Bundle bundle = bundles[i];
+            BundleInfo info = this.bundleService.getInfo(bundle);
+            if (info.getStartLevel() >= bundleLevelThreshold) {
+                String name = getNameToShow(info) + printFragments(info) + printHosts(info);
+                String version = info.getVersion();
+                table.addRow().addContent(info.getBundleId(), getStateString(info.getState()), 
+                        info.getStartLevel(), version, name);
+            }
+        }
+        table.print(System.out, !noFormat);
+
+        return null;
+    }
+
+    private String getNameHeader() {
+        String msg = "Name";
+        if (showLoc) {
+            msg = "Location";
+        } else if (showSymbolic) {
+            msg = "Symbolic name";
+        } else if (showUpdate) {
+            msg = "Update location";
+        }
+        return msg;
+    }
+
+    private void determineBundleLevelThreshold() {
+        final String sbslProp = bundleContext.getProperty("karaf.systemBundlesStartLevel");
+        if (sbslProp != null) {
+            try {
+                if (bundleLevelThreshold < 0) {
+                    bundleLevelThreshold = Integer.valueOf(sbslProp);
+                }
+            } catch (Exception ignore) {
+                // ignore
+            }
+        }
+    }
+
+    private String printHosts(BundleInfo info) {
+        if (info.getFragmentHosts().size() <= 0) {
+            return "";
+        }
+        StringBuilder builder = new StringBuilder();
+        builder.append(", Hosts: ");
+        boolean first = true;
+        for (Bundle host : info.getFragmentHosts()) {
+            builder.append((first ? "" : ", ") + host.getBundleId());
+            first = false;
+        }
+        return builder.toString();
+    }
+
+    private String printFragments(BundleInfo info) {
+        if (info.getFragments().size() <= 0) {
+            return "";
+        }
+        StringBuilder builder = new StringBuilder();
+        builder.append(", Fragments: ");
+        boolean first = true;
+        for (Bundle host : info.getFragments()) {
+            builder.append((first ? "" : ", ") + host.getBundleId());
+            first = false;
+        }
+        return builder.toString();
+    }
+
+    private String getStateString(BundleState state) {
+        return (state == null) ? "" : state.toString();
+    }
+
+    /**
+     * Overwrite the default value is the user specifically requested to display
+     * one or the other.
+     * 
+     * @param info
+     * @return
+     */
+    private String getNameToShow(BundleInfo info) {
+        if (showLoc) {
+            return info.getUpdateLocation();
+        } else if (showSymbolic) {
+            return info.getSymbolicName() == null ? "<no symbolic name>" : info.getSymbolicName();
+        } else if (showUpdate) {
+            return info.getUpdateLocation();
+        } else {
+            String name = (info.getName() == null) ? info.getSymbolicName() : info.getName();
+            return (name == null) ? info.getUpdateLocation() : name;
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d0180939/bundle/core/src/main/java/org/apache/karaf/bundle/command/LoadTest.java
----------------------------------------------------------------------
diff --git a/bundle/core/src/main/java/org/apache/karaf/bundle/command/LoadTest.java b/bundle/core/src/main/java/org/apache/karaf/bundle/command/LoadTest.java
new file mode 100644
index 0000000..8ed318f
--- /dev/null
+++ b/bundle/core/src/main/java/org/apache/karaf/bundle/command/LoadTest.java
@@ -0,0 +1,192 @@
+/*
+ * 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.karaf.bundle.command;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Random;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import org.apache.karaf.shell.api.action.Action;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.Option;
+import org.apache.karaf.shell.api.console.Session;
+import org.apache.karaf.shell.api.action.lifecycle.Reference;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleException;
+import org.osgi.framework.FrameworkEvent;
+import org.osgi.framework.FrameworkListener;
+import org.osgi.framework.wiring.FrameworkWiring;
+
+@Command(scope = "bundle", name = "load-test", description = "Load test bundle lifecycle")
+@Service
+public class LoadTest implements Action {
+
+    @Option(name = "--threads", description = "number of concurrent threads")
+    int threads = 2;
+
+    @Option(name = "--delay", description = "maximum delay between actions")
+    int delay = 1;
+
+    @Option(name = "--iterations", description = "number of iterations per thread")
+    int iterations = 100;
+
+    @Option(name = "--refresh", description = "percentage of bundle refresh vs restart")
+    int refresh = 20;
+
+    @Option(name = "--excludes", description = "List of bundles (ids or symbolic names) to exclude")
+    List<String> excludes = Arrays.asList("0", "org.ops4j.pax.url.mvn", "org.ops4j.pax.logging.pax-logging-api", "org.ops4j.pax.logging.pax-logging-service");
+
+    @Reference
+    Session session;
+
+    @Reference
+    BundleContext bundleContext;
+
+    @Override
+    public Object execute() throws Exception {
+        if (!confirm(session)) {
+            return null;
+        }
+        final BundleContext bundleContext = this.bundleContext.getBundle(0).getBundleContext();
+        final FrameworkWiring wiring = bundleContext.getBundle().adapt(FrameworkWiring.class);
+        final CountDownLatch latch = new CountDownLatch(threads);
+        final Bundle[] bundles = bundleContext.getBundles();
+        final AtomicBoolean[] locks = new AtomicBoolean[bundles.length];
+        for (int b = 0; b < locks.length; b++) {
+            locks[b] = new AtomicBoolean(true);
+            // Avoid touching excluded bundles
+            if (excludes.contains(Long.toString(bundles[b].getBundleId()))
+                    || excludes.contains(bundles[b].getSymbolicName())) {
+                continue;
+            }
+            // Only touch active bundles
+            if (bundles[b].getState() != Bundle.ACTIVE) {
+                continue;
+            }
+            // Now set the lock to available
+            locks[b].set(false);
+        }
+        for (int i = 0; i < threads; i++) {
+            new Thread() {
+                public void run() {
+                    try {
+                        Random rand = new Random();
+                        for (int j = 0; j < iterations; j++) {
+                            for (;;) {
+                                int b = rand.nextInt(bundles.length);
+                                if (locks[b].compareAndSet(false, true)) {
+                                    try {
+                                        // Only touch active bundles
+                                        if (bundles[b].getState() != Bundle.ACTIVE) {
+                                            continue;
+                                        }
+                                        if (rand.nextInt(100) < refresh) {
+                                            try {
+                                                bundles[b].update();
+                                                final CountDownLatch latch = new CountDownLatch(1);
+                                                wiring.refreshBundles(Collections.singletonList(bundles[b]), new FrameworkListener() {
+                                                    public void frameworkEvent(FrameworkEvent event) {
+                                                        latch.countDown();
+                                                    }
+                                                });
+                                                latch.await();
+                                            } finally {
+                                                while (true) {
+                                                    try {
+                                                        bundles[b].start(Bundle.START_TRANSIENT);
+                                                        break;
+                                                    } catch (Exception e) {
+                                                        Thread.sleep(1);
+                                                    }
+                                                }
+                                            }
+                                        } else {
+                                            try {
+                                                bundles[b].stop(Bundle.STOP_TRANSIENT);
+                                            } finally {
+                                                while (true) {
+                                                    try {
+                                                        bundles[b].start(Bundle.START_TRANSIENT);
+                                                        break;
+                                                    } catch (Exception e) {
+                                                        Thread.sleep(1);
+                                                    }
+                                                }
+                                            }
+                                        }
+                                        Thread.sleep(rand.nextInt(delay));
+                                    } catch (Exception e) {
+                                        boolean ignore = false;
+                                        if (e instanceof BundleException && e.getMessage() != null) {
+                                            String msg = e.getMessage();
+                                            if ("Cannot acquire global lock to update the bundle.".equals(msg) ||
+                                                    "Unable to acquire global lock for resolve.".equals(msg) ||
+                                                    msg.matches("Bundle .* cannot be update, since it is either starting or stopping.")) {
+                                                ignore = true;
+                                            }
+                                        }
+                                        if (!ignore) {
+                                            e.printStackTrace();
+                                        }
+                                    } finally {
+                                        locks[b].set(false);
+                                    }
+                                }
+                                break;
+                            }
+                        }
+                    } catch (Throwable t) {
+                        t.printStackTrace();
+                    } finally {
+                        latch.countDown();
+                    }
+                }
+            }.start();
+        }
+        new Thread() {
+            @Override
+            public void run() {
+                try {
+                    latch.await();
+                } catch (InterruptedException e) {
+                    e.printStackTrace();
+                }
+                System.err.println("Load test finished");
+            }
+        }.start();
+        return null;
+    }
+
+    private boolean confirm(Session session) throws IOException {
+        for (;;) {
+            String msg = "You are about to perform a start/stop/refresh load test on bundles.\nDo you wish to continue (yes/no): ";
+            String str = session.readLine(msg, null);
+            if ("yes".equalsIgnoreCase(str)) {
+                return true;
+            }
+            if ("no".equalsIgnoreCase(str)) {
+                return false;
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d0180939/bundle/core/src/main/java/org/apache/karaf/bundle/command/Refresh.java
----------------------------------------------------------------------
diff --git a/bundle/core/src/main/java/org/apache/karaf/bundle/command/Refresh.java b/bundle/core/src/main/java/org/apache/karaf/bundle/command/Refresh.java
new file mode 100644
index 0000000..53adaeb
--- /dev/null
+++ b/bundle/core/src/main/java/org/apache/karaf/bundle/command/Refresh.java
@@ -0,0 +1,43 @@
+/*
+ * 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.karaf.bundle.command;
+
+import java.util.List;
+
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.wiring.FrameworkWiring;
+
+@Command(scope = "bundle", name = "refresh", description = "Refresh bundles.")
+@Service
+public class Refresh extends BundlesCommandWithConfirmation {
+    
+    public Refresh() {
+        this.defaultAllBundles = false;
+    }
+
+    protected void doExecute(List<Bundle> bundles) throws Exception {
+        FrameworkWiring wiring = bundleContext.getBundle(0).adapt(FrameworkWiring.class);
+        wiring.refreshBundles(bundles == null || bundles.isEmpty() ? null : bundles);
+    }
+
+    @Override
+    protected void executeOnBundle(Bundle bundle) throws Exception {
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d0180939/bundle/core/src/main/java/org/apache/karaf/bundle/command/Requirements.java
----------------------------------------------------------------------
diff --git a/bundle/core/src/main/java/org/apache/karaf/bundle/command/Requirements.java b/bundle/core/src/main/java/org/apache/karaf/bundle/command/Requirements.java
new file mode 100644
index 0000000..c87d4d4
--- /dev/null
+++ b/bundle/core/src/main/java/org/apache/karaf/bundle/command/Requirements.java
@@ -0,0 +1,177 @@
+/*
+ * 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.karaf.bundle.command;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Pattern;
+
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.Option;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.apache.karaf.shell.support.ShellUtil;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.wiring.BundleCapability;
+import org.osgi.framework.wiring.BundleRequirement;
+import org.osgi.framework.wiring.BundleWire;
+import org.osgi.framework.wiring.BundleWiring;
+
+@Command(scope = "bundle", name = "requirements", description = "Displays OSGi requirements of a given bundles.")
+@Service
+public class Requirements extends BundlesCommand {
+
+    public static final String NONSTANDARD_SERVICE_NAMESPACE = "service";
+
+    private static final String EMPTY_MESSAGE = "[EMPTY]";
+    private static final String UNRESOLVED_MESSAGE = "[UNRESOLVED]";
+
+    @Option(name = "--namespace")
+    String namespace = "*";
+    
+    public Requirements() {
+        super(true);
+    }
+
+    @Override
+    protected void doExecute(List<Bundle> bundles) throws Exception {
+        boolean separatorNeeded = false;
+        Pattern ns = Pattern.compile(namespace.replaceAll("\\.", "\\\\.").replaceAll("\\*", ".*"));
+        for (Bundle b : bundles) {
+            if (separatorNeeded) {
+                System.out.println("");
+            }
+
+            // Print out any matching generic requirements.
+            BundleWiring wiring = b.adapt(BundleWiring.class);
+            if (wiring != null) {
+                String title = b + " requires:";
+                System.out.println(title);
+                System.out.println(ShellUtil.getUnderlineString(title));
+                boolean matches = printMatchingRequirements(wiring, ns);
+
+                // Handle service requirements separately, since they aren't part
+                // of the generic model in OSGi.
+                if (matchNamespace(ns, NONSTANDARD_SERVICE_NAMESPACE)) {
+                    matches |= printServiceRequirements(b);
+                }
+
+                // If there were no requirements for the specified namespace,
+                // then say so.
+                if (!matches) {
+                    System.out.println(namespace + " " + EMPTY_MESSAGE);
+                }
+            } else {
+                System.out.println("Bundle " + b.getBundleId() + " is not resolved.");
+            }
+
+            separatorNeeded = true;
+        }
+    }
+
+    private static boolean printMatchingRequirements(BundleWiring wiring, Pattern namespace) {
+        List<BundleWire> wires = wiring.getRequiredWires(null);
+        Map<BundleRequirement, List<BundleWire>> aggregateReqs = aggregateRequirements(namespace, wires);
+        List<BundleRequirement> allReqs = wiring.getRequirements(null);
+        boolean matches = false;
+        for (BundleRequirement req : allReqs) {
+            if (matchNamespace(namespace, req.getNamespace())) {
+                matches = true;
+                List<BundleWire> providers = aggregateReqs.get(req);
+                if (providers != null) {
+                    System.out.println(req.getNamespace() + "; "
+                                    + req.getDirectives().get(Constants.FILTER_DIRECTIVE) + " resolved by:");
+                    for (BundleWire wire : providers) {
+                        String msg;
+                        Object keyAttr = wire.getCapability().getAttributes().get(wire.getCapability().getNamespace());
+                        if (keyAttr != null) {
+                            msg = wire.getCapability().getNamespace() + "; "
+                                    + keyAttr + " " + getVersionFromCapability(wire.getCapability());
+                        } else {
+                            msg = wire.getCapability().toString();
+                        }
+                        msg = "   " + msg + " from " + wire.getProviderWiring().getBundle();
+                        System.out.println(msg);
+                    }
+                } else {
+                    System.out.println(req.getNamespace() + "; "
+                                    + req.getDirectives().get(Constants.FILTER_DIRECTIVE) + " " + UNRESOLVED_MESSAGE);
+                }
+            }
+        }
+        return matches;
+    }
+
+    private static Map<BundleRequirement, List<BundleWire>> aggregateRequirements(
+            Pattern namespace, List<BundleWire> wires) {
+        // Aggregate matching capabilities.
+        Map<BundleRequirement, List<BundleWire>> map = new HashMap<BundleRequirement, List<BundleWire>>();
+        for (BundleWire wire : wires) {
+            if (matchNamespace(namespace, wire.getRequirement().getNamespace())) {
+                List<BundleWire> providers = map.get(wire.getRequirement());
+                if (providers == null) {
+                    providers = new ArrayList<BundleWire>();
+                    map.put(wire.getRequirement(), providers);
+                }
+                providers.add(wire);
+            }
+        }
+        return map;
+    }
+
+    static boolean printServiceRequirements(Bundle b) {
+        boolean matches = false;
+
+        try {
+            ServiceReference<?>[] refs = b.getServicesInUse();
+
+            if ((refs != null) && (refs.length > 0)) {
+                matches = true;
+                // Print properties for each service.
+                for (ServiceReference<?> ref : refs) {
+                    // Print object class with "namespace".
+                    System.out.println(
+                            NONSTANDARD_SERVICE_NAMESPACE
+                                    + "; "
+                                    + ShellUtil.getValueString(ref.getProperty("objectClass"))
+                                    + " provided by:");
+                    System.out.println("   " + ref.getBundle());
+                }
+            }
+        } catch (Exception ex) {
+            System.err.println(ex.toString());
+        }
+
+        return matches;
+    }
+
+    private static String getVersionFromCapability(BundleCapability c) {
+        Object o = c.getAttributes().get(Constants.VERSION_ATTRIBUTE);
+        if (o == null) {
+            o = c.getAttributes().get(Constants.BUNDLE_VERSION_ATTRIBUTE);
+        }
+        return (o == null) ? "" : o.toString();
+    }
+
+    private static boolean matchNamespace(Pattern namespace, String actual) {
+        return namespace.matcher(actual).matches();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d0180939/bundle/core/src/main/java/org/apache/karaf/bundle/command/Resolve.java
----------------------------------------------------------------------
diff --git a/bundle/core/src/main/java/org/apache/karaf/bundle/command/Resolve.java b/bundle/core/src/main/java/org/apache/karaf/bundle/command/Resolve.java
new file mode 100644
index 0000000..720f118
--- /dev/null
+++ b/bundle/core/src/main/java/org/apache/karaf/bundle/command/Resolve.java
@@ -0,0 +1,39 @@
+/*
+ * 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.karaf.bundle.command;
+
+import java.util.List;
+
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.wiring.FrameworkWiring;
+
+@Command(scope = "bundle", name = "resolve", description = "Resolve bundles.")
+@Service
+public class Resolve extends BundlesCommand {
+
+    public Resolve() {
+        super(true);
+    }
+
+    protected void doExecute(List<Bundle> bundles) throws Exception {
+        FrameworkWiring wiring = bundleContext.getBundle(0).adapt(FrameworkWiring.class);
+        wiring.resolveBundles(bundles == null || bundles.isEmpty() ? null : bundles);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d0180939/bundle/core/src/main/java/org/apache/karaf/bundle/command/Restart.java
----------------------------------------------------------------------
diff --git a/bundle/core/src/main/java/org/apache/karaf/bundle/command/Restart.java b/bundle/core/src/main/java/org/apache/karaf/bundle/command/Restart.java
new file mode 100644
index 0000000..95d5dfe
--- /dev/null
+++ b/bundle/core/src/main/java/org/apache/karaf/bundle/command/Restart.java
@@ -0,0 +1,62 @@
+/*
+ * 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.karaf.bundle.command;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.apache.karaf.shell.support.MultiException;
+import org.osgi.framework.Bundle;
+
+@Command(scope = "bundle", name = "restart", description = "Restarts bundles.")
+@Service
+public class Restart extends BundlesCommandWithConfirmation {
+    
+    public Restart() {
+        errorMessage = "Error restarting bundle";
+    }
+
+    protected void doExecute(List<Bundle> bundles) throws Exception {
+        if (bundles.isEmpty()) {
+            System.err.println("No bundles specified.");
+            return;
+        }
+        List<Exception> exceptions = new ArrayList<Exception>();
+        for (Bundle bundle : bundles) {
+            try {
+                bundle.stop();
+            } catch (Exception e) {
+                exceptions.add(new Exception("Unable to stop bundle " + bundle.getBundleId() + ": " + e.getMessage(), e));
+            }
+        }
+        for (Bundle bundle : bundles) {
+            try {
+                bundle.start();
+            } catch (Exception e) {
+                exceptions.add(new Exception("Unable to start bundle " + bundle.getBundleId() + ": " + e.getMessage(), e));
+            }
+        }
+        MultiException.throwIf("Error restarting bundles", exceptions);
+    }
+
+    @Override
+    protected void executeOnBundle(Bundle bundle) throws Exception {
+    }
+
+}


[15/59] [abbrv] [KARAF-2852] Merge features/core and features/command

Posted by gn...@apache.org.
http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/core/src/main/java/org/apache/karaf/features/internal/model/Config.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/model/Config.java b/features/core/src/main/java/org/apache/karaf/features/internal/model/Config.java
deleted file mode 100644
index a2c6674..0000000
--- a/features/core/src/main/java/org/apache/karaf/features/internal/model/Config.java
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * 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.karaf.features.internal.model;
-
-import javax.xml.bind.annotation.XmlAccessType;
-import javax.xml.bind.annotation.XmlAccessorType;
-import javax.xml.bind.annotation.XmlAttribute;
-import javax.xml.bind.annotation.XmlType;
-import javax.xml.bind.annotation.XmlValue;
-
-
-/**
- * 
- * Configuration entries which should be created during feature installation. This
- * configuration may be used with OSGi Configuration Admin.
- *             
- * 
- * <p>Java class for config complex type.
- * 
- * <p>The following schema fragment specifies the expected content contained within this class.
- * 
- * <pre>
- * &lt;complexType name="config">
- *   &lt;simpleContent>
- *     &lt;extension base="&lt;http://www.w3.org/2001/XMLSchema>string">
- *       &lt;attribute name="name" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
- *     &lt;/extension>
- *   &lt;/simpleContent>
- * &lt;/complexType>
- * </pre>
- * 
- * 
- */
-@XmlAccessorType(XmlAccessType.FIELD)
-@XmlType(name = "config", propOrder = {
-    "value"
-})
-public class Config {
-
-    @XmlValue
-    protected String value;
-    @XmlAttribute(required = true)
-    protected String name;
-
-    /**
-     * Gets the value of the value property.
-     * 
-     * @return
-     *     possible object is
-     *     {@link String }
-     *     
-     */
-    public String getValue() {
-        return value;
-    }
-
-    /**
-     * Sets the value of the value property.
-     * 
-     * @param value
-     *     allowed object is
-     *     {@link String }
-     *     
-     */
-    public void setValue(String value) {
-        this.value = value;
-    }
-
-    /**
-     * Gets the value of the name property.
-     * 
-     * @return
-     *     possible object is
-     *     {@link String }
-     *     
-     */
-    public String getName() {
-        return name;
-    }
-
-    /**
-     * Sets the value of the name property.
-     * 
-     * @param value
-     *     allowed object is
-     *     {@link String }
-     *     
-     */
-    public void setName(String value) {
-        this.name = value;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/core/src/main/java/org/apache/karaf/features/internal/model/ConfigFile.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/model/ConfigFile.java b/features/core/src/main/java/org/apache/karaf/features/internal/model/ConfigFile.java
deleted file mode 100644
index e5d9d94..0000000
--- a/features/core/src/main/java/org/apache/karaf/features/internal/model/ConfigFile.java
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * 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.karaf.features.internal.model;
-
-import javax.xml.bind.annotation.XmlAccessType;
-import javax.xml.bind.annotation.XmlAccessorType;
-import javax.xml.bind.annotation.XmlAttribute;
-import javax.xml.bind.annotation.XmlType;
-import javax.xml.bind.annotation.XmlValue;
-import org.apache.karaf.features.ConfigFileInfo;
-
-
-/**
- * 
- * Additional configuration files which should be created during feature installation.
- *             
- * 
- * <p>Java class for configFile complex type.
- * 
- * <p>The following schema fragment specifies the expected content contained within this class.
- * 
- * <pre>
- * &lt;complexType name="configFile">
- *   &lt;simpleContent>
- *     &lt;extension base="&lt;http://www.w3.org/2001/XMLSchema>string">
- *       &lt;attribute name="finalname" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
- *       &lt;attribute name="override" type="{http://www.w3.org/2001/XMLSchema}boolean" />
- *     &lt;/extension>
- *   &lt;/simpleContent>
- * &lt;/complexType>
- * </pre>
- * 
- * 
- */
-@XmlAccessorType(XmlAccessType.FIELD)
-@XmlType(name = "configFile", propOrder = {
-    "value"
-})
-public class ConfigFile implements ConfigFileInfo {
-
-    @XmlValue
-    protected String value;
-    @XmlAttribute(required = true)
-    protected String finalname;
-    @XmlAttribute
-    protected Boolean override;
-
-    /**
-     * Gets the value of the value property.
-     * 
-     * @return
-     *     possible object is
-     *     {@link String }
-     *     
-     */
-    public String getLocation() {
-        return value;
-    }
-
-    /**
-     * Sets the value of the value property.
-     * 
-     * @param value
-     *     allowed object is
-     *     {@link String }
-     *     
-     */
-    public void setLocation(String value) {
-        this.value = value;
-    }
-
-    /**
-     * Gets the value of the finalname property.
-     * 
-     * @return
-     *     possible object is
-     *     {@link String }
-     *     
-     */
-    public String getFinalname() {
-        return finalname;
-    }
-
-    /**
-     * Sets the value of the finalname property.
-     * 
-     * @param value
-     *     allowed object is
-     *     {@link String }
-     *     
-     */
-    public void setFinalname(String value) {
-    	this.finalname = value;
-    }
-
-    /**
-     * Gets the value of the override property.
-     * 
-     * @return
-     *     possible object is
-     *     {@link Boolean }
-     *     
-     */
-    public boolean isOverride() {
-        return override == null? false: override;
-    }
-
-    /**
-     * Sets the value of the override property.
-     * 
-     * @param value
-     *     allowed object is
-     *     {@link Boolean }
-     *     
-     */
-    public void setOverride(Boolean value) {
-    	this.override = value;
-    }
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/core/src/main/java/org/apache/karaf/features/internal/model/Content.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/model/Content.java b/features/core/src/main/java/org/apache/karaf/features/internal/model/Content.java
deleted file mode 100644
index 756e4c1..0000000
--- a/features/core/src/main/java/org/apache/karaf/features/internal/model/Content.java
+++ /dev/null
@@ -1,199 +0,0 @@
-/*
- * 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.karaf.features.internal.model;
-
-import java.io.IOException;
-import java.io.StringReader;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Enumeration;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Properties;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-import javax.xml.bind.annotation.XmlTransient;
-import org.apache.karaf.features.BundleInfo;
-import org.apache.karaf.features.ConfigFileInfo;
-
-@XmlTransient
-public class Content {
-
-    protected List<Config> config;
-    protected List<ConfigFile> configfile;
-    protected List<Dependency> feature;
-    protected List<Bundle> bundle;
-
-    /**
-     * Gets the value of the config property.
-     * <p/>
-     * <p/>
-     * This accessor method returns a reference to the live list,
-     * not a snapshot. Therefore any modification you make to the
-     * returned list will be present inside the JAXB object.
-     * This is why there is not a <CODE>set</CODE> method for the config property.
-     * <p/>
-     * <p/>
-     * For example, to add a new item, do as follows:
-     * <pre>
-     *    getConfig().add(newItem);
-     * </pre>
-     * <p/>
-     * <p/>
-     * <p/>
-     * Objects of the following type(s) are allowed in the list
-     * {@link Config }
-     */
-    public List<Config> getConfig() {
-        if (config == null) {
-            config = new ArrayList<Config>();
-        }
-        return this.config;
-    }
-
-    /**
-     * Gets the value of the configfile property.
-     * <p/>
-     * <p/>
-     * This accessor method returns a reference to the live list,
-     * not a snapshot. Therefore any modification you make to the
-     * returned list will be present inside the JAXB object.
-     * This is why there is not a <CODE>set</CODE> method for the configfile property.
-     * <p/>
-     * <p/>
-     * For example, to add a new item, do as follows:
-     * <pre>
-     *    getConfigfile().add(newItem);
-     * </pre>
-     * <p/>
-     * <p/>
-     * <p/>
-     * Objects of the following type(s) are allowed in the list
-     * {@link ConfigFile }
-     */
-    public List<ConfigFile> getConfigfile() {
-        if (configfile == null) {
-            configfile = new ArrayList<ConfigFile>();
-        }
-        return this.configfile;
-    }
-
-    /**
-     * Gets the value of the feature property.
-     * <p/>
-     * <p/>
-     * This accessor method returns a reference to the live list,
-     * not a snapshot. Therefore any modification you make to the
-     * returned list will be present inside the JAXB object.
-     * This is why there is not a <CODE>set</CODE> method for the feature property.
-     * <p/>
-     * <p/>
-     * For example, to add a new item, do as follows:
-     * <pre>
-     *    getFeature().add(newItem);
-     * </pre>
-     * <p/>
-     * <p/>
-     * <p/>
-     * Objects of the following type(s) are allowed in the list
-     * {@link Dependency }
-     */
-    public List<Dependency> getFeature() {
-        if (feature == null) {
-            feature = new ArrayList<Dependency>();
-        }
-        return this.feature;
-    }
-
-    /**
-     * Gets the value of the bundle property.
-     * <p/>
-     * <p/>
-     * This accessor method returns a reference to the live list,
-     * not a snapshot. Therefore any modification you make to the
-     * returned list will be present inside the JAXB object.
-     * This is why there is not a <CODE>set</CODE> method for the bundle property.
-     * <p/>
-     * <p/>
-     * For example, to add a new item, do as follows:
-     * <pre>
-     *    getBundle().add(newItem);
-     * </pre>
-     * <p/>
-     * <p/>
-     * <p/>
-     * Objects of the following type(s) are allowed in the list
-     * {@link Bundle }
-     */
-    public List<Bundle> getBundle() {
-        if (bundle == null) {
-            bundle = new ArrayList<Bundle>();
-        }
-        return this.bundle;
-    }
-
-    public List<org.apache.karaf.features.Dependency> getDependencies() {
-        return Collections.<org.apache.karaf.features.Dependency>unmodifiableList(getFeature());
-    }
-
-    public List<BundleInfo> getBundles() {
-        return Collections.<BundleInfo>unmodifiableList(getBundle());
-    }
-
-    public Map<String, Map<String, String>> getConfigurations() {
-        Map<String, Map<String, String>> result = new HashMap<String, Map<String, String>>();
-        for (Config config : getConfig()) {
-            String name = config.getName();
-            StringReader propStream = new StringReader(config.getValue());
-            Properties props = new Properties();
-            try {
-                props.load(propStream);
-            } catch (IOException e) {
-                //ignore??
-            }
-            interpolation(props);
-            Map<String, String> propMap = new HashMap<String, String>();
-            for (Map.Entry<Object, Object> entry : props.entrySet()) {
-                propMap.put((String) entry.getKey(), (String) entry.getValue());
-            }
-            result.put(name, propMap);
-        }
-        return result;
-    }
-
-    public List<ConfigFileInfo> getConfigurationFiles() {
-        return Collections.<ConfigFileInfo>unmodifiableList(getConfigfile());
-    }
-
-    @SuppressWarnings("rawtypes")
-	protected void interpolation(Properties properties) {
-        for (Enumeration e = properties.propertyNames(); e.hasMoreElements(); ) {
-            String key = (String) e.nextElement();
-            String val = properties.getProperty(key);
-            Matcher matcher = Pattern.compile("\\$\\{([^}]+)\\}").matcher(val);
-            while (matcher.find()) {
-                String rep = System.getProperty(matcher.group(1));
-                if (rep != null) {
-                    val = val.replace(matcher.group(0), rep);
-                    matcher.reset(val);
-                }
-            }
-            properties.put(key, val);
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/core/src/main/java/org/apache/karaf/features/internal/model/Dependency.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/model/Dependency.java b/features/core/src/main/java/org/apache/karaf/features/internal/model/Dependency.java
deleted file mode 100644
index 9c92a93..0000000
--- a/features/core/src/main/java/org/apache/karaf/features/internal/model/Dependency.java
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * 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.karaf.features.internal.model;
-
-import javax.xml.bind.annotation.XmlAccessType;
-import javax.xml.bind.annotation.XmlAccessorType;
-import javax.xml.bind.annotation.XmlAttribute;
-import javax.xml.bind.annotation.XmlType;
-import javax.xml.bind.annotation.XmlValue;
-
-
-/**
- * 
- * Dependency of feature.
- *             
- * 
- * <p>Java class for dependency complex type.
- * 
- * <p>The following schema fragment specifies the expected content contained within this class.
- * 
- * <pre>
- * &lt;complexType name="dependency">
- *   &lt;simpleContent>
- *     &lt;extension base="&lt;http://karaf.apache.org/xmlns/features/v1.0.0>featureName">
- *       &lt;attribute name="version" type="{http://www.w3.org/2001/XMLSchema}string" default="0.0.0" />
- *     &lt;/extension>
- *   &lt;/simpleContent>
- * &lt;/complexType>
- * </pre>
- * 
- * 
- */
-@XmlAccessorType(XmlAccessType.FIELD)
-@XmlType(name = "dependency", propOrder = {
-    "value"
-})
-public class Dependency implements org.apache.karaf.features.Dependency {
-
-    @XmlValue
-    protected String value;
-    @XmlAttribute
-    protected String version;
-
-    /**
-     * 
-     * Feature name should be non empty string.
-     *             
-     * 
-     * @return
-     *     possible object is
-     *     {@link String }
-     *     
-     */
-    public String getName() {
-        return value;
-    }
-
-    /**
-     * Sets the value of the value property.
-     * 
-     * @param value
-     *     allowed object is
-     *     {@link String }
-     *     
-     */
-    public void setName(String value) {
-        this.value = value;
-    }
-
-    /**
-     * Gets the value of the version property.
-     * 
-     * @return
-     *     possible object is
-     *     {@link String }
-     *     
-     */
-    public String getVersion() {
-        if (version == null) {
-            return "0.0.0";
-        } else {
-            return version;
-        }
-    }
-
-    /**
-     * Sets the value of the version property.
-     * 
-     * @param value
-     *     allowed object is
-     *     {@link String }
-     *     
-     */
-    public void setVersion(String value) {
-        this.version = value;
-    }
-
-    public String toString() {
-    	String ret = getName() + Feature.SPLIT_FOR_NAME_AND_VERSION + getVersion();
-    	return ret;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/core/src/main/java/org/apache/karaf/features/internal/model/Feature.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/model/Feature.java b/features/core/src/main/java/org/apache/karaf/features/internal/model/Feature.java
deleted file mode 100644
index 46580da..0000000
--- a/features/core/src/main/java/org/apache/karaf/features/internal/model/Feature.java
+++ /dev/null
@@ -1,374 +0,0 @@
-/*
- * 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.karaf.features.internal.model;
-
-import java.util.ArrayList;
-import java.util.Enumeration;
-import java.util.List;
-import java.util.Properties;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import javax.xml.bind.annotation.XmlAccessType;
-import javax.xml.bind.annotation.XmlAccessorType;
-import javax.xml.bind.annotation.XmlAttribute;
-import javax.xml.bind.annotation.XmlType;
-
-
-/**
- * 
- * Definition of the Feature.
- *             
- * 
- * <p>Java class for feature complex type.
- * 
- * <p>The following schema fragment specifies the expected content contained within this class.
- * 
- * <pre>
- * &lt;complexType name="feature">
- *   &lt;complexContent>
- *     &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
- *       &lt;sequence>
- *         &lt;element name="details" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
- *         &lt;element name="config" type="{http://karaf.apache.org/xmlns/features/v1.0.0}config" maxOccurs="unbounded" minOccurs="0"/>
- *         &lt;element name="configfile" type="{http://karaf.apache.org/xmlns/features/v1.0.0}configFile" maxOccurs="unbounded" minOccurs="0"/>
- *         &lt;element name="feature" type="{http://karaf.apache.org/xmlns/features/v1.0.0}dependency" maxOccurs="unbounded" minOccurs="0"/>
- *         &lt;element name="bundle" type="{http://karaf.apache.org/xmlns/features/v1.0.0}bundle" maxOccurs="unbounded" minOccurs="0"/>
- *         &lt;element name="conditional" type="{http://karaf.apache.org/xmlns/features/v1.0.0}conditional" maxOccurs="unbounded" minOccurs="0"/>
- *         &lt;element name="capability" type="{http://karaf.apache.org/xmlns/features/v1.0.0}capability" maxOccurs="unbounded" minOccurs="0"/>
- *         &lt;element name="requirement" type="{http://karaf.apache.org/xmlns/features/v1.0.0}requirement" maxOccurs="unbounded" minOccurs="0"/>
- *       &lt;/sequence>
- *       &lt;attribute name="name" use="required" type="{http://karaf.apache.org/xmlns/features/v1.0.0}featureName" />
- *       &lt;attribute name="version" type="{http://www.w3.org/2001/XMLSchema}string" default="0.0.0" />
- *       &lt;attribute name="description" type="{http://www.w3.org/2001/XMLSchema}string" />
- *       &lt;attribute name="resolver" type="{http://karaf.apache.org/xmlns/features/v1.0.0}resolver" />
- *     &lt;/restriction>
- *   &lt;/complexContent>
- * &lt;/complexType>
- * </pre>
- * 
- * 
- */
-@XmlAccessorType(XmlAccessType.FIELD)
-@XmlType(name = "feature", propOrder = {
-    "details",
-    "config",
-    "configfile",
-    "feature",
-    "bundle",
-    "conditional",
-    "capability",
-    "requirement"
-})
-public class Feature extends Content implements org.apache.karaf.features.Feature {
-    public static String SPLIT_FOR_NAME_AND_VERSION = "/";
-    public static String DEFAULT_VERSION = "0.0.0";
-
-
-    protected String details;
-    @XmlAttribute(required = true)
-    protected String name;
-    @XmlAttribute
-    protected String version;
-    @XmlAttribute
-    protected String description;
-    @XmlAttribute
-    protected String resolver;
-    @XmlAttribute
-    protected String install;
-    @XmlAttribute(name = "start-level")
-    protected Integer startLevel;
-    @XmlAttribute
-    protected String region;
-    protected List<Conditional> conditional;
-    protected List<Capability> capability;
-    protected List<Requirement> requirement;
-
-    public Feature() {
-    }
-
-    public Feature(String name) {
-        this.name = name;
-    }
-
-    public Feature(String name, String version) {
-        this.name = name;
-        this.version = version;
-    }
-
-
-    public static org.apache.karaf.features.Feature valueOf(String str) {
-    	if (str.contains(SPLIT_FOR_NAME_AND_VERSION)) {
-    		String strName = str.substring(0, str.indexOf(SPLIT_FOR_NAME_AND_VERSION));
-        	String strVersion = str.substring(str.indexOf(SPLIT_FOR_NAME_AND_VERSION)
-        			+ SPLIT_FOR_NAME_AND_VERSION.length(), str.length());
-        	return new Feature(strName, strVersion);
-    	} else {
-    		return new Feature(str);
-    	}
-
-
-    }
-
-
-    public String getId() {
-        return getName() + SPLIT_FOR_NAME_AND_VERSION + getVersion();
-    }
-
-    /**
-     * Gets the value of the name property.
-     * 
-     * @return
-     *     possible object is
-     *     {@link String }
-     *     
-     */
-    public String getName() {
-        return name;
-    }
-
-    /**
-     * Sets the value of the name property.
-     * 
-     * @param value
-     *     allowed object is
-     *     {@link String }
-     *     
-     */
-    public void setName(String value) {
-        this.name = value;
-    }
-
-    /**
-     * Gets the value of the version property.
-     * 
-     * @return
-     *     possible object is
-     *     {@link String }
-     *     
-     */
-    public String getVersion() {
-        if (version == null) {
-            return DEFAULT_VERSION;
-        } else {
-            return version;
-        }
-    }
-
-    /**
-     * Sets the value of the version property.
-     * 
-     * @param value
-     *     allowed object is
-     *     {@link String }
-     *     
-     */
-    public void setVersion(String value) {
-        this.version = value;
-    }
-
-    /**
-     * Since version has a default value ("0.0.0"), returns
-     * whether or not the version has been set.
-     */
-    public boolean hasVersion() {
-        return this.version != null;
-    }
-
-    /**
-     * Gets the value of the description property.
-     * 
-     * @return
-     *     possible object is
-     *     {@link String }
-     *     
-     */
-    public String getDescription() {
-        return description;
-    }
-
-    /**
-     * Sets the value of the description property.
-     * 
-     * @param value
-     *     allowed object is
-     *     {@link String }
-     *     
-     */
-    public void setDescription(String value) {
-        this.description = value;
-    }
-
-    public String getDetails() {
-        return details;
-    }
-
-    public void setDetails(String details) {
-        this.details = details;
-    }
-
-    /**
-     * Gets the value of the resolver property.
-     * 
-     * @return
-     *     possible object is
-     *     {@link String }
-     *     
-     */
-    public String getResolver() {
-        return resolver;
-    }
-
-    public String getInstall() {
-        return install;
-    }
-
-    public void setInstall(String install) {
-        this.install = install;
-    }
-
-    /**
-     * Sets the value of the resolver property.
-     * 
-     * @param value
-     *     allowed object is
-     *     {@link String }
-     *     
-     */
-    public void setResolver(String value) {
-        this.resolver = value;
-    }
-    
-    /**
-     * Gets the value of the startLevel property.
-     * 
-     * @return
-     *     possible object is
-     *     {@link Integer }
-     *     
-     */
-    public int getStartLevel() {
-        return startLevel == null? 0: startLevel;
-    }
-
-    /**
-     * Sets the value of the startLevel property.
-     * 
-     * @param value
-     *     allowed object is
-     *     {@link Integer }
-     *     
-     */
-    public void setStartLevel(Integer value) {
-        this.startLevel = value;
-    }
-
-
-    public String getRegion() {
-        return region;
-    }
-
-    public void setRegion(String region) {
-        this.region = region;
-    }
-
-    /**
-     * Gets the value of the conditional property.
-     * <p/>
-     * <p/>
-     * This accessor method returns a reference to the live list,
-     * not a snapshot. Therefore any modification you make to the
-     * returned list will be present inside the JAXB object.
-     * This is why there is not a <CODE>set</CODE> method for the feature property.
-     * <p/>
-     * <p/>
-     * For example, to add a new item, do as follows:
-     * <pre>
-     *    getConditionals().add(newItem);
-     * </pre>
-     * <p/>
-     * <p/>
-     * <p/>
-     * Objects of the following type(s) are allowed in the list
-     * {@link Conditional }
-     */
-    public List<Conditional> getConditional() {
-        if (conditional == null) {
-            conditional = new ArrayList<Conditional>();
-        }
-        return this.conditional;
-    }
-
-    public List<Capability> getCapabilities() {
-        if (capability == null) {
-            capability = new ArrayList<Capability>();
-        }
-        return this.capability;
-    }
-
-    public List<Requirement> getRequirements() {
-        if (requirement == null) {
-            requirement = new ArrayList<Requirement>();
-        }
-        return this.requirement;
-    }
-
-    public String toString() {
-    	return getId();
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) return true;
-        if (o == null || getClass() != o.getClass()) return false;
-
-        Feature feature = (Feature) o;
-
-        if (name != null ? !name.equals(feature.name) : feature.name != null) return false;
-        if (version != null ? !version.equals(feature.version) : feature.version != null) return false;
-
-        return true;
-    }
-
-    @Override
-    public int hashCode() {
-        int result = name != null ? name.hashCode() : 0;
-        result = 31 * result + (version != null ? version.hashCode() : 0);
-        return result;
-    }
-
-    @SuppressWarnings("rawtypes")
-	protected void interpolation(Properties properties) {
-        for (Enumeration e = properties.propertyNames(); e.hasMoreElements();) {
-            String key = (String) e.nextElement();
-            String val = properties.getProperty(key);
-            Matcher matcher = Pattern.compile("\\$\\{([^}]+)\\}").matcher(val);
-            while (matcher.find()) {
-                String rep = System.getProperty(matcher.group(1));
-                if (rep != null) {
-                    val = val.replace(matcher.group(0), rep);
-                    matcher.reset(val);
-                }
-            }
-            properties.put(key, val);
-        }
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/core/src/main/java/org/apache/karaf/features/internal/model/Features.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/model/Features.java b/features/core/src/main/java/org/apache/karaf/features/internal/model/Features.java
deleted file mode 100644
index e116f31..0000000
--- a/features/core/src/main/java/org/apache/karaf/features/internal/model/Features.java
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * 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.karaf.features.internal.model;
-
-import java.util.ArrayList;
-import java.util.List;
-import javax.xml.bind.annotation.XmlAccessType;
-import javax.xml.bind.annotation.XmlAccessorType;
-import javax.xml.bind.annotation.XmlAttribute;
-import javax.xml.bind.annotation.XmlRootElement;
-import javax.xml.bind.annotation.XmlSchemaType;
-import javax.xml.bind.annotation.XmlType;
-
-
-/**
- * 
- * Root element of Feature definition. It contains optional attribute which allow
- * name of repository. This name will be used in shell to display source repository
- * of given feature.
- *             
- * 
- * <p>Java class for featuresRoot complex type.
- * 
- * <p>The following schema fragment specifies the expected content contained within this class.
- * 
- * <pre>
- * &lt;complexType name="features">
- *   &lt;complexContent>
- *     &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
- *       &lt;sequence>
- *         &lt;element name="repository" type="{http://www.w3.org/2001/XMLSchema}anyURI" maxOccurs="unbounded" minOccurs="0"/>
- *         &lt;element name="feature" type="{http://karaf.apache.org/xmlns/features/v1.0.0}feature" maxOccurs="unbounded" minOccurs="0"/>
- *       &lt;/sequence>
- *       &lt;attribute name="name" type="{http://www.w3.org/2001/XMLSchema}string" />
- *     &lt;/restriction>
- *   &lt;/complexContent>
- * &lt;/complexType>
- * </pre>
- * 
- * 
- */
-@XmlRootElement(name = "features")
-@XmlAccessorType(XmlAccessType.FIELD)
-@XmlType(name = "features", propOrder = {
-    "repository",
-    "feature"
-})
-public class Features {
-
-    @XmlSchemaType(name = "anyURI")
-    protected List<String> repository;
-    protected List<Feature> feature;
-    @XmlAttribute
-    protected String name;
-
-    /**
-     * Gets the value of the repository property.
-     * 
-     * <p>
-     * This accessor method returns a reference to the live list,
-     * not a snapshot. Therefore any modification you make to the
-     * returned list will be present inside the JAXB object.
-     * This is why there is not a <CODE>set</CODE> method for the repository property.
-     * 
-     * <p>
-     * For example, to add a new item, do as follows:
-     * <pre>
-     *    getRepository().add(newItem);
-     * </pre>
-     * 
-     * 
-     * <p>
-     * Objects of the following type(s) are allowed in the list
-     * {@link String }
-     * 
-     * 
-     */
-    public List<String> getRepository() {
-        if (repository == null) {
-            repository = new ArrayList<String>();
-        }
-        return this.repository;
-    }
-
-    /**
-     * Gets the value of the feature property.
-     * 
-     * <p>
-     * This accessor method returns a reference to the live list,
-     * not a snapshot. Therefore any modification you make to the
-     * returned list will be present inside the JAXB object.
-     * This is why there is not a <CODE>set</CODE> method for the feature property.
-     * 
-     * <p>
-     * For example, to add a new item, do as follows:
-     * <pre>
-     *    getFeature().add(newItem);
-     * </pre>
-     * 
-     * 
-     * <p>
-     * Objects of the following type(s) are allowed in the list
-     * {@link Feature }
-     * 
-     * 
-     */
-    public List<Feature> getFeature() {
-        if (feature == null) {
-            feature = new ArrayList<Feature>();
-        }
-        return this.feature;
-    }
-
-    /**
-     * Gets the value of the name property.
-     * 
-     * @return
-     *     possible object is
-     *     {@link String }
-     *     
-     */
-    public String getName() {
-        return name;
-    }
-
-    /**
-     * Sets the value of the name property.
-     * 
-     * @param value
-     *     allowed object is
-     *     {@link String }
-     *     
-     */
-    public void setName(String value) {
-        this.name = value;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/core/src/main/java/org/apache/karaf/features/internal/model/JaxbUtil.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/model/JaxbUtil.java b/features/core/src/main/java/org/apache/karaf/features/internal/model/JaxbUtil.java
deleted file mode 100644
index 39c057a..0000000
--- a/features/core/src/main/java/org/apache/karaf/features/internal/model/JaxbUtil.java
+++ /dev/null
@@ -1,149 +0,0 @@
-/*
- * 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.karaf.features.internal.model;
-
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.Writer;
-import javax.xml.bind.JAXBContext;
-import javax.xml.bind.JAXBException;
-import javax.xml.bind.Marshaller;
-import javax.xml.bind.Unmarshaller;
-import javax.xml.bind.ValidationEvent;
-import javax.xml.bind.ValidationEventHandler;
-import javax.xml.parsers.ParserConfigurationException;
-import javax.xml.parsers.SAXParser;
-import javax.xml.parsers.SAXParserFactory;
-import javax.xml.stream.XMLInputFactory;
-import javax.xml.transform.sax.SAXSource;
-
-import org.apache.karaf.features.FeaturesNamespaces;
-import org.xml.sax.Attributes;
-import org.xml.sax.InputSource;
-import org.xml.sax.SAXException;
-import org.xml.sax.XMLFilter;
-import org.xml.sax.XMLReader;
-import org.xml.sax.helpers.XMLFilterImpl;
-
-public class JaxbUtil {
-
-    public static final XMLInputFactory XMLINPUT_FACTORY = XMLInputFactory.newInstance();
-    private static final JAXBContext FEATURES_CONTEXT;
-    static {
-        try {
-            FEATURES_CONTEXT = JAXBContext.newInstance(Features.class);
-        } catch (JAXBException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    public static void marshal(Features features, OutputStream out) throws JAXBException {
-        Marshaller marshaller = FEATURES_CONTEXT.createMarshaller();
-
-        marshaller.setProperty("jaxb.formatted.output", true);
-
-        marshaller.marshal(features, out);
-    }
-
-    public static void marshal(Features features, Writer out) throws JAXBException {
-        Marshaller marshaller = FEATURES_CONTEXT.createMarshaller();
-
-        marshaller.setProperty("jaxb.formatted.output", true);
-
-        marshaller.marshal(features, out);
-    }
-
-
-    /**
-     * Read in a Features from the input stream.
-     *
-     * @param in       input stream to read
-     * @param validate whether to validate the input.
-     * @return a Features read from the input stream
-     * @throws ParserConfigurationException is the SAX parser can not be configured
-     * @throws SAXException                 if there is an xml problem
-     * @throws JAXBException                if the xml cannot be marshalled into a T.
-     */
-    public static Features unmarshal(InputStream in, boolean validate) {
-        InputSource inputSource = new InputSource(in);
-
-        SAXParserFactory factory = SAXParserFactory.newInstance();
-        factory.setNamespaceAware(true);
-        factory.setValidating(validate);
-        SAXParser parser;
-        try {
-            parser = factory.newSAXParser();
-        
-
-        Unmarshaller unmarshaller = FEATURES_CONTEXT.createUnmarshaller();
-        unmarshaller.setEventHandler(new ValidationEventHandler() {
-            public boolean handleEvent(ValidationEvent validationEvent) {
-                System.out.println(validationEvent);
-                return false;
-            }
-        });
-
-        XMLFilter xmlFilter = new NoSourceAndNamespaceFilter(parser.getXMLReader());
-        xmlFilter.setContentHandler(unmarshaller.getUnmarshallerHandler());
-
-        SAXSource source = new SAXSource(xmlFilter, inputSource);
-
-        return (Features)unmarshaller.unmarshal(source);
-        
-        } catch (ParserConfigurationException e) {
-            throw new RuntimeException(e);
-        } catch (JAXBException e) {
-            throw new RuntimeException(e);
-        } catch (SAXException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    /**
-     * Provides an empty inputsource for the entity resolver.
-     * Converts all elements to the features namespace to make old feature files
-     * compatible to the new format
-     */
-    public static class NoSourceAndNamespaceFilter extends XMLFilterImpl {        
-        private static final InputSource EMPTY_INPUT_SOURCE = new InputSource(new ByteArrayInputStream(new byte[0]));
-
-        public NoSourceAndNamespaceFilter(XMLReader xmlReader) {
-            super(xmlReader);
-        }
-
-        @Override
-        public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException {
-            return EMPTY_INPUT_SOURCE;
-        }
-
-        @Override
-        public void startElement(String uri, String localName, String qName, Attributes atts) throws SAXException {
-            super.startElement(FeaturesNamespaces.URI_CURRENT, localName, qName, atts);
-        }
-
-        @Override
-        public void endElement(String uri, String localName, String qName) throws SAXException {
-            super.endElement(FeaturesNamespaces.URI_CURRENT, localName, qName);
-        }
-    }
-
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/core/src/main/java/org/apache/karaf/features/internal/model/ObjectFactory.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/model/ObjectFactory.java b/features/core/src/main/java/org/apache/karaf/features/internal/model/ObjectFactory.java
deleted file mode 100644
index 96fbb0f..0000000
--- a/features/core/src/main/java/org/apache/karaf/features/internal/model/ObjectFactory.java
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * 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.karaf.features.internal.model;
-
-import javax.xml.bind.JAXBElement;
-import javax.xml.bind.annotation.XmlElementDecl;
-import javax.xml.bind.annotation.XmlRegistry;
-import javax.xml.namespace.QName;
-
-
-/**
- * This object contains factory methods for each 
- * Java content interface and Java element interface 
- * generated in the org.apache.karaf.features.wrapper package.
- * <p>An ObjectFactory allows you to programatically 
- * construct new instances of the Java representation 
- * for XML content. The Java representation of XML 
- * content can consist of schema derived interfaces 
- * and classes representing the binding of schema 
- * type definitions, element declarations and model 
- * groups.  Factory methods for each of these are 
- * provided in this class.
- * 
- */
-@XmlRegistry
-public class ObjectFactory {
-
-    private final static QName _Features_QNAME = new QName("http://karaf.apache.org/xmlns/features/v1.0.0", "features");
-
-    /**
-     * Create a new ObjectFactory that can be used to create new instances of schema derived classes for package: org.apache.karaf.features.wrapper
-     * 
-     */
-    public ObjectFactory() {
-    }
-
-    /**
-     * Create an instance of {@link ConfigFile }
-     * 
-     */
-    public ConfigFile createConfigFile() {
-        return new ConfigFile();
-    }
-
-    /**
-     * Create an instance of {@link Dependency }
-     * 
-     */
-    public Dependency createDependency() {
-        return new Dependency();
-    }
-
-    /**
-     * Create an instance of {@link Bundle }
-     * 
-     */
-    public Bundle createBundle() {
-        return new Bundle();
-    }
-
-    /**
-     * Create an instance of {@link Features }
-     * 
-     */
-    public Features createFeaturesRoot() {
-        return new Features();
-    }
-
-    /**
-     * Create an instance of {@link Config }
-     * 
-     */
-    public Config createConfig() {
-        return new Config();
-    }
-
-    /**
-     * Create an instance of {@link Feature }
-     * 
-     */
-    public Feature createFeature() {
-        return new Feature();
-    }
-
-    /**
-     * Create an instance of {@link JAXBElement }{@code <}{@link Features }{@code >}}
-     * 
-     */
-    @XmlElementDecl(namespace = "http://karaf.apache.org/xmlns/features/v1.0.0", name = "features")
-    public JAXBElement<Features> createFeatures(Features value) {
-        return new JAXBElement<Features>(_Features_QNAME, Features.class, null, value);
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/core/src/main/java/org/apache/karaf/features/internal/model/Requirement.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/model/Requirement.java b/features/core/src/main/java/org/apache/karaf/features/internal/model/Requirement.java
deleted file mode 100644
index f7b5775..0000000
--- a/features/core/src/main/java/org/apache/karaf/features/internal/model/Requirement.java
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * 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.karaf.features.internal.model;
-
-import javax.xml.bind.annotation.XmlAccessType;
-import javax.xml.bind.annotation.XmlAccessorType;
-import javax.xml.bind.annotation.XmlType;
-import javax.xml.bind.annotation.XmlValue;
-
-
-/**
- * 
- * Additional requirement for a feature.
- *             
- * 
- * <p>Java class for bundle complex type.
- * 
- * <p>The following schema fragment specifies the expected content contained within this class.
- * 
- * <pre>
- * &lt;complexType name="capability">
- *   &lt;simpleContent>
- *     &lt;extension base="&lt;http://www.w3.org/2001/XMLSchema>string">
- *     &lt;/extension>
- *   &lt;/simpleContent>
- * &lt;/complexType>
- * </pre>
- * 
- * 
- */
-@XmlAccessorType(XmlAccessType.FIELD)
-@XmlType(name = "requirement", propOrder = {
-    "value"
-})
-public class Requirement implements org.apache.karaf.features.Requirement {
-
-    @XmlValue
-    protected String value;
-
-
-    public Requirement() {
-    }
-
-    public Requirement(String value) {
-        this.value = value;
-    }
-
-    public String getValue() {
-        return value;
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) return true;
-        if (o == null || getClass() != o.getClass()) return false;
-
-        Requirement bundle = (Requirement) o;
-
-        if (value != null ? !value.equals(bundle.value) : bundle.value != null) return false;
-
-        return true;
-    }
-
-    @Override
-    public int hashCode() {
-        int result = value != null ? value.hashCode() : 0;
-        return result;
-    }
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/core/src/main/java/org/apache/karaf/features/internal/model/package-info.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/model/package-info.java b/features/core/src/main/java/org/apache/karaf/features/internal/model/package-info.java
deleted file mode 100644
index c86a58c..0000000
--- a/features/core/src/main/java/org/apache/karaf/features/internal/model/package-info.java
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * 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.
- */
-
-@javax.xml.bind.annotation.XmlSchema(namespace = org.apache.karaf.features.FeaturesNamespaces.URI_CURRENT, elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED)
-package org.apache.karaf.features.internal.model;

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/core/src/main/java/org/apache/karaf/features/internal/osgi/Activator.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/osgi/Activator.java b/features/core/src/main/java/org/apache/karaf/features/internal/osgi/Activator.java
deleted file mode 100644
index be0da05..0000000
--- a/features/core/src/main/java/org/apache/karaf/features/internal/osgi/Activator.java
+++ /dev/null
@@ -1,208 +0,0 @@
-/*
- * 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.karaf.features.internal.osgi;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.FileReader;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.util.Dictionary;
-import java.util.Hashtable;
-import java.util.Properties;
-
-import org.apache.karaf.features.FeaturesListener;
-import org.apache.karaf.features.FeaturesService;
-import org.apache.karaf.features.internal.service.EventAdminListener;
-import org.apache.karaf.features.internal.service.FeatureConfigInstaller;
-import org.apache.karaf.features.internal.service.FeatureFinder;
-import org.apache.karaf.features.internal.service.BootFeaturesInstaller;
-import org.apache.karaf.features.internal.service.FeaturesServiceImpl;
-import org.apache.karaf.features.internal.service.StateStorage;
-import org.apache.karaf.features.internal.management.FeaturesServiceMBeanImpl;
-import org.apache.karaf.features.RegionsPersistence;
-import org.apache.karaf.util.tracker.BaseActivator;
-import org.apache.karaf.util.tracker.SingleServiceTracker;
-import org.osgi.framework.Constants;
-import org.osgi.framework.ServiceReference;
-import org.osgi.service.cm.ConfigurationAdmin;
-import org.osgi.service.cm.ManagedService;
-import org.osgi.service.url.URLStreamHandlerService;
-import org.osgi.util.tracker.ServiceTracker;
-import org.osgi.util.tracker.ServiceTrackerCustomizer;
-
-public class Activator extends BaseActivator {
-
-    public static final String FEATURES_REPOS_PID = "org.apache.karaf.features.repos";
-    public static final String FEATURES_SERVICE_CONFIG_FILE = "org.apache.karaf.features.cfg";
-
-    private ServiceTracker<FeaturesListener, FeaturesListener> featuresListenerTracker;
-    private FeaturesServiceImpl featuresService;
-    private SingleServiceTracker<RegionsPersistence> regionsTracker;
-
-    public Activator() {
-        // Special case here, as we don't want the activator to wait for current job to finish,
-        // else it would forbid the features service to refresh itself
-        setSchedulerStopTimeout(0);
-    }
-
-    @Override
-    protected void doOpen() throws Exception {
-        trackService(URLStreamHandlerService.class, "(url.handler.protocol=mvn)");
-        trackService(ConfigurationAdmin.class);
-
-        Properties configuration = new Properties();
-        File configFile = new File(System.getProperty("karaf.etc"), FEATURES_SERVICE_CONFIG_FILE);
-        if (configFile.isFile() && configFile.canRead()) {
-            try {
-                configuration.load(new FileReader(configFile));
-            } catch (IOException e) {
-                logger.warn("Error reading configuration file " + configFile.toString(), e);
-            }
-        }
-        updated((Dictionary) configuration);
-    }
-
-    protected void doStart() throws Exception {
-        ConfigurationAdmin configurationAdmin = getTrackedService(ConfigurationAdmin.class);
-        URLStreamHandlerService mvnUrlHandler = getTrackedService(URLStreamHandlerService.class);
-
-        if (configurationAdmin == null || mvnUrlHandler == null) {
-            return;
-        }
-
-        FeatureFinder featureFinder = new FeatureFinder();
-        Hashtable<String, Object> props = new Hashtable<String, Object>();
-        props.put(Constants.SERVICE_PID, FEATURES_REPOS_PID);
-        register(ManagedService.class, featureFinder, props);
-
-        // TODO: region support
-//        final BundleManager bundleManager = new BundleManager(bundleContext);
-//        regionsTracker = new SingleServiceTracker<RegionsPersistence>(bundleContext, RegionsPersistence.class,
-//                new SingleServiceTracker.SingleServiceListener() {
-//                    @Override
-//                    public void serviceFound() {
-//                        bundleManager.setRegionsPersistence(regionsTracker.getService());
-//                    }
-//                    @Override
-//                    public void serviceLost() {
-//                        serviceFound();
-//                    }
-//                    @Override
-//                    public void serviceReplaced() {
-//                        serviceFound();
-//                    }
-//                });
-//        regionsTracker.open();
-
-
-        FeatureConfigInstaller configInstaller = new FeatureConfigInstaller(configurationAdmin);
-        // TODO: honor respectStartLvlDuringFeatureStartup and respectStartLvlDuringFeatureUninstall
-//        boolean respectStartLvlDuringFeatureStartup = getBoolean("respectStartLvlDuringFeatureStartup", true);
-//        boolean respectStartLvlDuringFeatureUninstall = getBoolean("respectStartLvlDuringFeatureUninstall", true);
-        String overrides = getString("overrides", new File(System.getProperty("karaf.etc"), "overrides.properties").toURI().toString());
-        String featureResolutionRange = getString("featureResolutionRange", FeaturesServiceImpl.DEFAULT_FEATURE_RESOLUTION_RANGE);
-        String bundleUpdateRange = getString("bundleUpdateRange", FeaturesServiceImpl.DEFAULT_BUNDLE_UPDATE_RANGE);
-        String updateSnapshots = getString("updateSnapshots", FeaturesServiceImpl.DEFAULT_UPDATE_SNAPSHOTS);
-        StateStorage stateStorage = new StateStorage() {
-            @Override
-            protected InputStream getInputStream() throws IOException {
-                File file = bundleContext.getDataFile("FeaturesServiceState.properties");
-                if (file.exists()) {
-                    return new FileInputStream(file);
-                } else {
-                    return null;
-                }
-            }
-
-            @Override
-            protected OutputStream getOutputStream() throws IOException {
-                File file = bundleContext.getDataFile("FeaturesServiceState.properties");
-                return new FileOutputStream(file);
-            }
-        };
-        EventAdminListener eventAdminListener;
-        try {
-            eventAdminListener = new EventAdminListener(bundleContext);
-        } catch (Throwable t) {
-            eventAdminListener = null;
-        }
-        featuresService = new FeaturesServiceImpl(
-                                bundleContext.getBundle(),
-                                bundleContext.getBundle(0).getBundleContext(),
-                                stateStorage,
-                                featureFinder,
-                                eventAdminListener,
-                                configInstaller,
-                                overrides,
-                                featureResolutionRange,
-                                bundleUpdateRange,
-                                updateSnapshots);
-        register(FeaturesService.class, featuresService);
-
-        featuresListenerTracker = new ServiceTracker<FeaturesListener, FeaturesListener>(
-                bundleContext, FeaturesListener.class, new ServiceTrackerCustomizer<FeaturesListener, FeaturesListener>() {
-            @Override
-            public FeaturesListener addingService(ServiceReference<FeaturesListener> reference) {
-                FeaturesListener service = bundleContext.getService(reference);
-                featuresService.registerListener(service);
-                return service;
-            }
-            @Override
-            public void modifiedService(ServiceReference<FeaturesListener> reference, FeaturesListener service) {
-            }
-            @Override
-            public void removedService(ServiceReference<FeaturesListener> reference, FeaturesListener service) {
-                featuresService.unregisterListener(service);
-                bundleContext.ungetService(reference);
-            }
-        }
-        );
-        featuresListenerTracker.open();
-
-        String featuresRepositories = getString("featuresRepositories", "");
-        String featuresBoot = getString("featuresBoot", "");
-        boolean featuresBootAsynchronous = getBoolean("featuresBootAsynchronous", false);
-        BootFeaturesInstaller bootFeaturesInstaller = new BootFeaturesInstaller(
-                bundleContext, featuresService,
-                featuresRepositories, featuresBoot, featuresBootAsynchronous);
-        bootFeaturesInstaller.start();
-
-        FeaturesServiceMBeanImpl featuresServiceMBean = new FeaturesServiceMBeanImpl();
-        featuresServiceMBean.setBundleContext(bundleContext);
-        featuresServiceMBean.setFeaturesService(featuresService);
-        registerMBean(featuresServiceMBean, "type=feature");
-    }
-
-    protected void doStop() {
-        if (regionsTracker != null) {
-            regionsTracker.close();
-            regionsTracker = null;
-        }
-        if (featuresListenerTracker != null) {
-            featuresListenerTracker.close();
-            featuresListenerTracker = null;
-        }
-        super.doStop();
-        if (featuresService != null) {
-            featuresService = null;
-        }
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/core/src/main/java/org/apache/karaf/features/internal/repository/AggregateRepository.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/repository/AggregateRepository.java b/features/core/src/main/java/org/apache/karaf/features/internal/repository/AggregateRepository.java
deleted file mode 100644
index 0d5e83d..0000000
--- a/features/core/src/main/java/org/apache/karaf/features/internal/repository/AggregateRepository.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * 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.karaf.features.internal.repository;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import org.osgi.resource.Capability;
-import org.osgi.resource.Requirement;
-import org.osgi.service.repository.Repository;
-
-public class AggregateRepository implements Repository {
-
-    private final Collection<Repository> repositories;
-
-    public AggregateRepository(Collection<Repository> repositories) {
-        this.repositories = repositories;
-    }
-
-    @Override
-    public Map<Requirement, Collection<Capability>> findProviders(Collection<? extends Requirement> requirements) {
-        Map<Requirement, Collection<Capability>> result = new HashMap<Requirement, Collection<Capability>>();
-        for (Requirement requirement : requirements) {
-            List<Capability> caps = new ArrayList<Capability>();
-            for (Repository repository : repositories) {
-                Map<Requirement, Collection<Capability>> resMap =
-                        repository.findProviders(Collections.singleton(requirement));
-                Collection<Capability> res = resMap != null ? resMap.get(requirement) : null;
-                if (res != null) {
-                    caps.addAll(res);
-                }
-            }
-            result.put(requirement, caps);
-        }
-        return result;
-    }
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/core/src/main/java/org/apache/karaf/features/internal/repository/BaseRepository.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/repository/BaseRepository.java b/features/core/src/main/java/org/apache/karaf/features/internal/repository/BaseRepository.java
deleted file mode 100644
index c4c0d16..0000000
--- a/features/core/src/main/java/org/apache/karaf/features/internal/repository/BaseRepository.java
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * 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.karaf.features.internal.repository;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import org.apache.karaf.features.internal.resolver.CapabilitySet;
-import org.apache.karaf.features.internal.resolver.RequirementImpl;
-import org.apache.karaf.features.internal.resolver.SimpleFilter;
-import org.osgi.framework.Constants;
-import org.osgi.resource.Capability;
-import org.osgi.resource.Requirement;
-import org.osgi.resource.Resource;
-import org.osgi.service.repository.Repository;
-
-/**
- */
-public class BaseRepository implements Repository {
-
-    protected final List<Resource> resources;
-    protected final Map<String, CapabilitySet> capSets;
-
-    public BaseRepository() {
-        this.resources = new ArrayList<Resource>();
-        this.capSets = new HashMap<String, CapabilitySet>();
-    }
-
-    protected void addResource(Resource resource) {
-        for (Capability cap : resource.getCapabilities(null)) {
-            String ns = cap.getNamespace();
-            CapabilitySet set = capSets.get(ns);
-            if (set == null) {
-                set = new CapabilitySet(Collections.singletonList(ns));
-                capSets.put(ns, set);
-            }
-            set.addCapability(cap);
-        }
-        resources.add(resource);
-    }
-
-    public List<Resource> getResources() {
-        return resources;
-    }
-
-    @Override
-    public Map<Requirement, Collection<Capability>> findProviders(Collection<? extends Requirement> requirements) {
-        Map<Requirement, Collection<Capability>> result = new HashMap<Requirement, Collection<Capability>>();
-        for (Requirement requirement : requirements) {
-            CapabilitySet set = capSets.get(requirement.getNamespace());
-            if (set != null) {
-                SimpleFilter sf;
-                if (requirement instanceof RequirementImpl) {
-                    sf = ((RequirementImpl) requirement).getFilter();
-                } else {
-                    String filter = requirement.getDirectives().get(Constants.FILTER_DIRECTIVE);
-                    sf = (filter != null)
-                            ? SimpleFilter.parse(filter)
-                            : new SimpleFilter(null, null, SimpleFilter.MATCH_ALL);
-                }
-                result.put(requirement, set.match(sf, true));
-            } else {
-                result.put(requirement, Collections.<Capability>emptyList());
-            }
-        }
-        return result;
-    }
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/core/src/main/java/org/apache/karaf/features/internal/repository/CacheRepository.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/repository/CacheRepository.java b/features/core/src/main/java/org/apache/karaf/features/internal/repository/CacheRepository.java
deleted file mode 100644
index 7916821..0000000
--- a/features/core/src/main/java/org/apache/karaf/features/internal/repository/CacheRepository.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * 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.karaf.features.internal.repository;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-
-import org.osgi.resource.Capability;
-import org.osgi.resource.Requirement;
-import org.osgi.service.repository.Repository;
-
-public class CacheRepository implements Repository {
-
-    private final Repository repository;
-    private final Map<Requirement, Collection<Capability>> cache =
-            new ConcurrentHashMap<Requirement, Collection<Capability>>();
-
-    public CacheRepository(Repository repository) {
-        this.repository = repository;
-    }
-
-    @Override
-    public Map<Requirement, Collection<Capability>> findProviders(Collection<? extends Requirement> requirements) {
-        List<Requirement> missing = new ArrayList<Requirement>();
-        Map<Requirement, Collection<Capability>> result = new HashMap<Requirement, Collection<Capability>>();
-        for (Requirement requirement : requirements) {
-            Collection<Capability> caps = cache.get(requirement);
-            if (caps == null) {
-                missing.add(requirement);
-            } else {
-                result.put(requirement, caps);
-            }
-        }
-        Map<Requirement, Collection<Capability>> newCache = repository.findProviders(missing);
-        for (Requirement requirement : newCache.keySet()) {
-            cache.put(requirement, newCache.get(requirement));
-            result.put(requirement, newCache.get(requirement));
-        }
-        return result;
-    }
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/core/src/main/java/org/apache/karaf/features/internal/repository/HttpMetadataProvider.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/repository/HttpMetadataProvider.java b/features/core/src/main/java/org/apache/karaf/features/internal/repository/HttpMetadataProvider.java
deleted file mode 100644
index 1aecef1..0000000
--- a/features/core/src/main/java/org/apache/karaf/features/internal/repository/HttpMetadataProvider.java
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * 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.karaf.features.internal.repository;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.HttpURLConnection;
-import java.net.URL;
-import java.util.Map;
-import java.util.zip.GZIPInputStream;
-
-import org.apache.karaf.features.internal.util.JsonReader;
-
-/**
- */
-public class HttpMetadataProvider implements MetadataProvider {
-
-    public static final String HEADER_ACCEPT_ENCODING = "Accept-Encoding";
-    public static final String HEADER_CONTENT_ENCODING = "Content-Encoding";
-    public static final String GZIP = "gzip";
-
-    private final String url;
-    private long lastModified;
-    private Map<String, Map<String, String>> metadatas;
-
-    public HttpMetadataProvider(String url) {
-        this.url = url;
-    }
-
-    @Override
-    public long getLastModified() {
-        return lastModified;
-    }
-
-    @Override
-    public Map<String, Map<String, String>> getMetadatas() {
-        try {
-            HttpURLConnection.setFollowRedirects(false);
-            HttpURLConnection con = (HttpURLConnection) new URL(url).openConnection();
-            if (lastModified > 0) {
-                con.setIfModifiedSince(lastModified);
-            }
-            con.setRequestProperty(HEADER_ACCEPT_ENCODING, GZIP);
-            if (con.getResponseCode() == HttpURLConnection.HTTP_OK) {
-                lastModified = con.getLastModified();
-                InputStream is = con.getInputStream();
-                if (GZIP.equals(con.getHeaderField(HEADER_CONTENT_ENCODING))) {
-                    is = new GZIPInputStream(is);
-                }
-                metadatas = verify(JsonReader.read(is));
-            } else if (con.getResponseCode() != HttpURLConnection.HTTP_NOT_MODIFIED) {
-                throw new IOException("Unexpected http response: "
-                        + con.getResponseCode() + " " + con.getResponseMessage());
-            }
-            return metadatas;
-        } catch (IOException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    private Map<String, Map<String, String>> verify(Object value) {
-        Map<?,?> obj = Map.class.cast(value);
-        for (Map.Entry<?,?> entry : obj.entrySet()) {
-            String.class.cast(entry.getKey());
-            Map<?,?> child = Map.class.cast(entry.getValue());
-            for (Map.Entry<?,?> ce : child.entrySet()) {
-                String.class.cast(ce.getKey());
-                String.class.cast(ce.getValue());
-            }
-        }
-        return (Map<String, Map<String, String>>) obj;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/core/src/main/java/org/apache/karaf/features/internal/repository/MetadataProvider.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/repository/MetadataProvider.java b/features/core/src/main/java/org/apache/karaf/features/internal/repository/MetadataProvider.java
deleted file mode 100644
index 9ac54a1..0000000
--- a/features/core/src/main/java/org/apache/karaf/features/internal/repository/MetadataProvider.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * 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.karaf.features.internal.repository;
-
-import java.util.Map;
-
-/**
- */
-public interface MetadataProvider {
-
-    long getLastModified();
-
-    Map<String, Map<String, String>> getMetadatas();
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/core/src/main/java/org/apache/karaf/features/internal/repository/MetadataRepository.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/repository/MetadataRepository.java b/features/core/src/main/java/org/apache/karaf/features/internal/repository/MetadataRepository.java
deleted file mode 100644
index 2d4fbba..0000000
--- a/features/core/src/main/java/org/apache/karaf/features/internal/repository/MetadataRepository.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * 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.karaf.features.internal.repository;
-
-import java.util.Map;
-
-import org.apache.karaf.features.internal.resolver.ResourceBuilder;
-import org.osgi.resource.Resource;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- */
-public class MetadataRepository extends BaseRepository {
-
-    private static final Logger LOGGER = LoggerFactory.getLogger(MetadataRepository.class);
-
-    public MetadataRepository(MetadataProvider provider) {
-        Map<String, Map<String, String>> metadatas = provider.getMetadatas();
-        for (Map.Entry<String, Map<String, String>> metadata : metadatas.entrySet()) {
-            try {
-                Resource resource = ResourceBuilder.build(metadata.getKey(), metadata.getValue());
-                addResource(resource);
-            } catch (Exception e) {
-                LOGGER.info("Unable to build resource for " + metadata.getKey(), e);
-            }
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/core/src/main/java/org/apache/karaf/features/internal/repository/StaticRepository.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/repository/StaticRepository.java b/features/core/src/main/java/org/apache/karaf/features/internal/repository/StaticRepository.java
deleted file mode 100644
index f289c8d..0000000
--- a/features/core/src/main/java/org/apache/karaf/features/internal/repository/StaticRepository.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * 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.karaf.features.internal.repository;
-
-import java.util.Collection;
-
-import org.osgi.resource.Resource;
-
-/**
- */
-public class StaticRepository extends BaseRepository {
-
-    public StaticRepository(Collection<Resource> resources) {
-        for (Resource resource : resources) {
-            addResource(resource);
-        }
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/core/src/main/java/org/apache/karaf/features/internal/resolver/BaseClause.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/resolver/BaseClause.java b/features/core/src/main/java/org/apache/karaf/features/internal/resolver/BaseClause.java
deleted file mode 100644
index 0653398..0000000
--- a/features/core/src/main/java/org/apache/karaf/features/internal/resolver/BaseClause.java
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * 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.karaf.features.internal.resolver;
-
-import java.util.Map;
-
-import org.osgi.framework.Version;
-import org.osgi.resource.Resource;
-
-/**
- */
-public abstract class BaseClause {
-
-    public abstract Resource getResource();
-
-    public abstract String getNamespace();
-
-    public abstract Map<String, String> getDirectives();
-
-    public abstract Map<String, Object> getAttributes();
-
-    @Override
-    public String toString() {
-        return toString(getResource(), getNamespace(), getAttributes(), getDirectives());
-    }
-
-    public static String toString(Resource res, String namespace, Map<String, Object> attrs, Map<String, String> dirs) {
-        StringBuilder sb = new StringBuilder();
-        if (res != null) {
-            sb.append("[").append(res).append("] ");
-        }
-        sb.append(namespace);
-        for (String key : attrs.keySet()) {
-            sb.append("; ");
-            append(sb, key, attrs.get(key), true);
-        }
-        for (String key : dirs.keySet()) {
-            sb.append("; ");
-            append(sb, key, dirs.get(key), false);
-        }
-        return sb.toString();
-    }
-
-    private static void append(StringBuilder sb, String key, Object val, boolean attribute) {
-        sb.append(key);
-        if (val instanceof Version) {
-            sb.append(":Version=");
-            sb.append(val);
-        } else if (val instanceof Long) {
-            sb.append(":Long=");
-            sb.append(val);
-        } else if (val instanceof Double) {
-            sb.append(":Double=");
-            sb.append(val);
-        } else if (val instanceof Iterable) {
-            Iterable it = (Iterable) val;
-            String scalar = null;
-            for (Object o : it) {
-                String ts;
-                if (o instanceof String) {
-                    ts = "String";
-                } else if (o instanceof Long) {
-                    ts = "Long";
-                } else if (o instanceof Double) {
-                    ts = "Double";
-                } else if (o instanceof Version) {
-                    ts = "Version";
-                } else {
-                    throw new IllegalArgumentException("Unsupported scalar type: " + o);
-                }
-                if (scalar == null) {
-                    scalar = ts;
-                } else if (!scalar.equals(ts)) {
-                    throw new IllegalArgumentException("Unconsistent list type for attribute " + key);
-                }
-            }
-            sb.append(":List<").append(scalar).append(">=");
-            sb.append("\"");
-            boolean first = true;
-            for (Object o : it) {
-                if (first) {
-                    first = false;
-                } else {
-                    sb.append(",");
-                }
-                sb.append(o.toString().replace("\"", "\\\"").replace(",", "\\,"));
-            }
-            sb.append("\"");
-        } else {
-            sb.append(attribute ? "=" : ":=");
-            String s = val.toString();
-            if (s.matches("[0-9a-zA-Z_\\-.]*")) {
-                sb.append(s);
-            } else {
-                sb.append("\"").append(s.replace("\"", "\\\\")).append("\"");
-            }
-        }
-    }
-
-}


[17/59] [abbrv] git commit: [KARAF-2852] Merge features/core and features/command

Posted by gn...@apache.org.
[KARAF-2852] Merge features/core and features/command


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

Branch: refs/heads/master
Commit: 999f4970fecd3710da36b709f2d484cd0db38d09
Parents: 2c4e8da
Author: Guillaume Nodet <gn...@gmail.com>
Authored: Wed Apr 9 21:46:31 2014 +0200
Committer: Guillaume Nodet <gn...@gmail.com>
Committed: Thu Apr 10 15:59:05 2014 +0200

----------------------------------------------------------------------
 assemblies/apache-karaf-minimal/pom.xml         |    1 +
 assemblies/apache-karaf/pom.xml                 |    1 +
 .../standard/src/main/feature/feature.xml       |    1 -
 features/command/NOTICE                         |   71 -
 features/command/pom.xml                        |   90 --
 .../command/FeaturesCommandSupport.java         |   42 -
 .../features/command/InfoFeatureCommand.java    |  292 ----
 .../features/command/InstallFeatureCommand.java |   69 -
 .../command/ListFeatureVersionsCommand.java     |   62 -
 .../features/command/ListFeaturesCommand.java   |  106 --
 .../karaf/features/command/RepoAddCommand.java  |   54 -
 .../karaf/features/command/RepoListCommand.java |   71 -
 .../features/command/RepoRefreshCommand.java    |   65 -
 .../features/command/RepoRemoveCommand.java     |   56 -
 .../command/UninstallFeatureCommand.java        |   62 -
 .../command/completers/AllFeatureCompleter.java |   33 -
 .../completers/AvailableFeatureCompleter.java   |   33 -
 .../completers/AvailableRepoNameCompleter.java  |   48 -
 .../completers/FeatureCompleterSupport.java     |   65 -
 .../completers/InstalledRepoNameCompleter.java  |   58 -
 .../completers/InstalledRepoUriCompleter.java   |   59 -
 .../completers/RequiredFeatureCompleter.java    |   33 -
 .../src/main/resources/OSGI-INF/bundle.info     |   30 -
 features/core/NOTICE                            |   71 -
 features/core/pom.xml                           |  138 --
 .../org/apache/karaf/features/BootFinished.java |   24 -
 .../org/apache/karaf/features/BundleInfo.java   |   32 -
 .../org/apache/karaf/features/Capability.java   |   23 -
 .../org/apache/karaf/features/Conditional.java  |   35 -
 .../apache/karaf/features/ConfigFileInfo.java   |   27 -
 .../org/apache/karaf/features/Dependency.java   |   29 -
 .../apache/karaf/features/EventConstants.java   |   46 -
 .../java/org/apache/karaf/features/Feature.java |   63 -
 .../org/apache/karaf/features/FeatureEvent.java |   50 -
 .../apache/karaf/features/FeaturesListener.java |   25 -
 .../karaf/features/FeaturesNamespaces.java      |   41 -
 .../apache/karaf/features/FeaturesService.java  |  104 --
 .../karaf/features/RegionsPersistence.java      |   26 -
 .../org/apache/karaf/features/Repository.java   |   36 -
 .../apache/karaf/features/RepositoryEvent.java  |   50 -
 .../org/apache/karaf/features/Requirement.java  |   23 -
 .../org/apache/karaf/features/Resolver.java     |   25 -
 .../internal/deployment/DeploymentBuilder.java  |  334 ----
 .../internal/deployment/Downloader.java         |   35 -
 .../internal/deployment/StreamProvider.java     |   26 -
 .../management/FeaturesServiceMBeanImpl.java    |  290 ----
 .../management/StandardEmitterMBean.java        |   65 -
 .../karaf/features/internal/model/Bundle.java   |  198 ---
 .../features/internal/model/Capability.java     |   91 --
 .../features/internal/model/Conditional.java    |   71 -
 .../karaf/features/internal/model/Config.java   |  110 --
 .../features/internal/model/ConfigFile.java     |  136 --
 .../karaf/features/internal/model/Content.java  |  199 ---
 .../features/internal/model/Dependency.java     |  121 --
 .../karaf/features/internal/model/Feature.java  |  374 -----
 .../karaf/features/internal/model/Features.java |  155 --
 .../karaf/features/internal/model/JaxbUtil.java |  149 --
 .../features/internal/model/ObjectFactory.java  |  111 --
 .../features/internal/model/Requirement.java    |   87 --
 .../features/internal/model/package-info.java   |   21 -
 .../karaf/features/internal/osgi/Activator.java |  208 ---
 .../repository/AggregateRepository.java         |   55 -
 .../internal/repository/BaseRepository.java     |   86 --
 .../internal/repository/CacheRepository.java    |   59 -
 .../repository/HttpMetadataProvider.java        |   88 --
 .../internal/repository/MetadataProvider.java   |   29 -
 .../internal/repository/MetadataRepository.java |   43 -
 .../internal/repository/StaticRepository.java   |   33 -
 .../features/internal/resolver/BaseClause.java  |  114 --
 .../internal/resolver/CandidateComparator.java  |  129 --
 .../internal/resolver/CapabilityImpl.java       |  165 --
 .../internal/resolver/CapabilitySet.java        |  612 --------
 .../internal/resolver/FeatureNamespace.java     |   72 -
 .../internal/resolver/FeatureResource.java      |  121 --
 .../internal/resolver/IdentityCapability.java   |   63 -
 .../internal/resolver/RequirementImpl.java      |   80 -
 .../internal/resolver/ResolveContextImpl.java   |  102 --
 .../internal/resolver/ResourceBuilder.java      | 1129 --------------
 .../internal/resolver/ResourceImpl.java         |  110 --
 .../internal/resolver/ServiceNamespace.java     |   30 -
 .../internal/resolver/SimpleFilter.java         |  649 --------
 .../internal/resolver/Slf4jResolverLog.java     |   49 -
 .../internal/resolver/UriNamespace.java         |   47 -
 .../features/internal/service/Artifact.java     |   56 -
 .../internal/service/BootFeaturesInstaller.java |  171 --
 .../internal/service/EventAdminListener.java    |   91 --
 .../service/FeatureConfigInstaller.java         |  167 --
 .../internal/service/FeatureFinder.java         |   68 -
 .../internal/service/FeatureValidationUtil.java |  113 --
 .../internal/service/FeaturesServiceImpl.java   | 1454 -----------------
 .../features/internal/service/Overrides.java    |  132 --
 .../internal/service/RepositoryImpl.java        |  103 --
 .../internal/service/RequirementSort.java       |  107 --
 .../internal/service/SimpleDownloader.java      |   51 -
 .../karaf/features/internal/service/State.java  |   34 -
 .../features/internal/service/StateStorage.java |  175 ---
 .../features/internal/util/ChecksumUtils.java   |   56 -
 .../features/internal/util/JsonReader.java      |  349 -----
 .../features/internal/util/JsonWriter.java      |  120 --
 .../karaf/features/internal/util/Macro.java     |  142 --
 .../features/internal/util/MultiException.java  |   95 --
 .../management/FeaturesServiceMBean.java        |  142 --
 .../features/management/codec/JmxFeature.java   |  323 ----
 .../management/codec/JmxFeatureEvent.java       |   80 -
 .../management/codec/JmxRepository.java         |  132 --
 .../management/codec/JmxRepositoryEvent.java    |   77 -
 .../src/main/resources/OSGI-INF/bundle.info     |   20 -
 .../karaf/features/karaf-features-1.0.0.xsd     |  239 ---
 .../karaf/features/karaf-features-1.1.0.xsd     |  237 ---
 .../karaf/features/karaf-features-1.2.0.xsd     |  254 ---
 .../karaf/features/karaf-features-1.3.0.xsd     |  280 ----
 .../apache/karaf/features/ConditionalTest.java  |   47 -
 .../org/apache/karaf/features/FeatureTest.java  |   32 -
 .../karaf/features/FeaturesServiceTest.java     |  430 ------
 .../apache/karaf/features/RepositoryTest.java   |  140 --
 .../org/apache/karaf/features/TestBase.java     |  105 --
 .../service/BootFeaturesInstallerTest.java      |   93 --
 .../internal/service/BundleManagerTest.java     |   64 -
 .../service/FeaturesServiceImplTest.java        |  167 --
 .../service/FeaturesValidationTest.java         |   65 -
 .../internal/service/OverridesTest.java         |  208 ---
 .../karaf/features/internal/service/f01.xml     |   92 --
 .../karaf/features/internal/service/f02.xml     |  164 --
 .../karaf/features/internal/service/f03.xml     |   27 -
 .../karaf/features/internal/service/f04.xml     |   28 -
 .../karaf/features/internal/service/f05.xml     |   28 -
 .../karaf/features/internal/service/f06.xml     |   32 -
 .../karaf/features/internal/service/f07.xml     |   35 -
 .../internal/service/overrides.properties       |   23 -
 .../karaf/features/internal/service/repo2.xml   |   41 -
 .../org/apache/karaf/features/repo1.xml         |   35 -
 .../org/apache/karaf/features/repo2.xml         |   37 -
 .../org/apache/karaf/features/repo3.xml         |   27 -
 features/pom.xml                                |  123 +-
 .../org/apache/karaf/features/BootFinished.java |   24 +
 .../org/apache/karaf/features/BundleInfo.java   |   32 +
 .../org/apache/karaf/features/Capability.java   |   23 +
 .../org/apache/karaf/features/Conditional.java  |   35 +
 .../apache/karaf/features/ConfigFileInfo.java   |   27 +
 .../org/apache/karaf/features/Dependency.java   |   29 +
 .../apache/karaf/features/EventConstants.java   |   46 +
 .../java/org/apache/karaf/features/Feature.java |   63 +
 .../org/apache/karaf/features/FeatureEvent.java |   50 +
 .../apache/karaf/features/FeaturesListener.java |   25 +
 .../karaf/features/FeaturesNamespaces.java      |   41 +
 .../apache/karaf/features/FeaturesService.java  |  104 ++
 .../karaf/features/RegionsPersistence.java      |   26 +
 .../org/apache/karaf/features/Repository.java   |   36 +
 .../apache/karaf/features/RepositoryEvent.java  |   50 +
 .../org/apache/karaf/features/Requirement.java  |   23 +
 .../org/apache/karaf/features/Resolver.java     |   25 +
 .../command/FeaturesCommandSupport.java         |   42 +
 .../features/command/InfoFeatureCommand.java    |  292 ++++
 .../features/command/InstallFeatureCommand.java |   69 +
 .../command/ListFeatureVersionsCommand.java     |   62 +
 .../features/command/ListFeaturesCommand.java   |  106 ++
 .../karaf/features/command/RepoAddCommand.java  |   54 +
 .../karaf/features/command/RepoListCommand.java |   71 +
 .../features/command/RepoRefreshCommand.java    |   65 +
 .../features/command/RepoRemoveCommand.java     |   56 +
 .../command/UninstallFeatureCommand.java        |   62 +
 .../command/completers/AllFeatureCompleter.java |   33 +
 .../completers/AvailableFeatureCompleter.java   |   33 +
 .../completers/AvailableRepoNameCompleter.java  |   48 +
 .../completers/FeatureCompleterSupport.java     |   65 +
 .../completers/InstalledRepoNameCompleter.java  |   58 +
 .../completers/InstalledRepoUriCompleter.java   |   59 +
 .../completers/RequiredFeatureCompleter.java    |   33 +
 .../internal/deployment/DeploymentBuilder.java  |  334 ++++
 .../internal/deployment/Downloader.java         |   35 +
 .../internal/deployment/StreamProvider.java     |   26 +
 .../management/FeaturesServiceMBeanImpl.java    |  290 ++++
 .../management/StandardEmitterMBean.java        |   65 +
 .../karaf/features/internal/model/Bundle.java   |  198 +++
 .../features/internal/model/Capability.java     |   89 ++
 .../features/internal/model/Conditional.java    |   71 +
 .../karaf/features/internal/model/Config.java   |  110 ++
 .../features/internal/model/ConfigFile.java     |  136 ++
 .../karaf/features/internal/model/Content.java  |  199 +++
 .../features/internal/model/Dependency.java     |  121 ++
 .../karaf/features/internal/model/Feature.java  |  374 +++++
 .../karaf/features/internal/model/Features.java |  155 ++
 .../karaf/features/internal/model/JaxbUtil.java |  149 ++
 .../features/internal/model/ObjectFactory.java  |  111 ++
 .../features/internal/model/Requirement.java    |   87 ++
 .../features/internal/model/package-info.java   |   21 +
 .../karaf/features/internal/osgi/Activator.java |  208 +++
 .../repository/AggregateRepository.java         |   55 +
 .../internal/repository/BaseRepository.java     |   86 ++
 .../internal/repository/CacheRepository.java    |   59 +
 .../repository/HttpMetadataProvider.java        |   88 ++
 .../internal/repository/MetadataProvider.java   |   29 +
 .../internal/repository/MetadataRepository.java |   43 +
 .../internal/repository/StaticRepository.java   |   33 +
 .../features/internal/resolver/BaseClause.java  |  114 ++
 .../internal/resolver/CandidateComparator.java  |  129 ++
 .../internal/resolver/CapabilityImpl.java       |  165 ++
 .../internal/resolver/CapabilitySet.java        |  612 ++++++++
 .../internal/resolver/FeatureNamespace.java     |   72 +
 .../internal/resolver/FeatureResource.java      |  121 ++
 .../internal/resolver/IdentityCapability.java   |   63 +
 .../internal/resolver/RequirementImpl.java      |   80 +
 .../internal/resolver/ResolveContextImpl.java   |  102 ++
 .../internal/resolver/ResourceBuilder.java      | 1129 ++++++++++++++
 .../internal/resolver/ResourceImpl.java         |  110 ++
 .../internal/resolver/ServiceNamespace.java     |   30 +
 .../internal/resolver/SimpleFilter.java         |  649 ++++++++
 .../internal/resolver/Slf4jResolverLog.java     |   49 +
 .../internal/resolver/UriNamespace.java         |   47 +
 .../features/internal/service/Artifact.java     |   56 +
 .../internal/service/BootFeaturesInstaller.java |  170 ++
 .../internal/service/EventAdminListener.java    |   91 ++
 .../service/FeatureConfigInstaller.java         |  167 ++
 .../internal/service/FeatureFinder.java         |   68 +
 .../internal/service/FeatureValidationUtil.java |  113 ++
 .../internal/service/FeaturesServiceImpl.java   | 1455 ++++++++++++++++++
 .../features/internal/service/Overrides.java    |  132 ++
 .../internal/service/RepositoryImpl.java        |  103 ++
 .../internal/service/RequirementSort.java       |  107 ++
 .../internal/service/SimpleDownloader.java      |   51 +
 .../karaf/features/internal/service/State.java  |   34 +
 .../features/internal/service/StateStorage.java |  174 +++
 .../features/internal/util/ChecksumUtils.java   |   56 +
 .../features/internal/util/JsonReader.java      |  349 +++++
 .../features/internal/util/JsonWriter.java      |  120 ++
 .../karaf/features/internal/util/Macro.java     |  142 ++
 .../features/internal/util/MultiException.java  |   95 ++
 .../management/FeaturesServiceMBean.java        |  142 ++
 .../features/management/codec/JmxFeature.java   |  323 ++++
 .../management/codec/JmxFeatureEvent.java       |   80 +
 .../management/codec/JmxRepository.java         |  132 ++
 .../management/codec/JmxRepositoryEvent.java    |   77 +
 .../src/main/resources/OSGI-INF/bundle.info     |   20 +
 .../karaf/features/karaf-features-1.0.0.xsd     |  239 +++
 .../karaf/features/karaf-features-1.1.0.xsd     |  237 +++
 .../karaf/features/karaf-features-1.2.0.xsd     |  254 +++
 .../karaf/features/karaf-features-1.3.0.xsd     |  280 ++++
 .../apache/karaf/features/ConditionalTest.java  |   47 +
 .../org/apache/karaf/features/FeatureTest.java  |   32 +
 .../karaf/features/FeaturesServiceTest.java     |  429 ++++++
 .../apache/karaf/features/RepositoryTest.java   |  140 ++
 .../org/apache/karaf/features/TestBase.java     |  105 ++
 .../service/BootFeaturesInstallerTest.java      |   93 ++
 .../internal/service/BundleManagerTest.java     |   64 +
 .../service/FeaturesServiceImplTest.java        |  167 ++
 .../service/FeaturesValidationTest.java         |   65 +
 .../internal/service/OverridesTest.java         |  202 +++
 .../karaf/features/internal/service/f01.xml     |   92 ++
 .../karaf/features/internal/service/f02.xml     |  164 ++
 .../karaf/features/internal/service/f03.xml     |   27 +
 .../karaf/features/internal/service/f04.xml     |   28 +
 .../karaf/features/internal/service/f05.xml     |   28 +
 .../karaf/features/internal/service/f06.xml     |   32 +
 .../karaf/features/internal/service/f07.xml     |   35 +
 .../internal/service/overrides.properties       |   23 +
 .../karaf/features/internal/service/repo2.xml   |   41 +
 .../org/apache/karaf/features/repo1.xml         |   35 +
 .../org/apache/karaf/features/repo2.xml         |   37 +
 .../org/apache/karaf/features/repo3.xml         |   27 +
 259 files changed, 15808 insertions(+), 16110 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/assemblies/apache-karaf-minimal/pom.xml
----------------------------------------------------------------------
diff --git a/assemblies/apache-karaf-minimal/pom.xml b/assemblies/apache-karaf-minimal/pom.xml
index 63c174e..385d3bd 100644
--- a/assemblies/apache-karaf-minimal/pom.xml
+++ b/assemblies/apache-karaf-minimal/pom.xml
@@ -116,6 +116,7 @@
                     </installedFeatures>
                     <bootFeatures>
                         <feature>jaas</feature>
+                        <feature>shell</feature>
                         <feature>ssh</feature>
                         <feature>management</feature>
                         <feature>bundle</feature>

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/assemblies/apache-karaf/pom.xml
----------------------------------------------------------------------
diff --git a/assemblies/apache-karaf/pom.xml b/assemblies/apache-karaf/pom.xml
index efc0acf..ce631b8 100644
--- a/assemblies/apache-karaf/pom.xml
+++ b/assemblies/apache-karaf/pom.xml
@@ -162,6 +162,7 @@
                     <bootFeatures>
                         <feature>aries-blueprint</feature>
                         <feature>shell-compat</feature>
+                        <feature>shell</feature>
                         <feature>jaas</feature>
                         <feature>ssh</feature>
                         <feature>management</feature>

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/assemblies/features/standard/src/main/feature/feature.xml
----------------------------------------------------------------------
diff --git a/assemblies/features/standard/src/main/feature/feature.xml b/assemblies/features/standard/src/main/feature/feature.xml
index 49028d2..fde555c 100644
--- a/assemblies/features/standard/src/main/feature/feature.xml
+++ b/assemblies/features/standard/src/main/feature/feature.xml
@@ -73,7 +73,6 @@
         <bundle dependency="true" start-level="30">mvn:org.jledit/core/${jledit.version}</bundle>
         <bundle start-level="30">mvn:org.apache.karaf.shell/org.apache.karaf.shell.core/${project.version}</bundle>
         <bundle start-level="30">mvn:org.apache.karaf.shell/org.apache.karaf.shell.commands/${project.version}</bundle>
-        <bundle start-level="30">mvn:org.apache.karaf.features/org.apache.karaf.features.command/${project.version}</bundle>
     </feature>
 
     <feature name="shell-compat" description="Karaf Shell Compatibility" version="${project.version}">

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/command/NOTICE
----------------------------------------------------------------------
diff --git a/features/command/NOTICE b/features/command/NOTICE
deleted file mode 100644
index b70f1f9..0000000
--- a/features/command/NOTICE
+++ /dev/null
@@ -1,71 +0,0 @@
-Apache Karaf
-Copyright 2010-2014 The Apache Software Foundation
-
-
-I. Included Software
-
-This product includes software developed at
-The Apache Software Foundation (http://www.apache.org/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-The OSGi Alliance (http://www.osgi.org/).
-Copyright (c) OSGi Alliance (2000, 2010).
-Licensed under the Apache License 2.0.
-
-This product includes software developed at
-OW2 (http://www.ow2.org/).
-Licensed under the BSD License.
-
-This product includes software developed at
-OPS4J (http://www.ops4j.org/).
-Licensed under the Apache License 2.0.
-
-This product includes software developed at
-Eclipse Foundation (http://www.eclipse.org/).
-Licensed under the EPL.
-
-This product includes software written by
-Antony Lesuisse.
-Licensed under Public Domain.
-
-
-II. Used Software
-
-This product uses software developed at
-FUSE Source (http://www.fusesource.org/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-AOP Alliance (http://aopalliance.sourceforge.net/).
-Licensed under the Public Domain.
-
-This product uses software developed at
-Tanuki Software (http://www.tanukisoftware.com/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-Jasypt (http://jasypt.sourceforge.net/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-JLine (http://jline.sourceforge.net).
-Licensed under the BSD License.
-
-This product uses software developed at
-SLF4J (http://www.slf4j.org/).
-Licensed under the MIT License.
-
-This product uses software developed at
-SpringSource (http://www.springsource.org/).
-Licensed under the Apache License 2.0.
-
-This product includes software from http://www.json.org.
-Copyright (c) 2002 JSON.org
-
-
-III. License Summary
-- Apache License 2.0
-- BSD License
-- EPL License
-- MIT License

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/command/pom.xml
----------------------------------------------------------------------
diff --git a/features/command/pom.xml b/features/command/pom.xml
deleted file mode 100644
index 4f49bb1..0000000
--- a/features/command/pom.xml
+++ /dev/null
@@ -1,90 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-
-    <!--
-
-        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.
-    -->
-
-    <modelVersion>4.0.0</modelVersion>
-
-    <parent>
-        <groupId>org.apache.karaf.features</groupId>
-        <artifactId>features</artifactId>
-        <version>4.0.0-SNAPSHOT</version>
-        <relativePath>../pom.xml</relativePath>
-    </parent>
-
-    <artifactId>org.apache.karaf.features.command</artifactId>
-    <packaging>bundle</packaging>
-    <name>Apache Karaf :: Features :: Command</name>
-    <description>This bundle provides the Karaf shell commands to manipulate features.</description>
-
-    <properties>
-        <appendedResourcesDirectory>${basedir}/../../etc/appended-resources</appendedResourcesDirectory>
-    </properties>
-
-    <dependencies>
-        <dependency>
-            <groupId>org.osgi</groupId>
-            <artifactId>org.osgi.core</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.osgi</groupId>
-            <artifactId>org.osgi.compendium</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.karaf.features</groupId>
-            <artifactId>org.apache.karaf.features.core</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.karaf.shell</groupId>
-            <artifactId>org.apache.karaf.shell.core</artifactId>
-        </dependency>
-    </dependencies>
-
-    <build>
-        <resources>
-            <resource>
-                <directory>${project.basedir}/src/main/resources</directory>
-                <includes>
-                    <include>**/*</include>
-                </includes>
-            </resource>
-            <resource>
-                <directory>${project.basedir}/src/main/resources</directory>
-                <filtering>true</filtering>
-                <includes>
-                    <include>**/*.info</include>
-                </includes>
-            </resource>
-        </resources>
-        <plugins>
-            <plugin>
-                <groupId>org.apache.felix</groupId>
-                <artifactId>maven-bundle-plugin</artifactId>
-                <configuration>
-                    <instructions>
-                        <Karaf-Commands>org.apache.karaf.features.command.*</Karaf-Commands>
-                    </instructions>
-                </configuration>
-            </plugin>
-        </plugins>
-    </build>
-
-</project>

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/command/src/main/java/org/apache/karaf/features/command/FeaturesCommandSupport.java
----------------------------------------------------------------------
diff --git a/features/command/src/main/java/org/apache/karaf/features/command/FeaturesCommandSupport.java b/features/command/src/main/java/org/apache/karaf/features/command/FeaturesCommandSupport.java
deleted file mode 100644
index 076650d..0000000
--- a/features/command/src/main/java/org/apache/karaf/features/command/FeaturesCommandSupport.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * 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.karaf.features.command;
-
-import org.apache.karaf.features.FeaturesService;
-import org.apache.karaf.shell.api.action.Action;
-import org.apache.karaf.shell.api.action.lifecycle.Reference;
-
-public abstract class FeaturesCommandSupport implements Action {
-
-    @Reference
-    private FeaturesService featuresService;
-
-    @Override
-    public Object execute() throws Exception {
-        if (featuresService == null) {
-            throw new IllegalStateException("FeaturesService not found");
-        }
-        doExecute(featuresService);
-        return null;
-    }
-
-    protected abstract void doExecute(FeaturesService admin) throws Exception;
-
-    public void setFeaturesService(FeaturesService featuresService) {
-        this.featuresService = featuresService;
-    }
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/command/src/main/java/org/apache/karaf/features/command/InfoFeatureCommand.java
----------------------------------------------------------------------
diff --git a/features/command/src/main/java/org/apache/karaf/features/command/InfoFeatureCommand.java b/features/command/src/main/java/org/apache/karaf/features/command/InfoFeatureCommand.java
deleted file mode 100644
index 7084a6e..0000000
--- a/features/command/src/main/java/org/apache/karaf/features/command/InfoFeatureCommand.java
+++ /dev/null
@@ -1,292 +0,0 @@
-/*
- * 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.karaf.features.command;
-
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-
-import org.apache.karaf.features.BundleInfo;
-import org.apache.karaf.features.Conditional;
-import org.apache.karaf.features.ConfigFileInfo;
-import org.apache.karaf.features.Dependency;
-import org.apache.karaf.features.Feature;
-import org.apache.karaf.features.FeaturesService;
-import org.apache.karaf.features.command.completers.AllFeatureCompleter;
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Completion;
-import org.apache.karaf.shell.api.action.Option;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-
-@Command(scope = "feature", name = "info", description = "Shows information about selected feature.")
-@Service
-public class InfoFeatureCommand extends FeaturesCommandSupport {
-
-    private static final String INDENT = "  ";
-    private static final String FEATURE_CONTENT = "Feature";
-    private static final String CONDITIONAL_CONTENT = "Conditional(%s)";
-
-	@Argument(index = 0, name = "name", description = "The name of the feature", required = true, multiValued = false)
-    @Completion(AllFeatureCompleter.class)
-    private String name;
-
-    @Argument(index = 1, name = "version", description = "The version of the feature", required = false, multiValued = false)
-    private String version;
-
-    @Option(name = "-c", aliases={"--configuration"}, description="Display configuration info", required = false, multiValued = false)
-    private boolean config;
-
-    @Option(name = "-d", aliases={"--dependency"}, description="Display dependencies info", required = false, multiValued = false)
-    private boolean dependency;
-
-    @Option(name = "-b", aliases={"--bundle"}, description="Display bundles info", required = false, multiValued = false)
-    private boolean bundle;
-
-    @Option(name = "--conditional", description="Display conditional info", required = false, multiValued = false)
-    private boolean conditional;
-
-    @Option(name = "-t", aliases={"--tree"}, description="Display feature tree", required = false, multiValued = false)
-    private boolean tree;
-
-    protected void doExecute(FeaturesService admin) throws Exception {
-        Feature feature = null;
-
-        if (version != null && version.length() > 0) {
-            feature = admin.getFeature(name, version);
-        } else {
-            feature = admin.getFeature(name);
-        }
-
-        if (feature == null) {
-            System.out.println("Feature not found");
-            return;
-        }
-
-        // default behavior
-        if (!config && !dependency && !bundle && !conditional) {
-            config = true;
-            dependency = true;
-            bundle = true;
-            conditional = true;
-        }
-
-        System.out.println("Feature " + feature.getName() + " " + feature.getVersion());
-        if (feature.getDescription() != null) {
-        	System.out.println("Description:");
-        	System.out.println(INDENT + feature.getDescription());
-        }
-        
-        if(feature.getDetails() != null) {
-        	System.out.println("Details:");
-        	printWithIndent(feature.getDetails());
-        }
-
-        if (config) {
-            displayConfigInformation(feature, FEATURE_CONTENT);
-            displayConfigFileInformation(feature, FEATURE_CONTENT);
-        }
-
-        if (dependency) {
-            displayDependencyInformation(feature, FEATURE_CONTENT);
-        }
-
-        if (bundle) {
-            displayBundleInformation(feature, FEATURE_CONTENT);
-        }
-
-        if(conditional) {
-           displayConditionalInfo(feature);
-        }
-
-        if (tree) {
-            if (config || dependency || bundle) {
-                System.out.println("\nFeature tree");
-            }
-
-            int unresolved = displayFeatureTree(admin, feature.getName(), feature.getVersion(), "");
-            if (unresolved > 0) {
-                System.out.println("Tree contains " + unresolved + " unresolved dependencies");
-                System.out.println(" * means that node declares dependency but the dependent feature is not available.");
-            }
-        }
-    }
-
-    private void printWithIndent(String details) {
-    	String[] lines = details.split("\r?\n");
-    	for (String line : lines) {
-			System.out.println(INDENT + line);
-		}
-	}
-
-	private void displayBundleInformation(Feature feature, String contentType) {
-        List<BundleInfo> bundleInfos = feature.getBundles();
-        if (bundleInfos.isEmpty()) {
-            System.out.println(contentType + " has no bundles.");
-        } else {
-            System.out.println(contentType + " contains followed bundles:");
-            for (BundleInfo featureBundle : bundleInfos) {
-                int startLevel = featureBundle.getStartLevel();
-                StringBuilder sb = new StringBuilder();
-                sb.append(INDENT).append(featureBundle.getLocation());
-                if(startLevel > 0) {
-                    sb.append(" start-level=").append(startLevel);
-                }
-                System.out.println(sb.toString());
-            }
-        }
-    }
-
-    private void displayDependencyInformation(Feature feature, String contentType) {
-        List<Dependency> dependencies = feature.getDependencies();
-        if (dependencies.isEmpty()) {
-            System.out.println(contentType + " has no dependencies.");
-        } else {
-            System.out.println(contentType + " depends on:");
-            for (Dependency featureDependency : dependencies) {
-                System.out.println(INDENT + featureDependency.getName() + " " + featureDependency.getVersion());
-            }
-        }
-    }
-
-    private void displayConfigInformation(Feature feature, String contentType) {
-        Map<String, Map<String, String>> configurations = feature.getConfigurations();
-        if (configurations.isEmpty()) {
-            System.out.println(contentType + " has no configuration");
-        } else {
-            System.out.println(contentType + " configuration:");
-            for (String name : configurations.keySet()) {
-                System.out.println(INDENT + name);
-            }
-        }
-    }
-    
-    private void displayConfigFileInformation(Feature feature, String contentType) {
-    	List<ConfigFileInfo> configurationFiles = feature.getConfigurationFiles();
-    	if (configurationFiles.isEmpty()) {
-    		System.out.println(contentType + " has no configuration files");
-    	} else {
-    		System.out.println(contentType + " configuration files: ");
-    		for (ConfigFileInfo configFileInfo : configurationFiles) {
-				System.out.println(INDENT + configFileInfo.getFinalname());
-			}
-    	}    	
-    }
-
-    /**
-     * Called originally with featureName and featureVersion that have already been resolved successfully.
-     *
-     * @param admin
-     * @param featureName
-     * @param featureVersion
-     * @param prefix
-     * @return
-     * @throws Exception
-     */
-    private int displayFeatureTree(FeaturesService admin, String featureName, String featureVersion, String prefix) throws Exception {
-        int unresolved = 0;
-
-        Feature resolved = admin.getFeature(featureName, featureVersion);
-        if (resolved != null) {
-            System.out.println(prefix + " " + resolved.getName() + " " + resolved.getVersion());
-        } else {
-            System.out.println(prefix + " " + featureName + " " + featureVersion + " *");
-            unresolved++;
-        }
-
-        if (resolved != null) {
-            if (bundle) {
-                List<String> bundleLocation = new LinkedList<String>();
-                List<BundleInfo> bundles = resolved.getBundles();
-                for (BundleInfo bundleInfo : bundles) {
-                    bundleLocation.add(bundleInfo.getLocation());
-                }
-
-                if (conditional) {
-                    for (Conditional cond : resolved.getConditional()) {
-                        List<? extends Dependency> condition = cond.getCondition();
-                        List<BundleInfo> conditionalBundles = cond.getBundles();
-                        for (BundleInfo bundleInfo : conditionalBundles) {
-                            bundleLocation.add(bundleInfo.getLocation() + "(condition:"+condition+")");
-                        }
-                    }
-                }
-                for (int i = 0, j = bundleLocation.size(); i < j; i++) {
-                    System.out.println(prefix + " " + (i + 1 == j ? "\\" : "+") + " " + bundleLocation.get(i));
-                }
-            }
-            prefix += "   ";
-            List<Dependency> dependencies = resolved.getDependencies();
-            for (int i = 0, j = dependencies.size(); i < j; i++) {
-                Dependency toDisplay =  dependencies.get(i);
-                unresolved += displayFeatureTree(admin, toDisplay.getName(), toDisplay.getVersion(), prefix +1);
-            }
-
-            if (conditional) {
-                for (Conditional cond : resolved.getConditional()) {
-                    List<Dependency> conditionDependencies = cond.getDependencies();
-                    for (int i = 0, j = conditionDependencies.size(); i < j; i++) {
-                        Dependency toDisplay =  dependencies.get(i);
-                        unresolved += displayFeatureTree(admin, toDisplay.getName(), toDisplay.getVersion(), prefix +1);
-                    }
-                }
-            }
-        }
-
-        return unresolved;
-    }
-
-    private void displayConditionalInfo(Feature feature) {
-        List<? extends Conditional> conditionals = feature.getConditional();
-        if (conditionals.isEmpty()) {
-            System.out.println("Feature has no conditionals.");
-        } else {
-            System.out.println("Feature contains followed conditionals:");
-            for (Conditional featureConditional : conditionals) {
-                String conditionDescription = getConditionDescription(featureConditional);
-                Feature wrappedConditional = featureConditional.asFeature(feature.getName(), feature.getVersion());
-                if (config) {
-                    displayConfigInformation(wrappedConditional, String.format(CONDITIONAL_CONTENT, conditionDescription));
-                    displayConfigFileInformation(wrappedConditional, String.format(CONDITIONAL_CONTENT, conditionDescription));
-                }
-
-                if (dependency) {
-                    displayDependencyInformation(wrappedConditional, String.format(CONDITIONAL_CONTENT, conditionDescription));
-                }
-
-                if (bundle) {
-                    displayBundleInformation(wrappedConditional, String.format(CONDITIONAL_CONTENT, conditionDescription));
-                }
-            }
-        }
-    }
-
-    private String getConditionDescription(Conditional cond) {
-        StringBuffer sb = new StringBuffer();
-        Iterator<? extends Dependency> di = cond.getCondition().iterator();
-        while (di.hasNext()) {
-            Dependency dep = di.next();
-            sb.append(dep.getName()).append("/").append(dep.getVersion());
-            if (di.hasNext()) {
-                sb.append(" ");
-            }
-        }
-        return sb.toString();
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/command/src/main/java/org/apache/karaf/features/command/InstallFeatureCommand.java
----------------------------------------------------------------------
diff --git a/features/command/src/main/java/org/apache/karaf/features/command/InstallFeatureCommand.java b/features/command/src/main/java/org/apache/karaf/features/command/InstallFeatureCommand.java
deleted file mode 100644
index b7f8184..0000000
--- a/features/command/src/main/java/org/apache/karaf/features/command/InstallFeatureCommand.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * 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.karaf.features.command;
-
-import java.util.EnumSet;
-import java.util.HashSet;
-import java.util.List;
-
-import org.apache.karaf.features.FeaturesService;
-import org.apache.karaf.features.command.completers.AvailableFeatureCompleter;
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Completion;
-import org.apache.karaf.shell.api.action.Option;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-
-@Command(scope = "feature", name = "install", description = "Installs a feature with the specified name and version.")
-@Service
-public class InstallFeatureCommand extends FeaturesCommandSupport {
-
-    private static String DEFAULT_VERSION = "0.0.0";
-
-    @Argument(index = 0, name = "feature", description = "The name and version of the features to install. A feature id looks like name/version. The version is optional.", required = true, multiValued = true)
-    @Completion(AvailableFeatureCompleter.class)
-    List<String> features;
-
-    @Option(name = "-r", aliases = "--no-auto-refresh", description = "Do not automatically refresh bundles", required = false, multiValued = false)
-    boolean noRefresh;
-
-    @Option(name = "-s", aliases = "--no-auto-start", description = "Do not start the bundles", required = false, multiValued = false)
-    boolean noStart;
-
-    @Option(name = "-v", aliases = "--verbose", description = "Explain what is being done", required = false, multiValued = false)
-    boolean verbose;
-
-    @Option(name = "-t", aliases = "--simulate", description = "Perform a simulation only", required = false, multiValued = false)
-    boolean simulate;
-
-    protected void doExecute(FeaturesService admin) throws Exception {
-        EnumSet<FeaturesService.Option> options = EnumSet.noneOf(FeaturesService.Option.class);
-        if (simulate) {
-            options.add(FeaturesService.Option.Simulate);
-        }
-        if (noStart) {
-            options.add(FeaturesService.Option.NoAutoStartBundles);
-        }
-        if (noRefresh) {
-            options.add(FeaturesService.Option.NoAutoRefreshBundles);
-        }
-        if (verbose) {
-            options.add(FeaturesService.Option.Verbose);
-        }
-        admin.installFeatures(new HashSet<String>(features), options);
-    }
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/command/src/main/java/org/apache/karaf/features/command/ListFeatureVersionsCommand.java
----------------------------------------------------------------------
diff --git a/features/command/src/main/java/org/apache/karaf/features/command/ListFeatureVersionsCommand.java b/features/command/src/main/java/org/apache/karaf/features/command/ListFeatureVersionsCommand.java
deleted file mode 100644
index b2c5e42..0000000
--- a/features/command/src/main/java/org/apache/karaf/features/command/ListFeatureVersionsCommand.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * 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.karaf.features.command;
-
-import java.util.Arrays;
-
-import org.apache.karaf.features.Feature;
-import org.apache.karaf.features.FeaturesService;
-import org.apache.karaf.features.Repository;
-import org.apache.karaf.features.command.completers.AllFeatureCompleter;
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Completion;
-import org.apache.karaf.shell.api.action.Option;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.apache.karaf.shell.support.table.ShellTable;
-
-@Command(scope = "feature", name = "version-list", description = "Lists all versions of a feature available from the currently available repositories.")
-@Service
-public class ListFeatureVersionsCommand extends FeaturesCommandSupport {
-
-	@Argument(index = 0, name = "feature", description = "Name of feature.", required = true, multiValued = false)
-    @Completion(AllFeatureCompleter.class)
-	String feature;
-
-    @Option(name = "--no-format", description = "Disable table rendered output", required = false, multiValued = false)
-    boolean noFormat;
-
-    protected void doExecute(FeaturesService admin) throws Exception {
-        ShellTable table = new ShellTable();
-        table.column("Version");
-        table.column("Repository");
-        table.column("Repository URL");
-        table.emptyTableText("No versions available for features '" + feature + "'");
-             
-        for (Repository r : Arrays.asList(admin.listRepositories())) {
-            for (Feature f : r.getFeatures()) {
-
-                if (f.getName().equals(feature)) {
-                    table.addRow().addContent(f.getVersion(), r.getName(), r.getURI());
-                }
-            }
-        }
-
-        table.print(System.out, !noFormat);
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/command/src/main/java/org/apache/karaf/features/command/ListFeaturesCommand.java
----------------------------------------------------------------------
diff --git a/features/command/src/main/java/org/apache/karaf/features/command/ListFeaturesCommand.java b/features/command/src/main/java/org/apache/karaf/features/command/ListFeaturesCommand.java
deleted file mode 100644
index e86ff64..0000000
--- a/features/command/src/main/java/org/apache/karaf/features/command/ListFeaturesCommand.java
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * 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.karaf.features.command;
-
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.List;
-
-import org.apache.karaf.features.Feature;
-import org.apache.karaf.features.FeaturesService;
-import org.apache.karaf.features.Repository;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Option;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.apache.karaf.shell.support.table.ShellTable;
-
-@Command(scope = "feature", name = "list", description = "Lists all existing features available from the defined repositories.")
-@Service
-public class ListFeaturesCommand extends FeaturesCommandSupport {
-
-    @Option(name = "-i", aliases = {"--installed"}, description = "Display a list of all installed features only", required = false, multiValued = false)
-    boolean onlyInstalled;
-
-    @Option(name = "-r", aliases = {"--required"}, description = "Display a list of all required features only", required = false, multiValued = false)
-    boolean onlyRequired;
-
-    @Option(name = "-o", aliases = {"--ordered"}, description = "Display a list using alphabetical order ", required = false, multiValued = false)
-    boolean ordered;
-
-    @Option(name = "--no-format", description = "Disable table rendered output", required = false, multiValued = false)
-    boolean noFormat;
-
-    protected void doExecute(FeaturesService featuresService) throws Exception {
-        boolean needsLegend = false;
-        
-        ShellTable table = new ShellTable();
-        table.column("Name");
-        table.column("Version");
-        table.column("Required");
-        table.column("Installed");
-        table.column("Repository");
-        table.column("Description").maxSize(50);
-        table.emptyTableText(onlyInstalled ? "No features installed" : "No features available");
-
-        List<Repository> repos = Arrays.asList(featuresService.listRepositories());
-        for (Repository r : repos) {
-            List<Feature> features = Arrays.asList(r.getFeatures());
-            if (ordered) {
-                Collections.sort(features, new FeatureComparator());
-            }
-            for (Feature f : features) {
-                if (onlyInstalled && !featuresService.isInstalled(f)) {
-                    // Filter out not installed features if we only want to see the installed ones
-                    continue;
-                }
-                if (onlyRequired && !featuresService.isRequired(f)) {
-                    // Filter out not installed features if we only want to see the installed ones
-                    continue;
-                }
-                table.addRow().addContent(
-                        f.getName(),
-                        f.getVersion(),
-                        featuresService.isRequired(f) ? "x" : "",
-                        featuresService.isInstalled(f) ? "x" : "",
-                        r.getName(),
-                        f.getDescription());
-                if (isInstalledViaDeployDir(r.getName())) {
-                    needsLegend = true;
-                }
-            }
-        }
-
-        table.print(System.out, !noFormat);
-
-        if (needsLegend) {
-            System.out.println("* Installed via deploy directory");
-        }
-
-    }
-
-    private boolean isInstalledViaDeployDir(String st) {
-        return (st == null || st.length() <= 1) ? false : (st.charAt(st.length() - 1) == '*');
-    }
-
-    class FeatureComparator implements Comparator<Feature> {
-        public int compare(Feature o1, Feature o2) {
-            return o1.getName().toLowerCase().compareTo( o2.getName().toLowerCase() );
-        }
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/command/src/main/java/org/apache/karaf/features/command/RepoAddCommand.java
----------------------------------------------------------------------
diff --git a/features/command/src/main/java/org/apache/karaf/features/command/RepoAddCommand.java b/features/command/src/main/java/org/apache/karaf/features/command/RepoAddCommand.java
deleted file mode 100644
index 16faf42..0000000
--- a/features/command/src/main/java/org/apache/karaf/features/command/RepoAddCommand.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * 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.karaf.features.command;
-
-import java.net.URI;
-
-import org.apache.karaf.features.FeaturesService;
-import org.apache.karaf.features.command.completers.AvailableRepoNameCompleter;
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Completion;
-import org.apache.karaf.shell.api.action.Option;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-
-@Command(scope = "feature", name = "repo-add", description = "Add a features repository")
-@Service
-public class RepoAddCommand extends FeaturesCommandSupport {
-
-    @Argument(index = 0, name = "name/url", description = "Shortcut name of the features repository or the full URL", required = true, multiValued = false)
-    @Completion(AvailableRepoNameCompleter.class)
-    private String nameOrUrl;
-    
-    @Argument(index = 1, name = "version", description = "The version of the features repository if using features repository name as first argument. It should be empty if using the URL", required = false, multiValued = false)
-    private String version;
-
-    @Option(name = "-i", aliases = { "--install" }, description = "Install all features contained in the features repository", required = false, multiValued = false)
-    private boolean install;
-
-    @Override
-    protected void doExecute(FeaturesService featuresService) throws Exception {
-        String effectiveVersion = (version == null) ? "LATEST" : version;
-        URI uri = featuresService.getRepositoryUriFor(nameOrUrl, effectiveVersion);
-        if (uri == null) {
-            uri = new URI(nameOrUrl);
-        }
-        System.out.println("Adding feature url " + uri);
-        featuresService.addRepository(uri, install);
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/command/src/main/java/org/apache/karaf/features/command/RepoListCommand.java
----------------------------------------------------------------------
diff --git a/features/command/src/main/java/org/apache/karaf/features/command/RepoListCommand.java b/features/command/src/main/java/org/apache/karaf/features/command/RepoListCommand.java
deleted file mode 100644
index 591a1c6..0000000
--- a/features/command/src/main/java/org/apache/karaf/features/command/RepoListCommand.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * 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.karaf.features.command;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import org.apache.karaf.features.FeaturesService;
-import org.apache.karaf.features.Repository;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Option;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.apache.karaf.shell.support.MultiException;
-import org.apache.karaf.shell.support.table.ShellTable;
-
-@Command(scope = "feature", name = "repo-list", description = "Displays a list of all defined repositories.")
-@Service
-public class RepoListCommand extends FeaturesCommandSupport {
-
-    @Option(name="-r", description="Reload all feature urls", required = false, multiValued = false)
-    boolean reload;
-
-    @Option(name = "--no-format", description = "Disable table rendered output", required = false, multiValued = false)
-    boolean noFormat;
-    
-    protected void doExecute(FeaturesService featuresService) throws Exception {
-        if (reload) {
-            reloadAllRepos(featuresService);
-        }
-        
-        ShellTable table = new ShellTable();
-        table.column("Repository");
-        table.column("URL");
-        table.emptyTableText("No repositories available");
-
-        Repository[] repos = featuresService.listRepositories();
-     	for (Repository repo : repos) {
-     	    table.addRow().addContent(repo.getName(), repo.getURI().toString()); 
-     	}
-     	table.print(System.out, !noFormat);
-    }
-
-    private void reloadAllRepos(FeaturesService featuresService) throws Exception {
-        System.out.println("Reloading all repositories from their urls");
-        System.out.println();
-        List<Exception> exceptions = new ArrayList<Exception>();
-        for (Repository repo : featuresService.listRepositories()) {
-            try {
-                featuresService.addRepository(repo.getURI());
-            } catch (Exception e) {
-                exceptions.add(e);
-            }
-        }
-        MultiException.throwIf("Unable to reload repositories", exceptions);
-    }
-    
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/command/src/main/java/org/apache/karaf/features/command/RepoRefreshCommand.java
----------------------------------------------------------------------
diff --git a/features/command/src/main/java/org/apache/karaf/features/command/RepoRefreshCommand.java b/features/command/src/main/java/org/apache/karaf/features/command/RepoRefreshCommand.java
deleted file mode 100644
index 8c7ed79..0000000
--- a/features/command/src/main/java/org/apache/karaf/features/command/RepoRefreshCommand.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * 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.karaf.features.command;
-
-import java.net.URI;
-import java.util.ArrayList;
-import java.util.List;
-
-import org.apache.karaf.features.FeaturesService;
-import org.apache.karaf.features.Repository;
-import org.apache.karaf.features.command.completers.InstalledRepoUriCompleter;
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Completion;
-
-@Command(scope = "feature", name = "repo-refresh", description = "Refresh a features repository")
-public class RepoRefreshCommand extends FeaturesCommandSupport {
-    @Argument(index = 0, name = "Feature name or uri", description = "Shortcut name of the feature repository or the full URI", required = false, multiValued = false)
-    @Completion(InstalledRepoUriCompleter.class)
-    private String nameOrUrl;
-    
-    @Argument(index = 1, name = "Feature version", description = "The version of the feature if using the feature name. Should be empty if using the uri", required = false, multiValued = false)
-    private String version;
-
-    @Override
-    protected void doExecute(FeaturesService featuresService) throws Exception {
-        List<URI> uris = new ArrayList<URI>();
-    	if (nameOrUrl != null) {
-    		String effectiveVersion = (version == null) ? "LATEST" : version;
-        	URI uri = featuresService.getRepositoryUriFor(nameOrUrl, effectiveVersion);
-        	if (uri == null) {
-        		uri = new URI(nameOrUrl);
-        	}
-            uris.add(uri);
-    	} else {
-            Repository[] repos = featuresService.listRepositories();
-            for (Repository repo : repos) {
-                uris.add(repo.getURI());
-            }
-    	}
-        for (URI uri : uris) {
-            try {
-                System.out.println("Refreshing feature url " + uri);
-                featuresService.refreshRepository(uri);
-            } catch (Exception e) {
-                System.err.println("Error refreshing " + uri.toString() + ": " + e.getMessage());
-            }
-        }
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/command/src/main/java/org/apache/karaf/features/command/RepoRemoveCommand.java
----------------------------------------------------------------------
diff --git a/features/command/src/main/java/org/apache/karaf/features/command/RepoRemoveCommand.java b/features/command/src/main/java/org/apache/karaf/features/command/RepoRemoveCommand.java
deleted file mode 100644
index 0710b72..0000000
--- a/features/command/src/main/java/org/apache/karaf/features/command/RepoRemoveCommand.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * 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.karaf.features.command;
-
-import java.net.URI;
-
-import org.apache.karaf.features.FeaturesService;
-import org.apache.karaf.features.Repository;
-import org.apache.karaf.features.command.completers.InstalledRepoNameCompleter;
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Completion;
-import org.apache.karaf.shell.api.action.Option;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-
-@Command(scope = "feature", name = "repo-remove", description = "Removes the specified repository features service.")
-@Service
-public class RepoRemoveCommand extends FeaturesCommandSupport {
-
-    @Argument(index = 0, name = "repository", description = "Name or url of the repository to remove.", required = true, multiValued = false)
-    @Completion(InstalledRepoNameCompleter.class)
-    private String repository;
-
-    @Option(name = "-u", aliases = { "--uninstall-all" }, description = "Uninstall all features from the repository", required = false, multiValued = false)
-    private boolean uninstall;
-
-    protected void doExecute(FeaturesService featuresService) throws Exception {
-    	URI uri = null;
-    	for (Repository r : featuresService.listRepositories()) {
-    		if (r.getName() != null && r.getName().equals(repository)) {
-    			uri = r.getURI();
-    			break;
-    		}
-    	}
-
-    	if (uri == null) {
-    	    uri = new URI(repository);
-    	}
-
-    	featuresService.removeRepository(uri, uninstall);
-    }
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/command/src/main/java/org/apache/karaf/features/command/UninstallFeatureCommand.java
----------------------------------------------------------------------
diff --git a/features/command/src/main/java/org/apache/karaf/features/command/UninstallFeatureCommand.java b/features/command/src/main/java/org/apache/karaf/features/command/UninstallFeatureCommand.java
deleted file mode 100644
index e62f697..0000000
--- a/features/command/src/main/java/org/apache/karaf/features/command/UninstallFeatureCommand.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * 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.karaf.features.command;
-
-import java.util.EnumSet;
-import java.util.HashSet;
-import java.util.List;
-
-import org.apache.karaf.features.FeaturesService;
-import org.apache.karaf.features.command.completers.RequiredFeatureCompleter;
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Completion;
-import org.apache.karaf.shell.api.action.Option;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-
-@Command(scope = "feature", name = "uninstall", description = "Uninstalls a feature with the specified name and version.")
-@Service
-public class UninstallFeatureCommand extends FeaturesCommandSupport {
-
-    @Argument(index = 0, name = "features", description = "The name and version of the features to uninstall. A feature id looks like name/version. The version is optional.", required = true, multiValued = true)
-    @Completion(RequiredFeatureCompleter.class)
-    List<String> features;
-
-    @Option(name = "-r", aliases = "--no-auto-refresh", description = "Do not automatically refresh bundles", required = false, multiValued = false)
-    boolean noRefresh;
-
-    @Option(name = "-v", aliases = "--verbose", description = "Explain what is being done", required = false, multiValued = false)
-    boolean verbose;
-
-    @Option(name = "-t", aliases = "--simulate", description = "Perform a simulation only", required = false, multiValued = false)
-    boolean simulate;
-
-    protected void doExecute(FeaturesService admin) throws Exception {
-        // iterate in the provided feature
-        EnumSet<FeaturesService.Option> options = EnumSet.noneOf(FeaturesService.Option.class);
-        if (simulate) {
-            options.add(FeaturesService.Option.Simulate);
-        }
-        if (noRefresh) {
-            options.add(FeaturesService.Option.NoAutoRefreshBundles);
-        }
-        if (verbose) {
-            options.add(FeaturesService.Option.Verbose);
-        }
-        admin.uninstallFeatures(new HashSet<String>(features), options);
-    }
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/command/src/main/java/org/apache/karaf/features/command/completers/AllFeatureCompleter.java
----------------------------------------------------------------------
diff --git a/features/command/src/main/java/org/apache/karaf/features/command/completers/AllFeatureCompleter.java b/features/command/src/main/java/org/apache/karaf/features/command/completers/AllFeatureCompleter.java
deleted file mode 100644
index 7444b95..0000000
--- a/features/command/src/main/java/org/apache/karaf/features/command/completers/AllFeatureCompleter.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * 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.karaf.features.command.completers;
-
-import org.apache.karaf.features.Feature;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-
-/**
- * {@link org.apache.karaf.shell.console.Completer} for available features.
- */
-@Service
-public class AllFeatureCompleter extends FeatureCompleterSupport {
-
-    @Override
-    protected boolean acceptsFeature(Feature feature) {
-        return true;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/command/src/main/java/org/apache/karaf/features/command/completers/AvailableFeatureCompleter.java
----------------------------------------------------------------------
diff --git a/features/command/src/main/java/org/apache/karaf/features/command/completers/AvailableFeatureCompleter.java b/features/command/src/main/java/org/apache/karaf/features/command/completers/AvailableFeatureCompleter.java
deleted file mode 100644
index 79cd280..0000000
--- a/features/command/src/main/java/org/apache/karaf/features/command/completers/AvailableFeatureCompleter.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * 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.karaf.features.command.completers;
-
-import org.apache.karaf.features.Feature;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-
-/**
- * {@link org.apache.karaf.shell.console.Completer} for features not installed yet.
- */
-@Service
-public class AvailableFeatureCompleter extends FeatureCompleterSupport {
-
-    @Override
-    protected boolean acceptsFeature(Feature feature) {
-        return !featuresService.isInstalled(feature);
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/command/src/main/java/org/apache/karaf/features/command/completers/AvailableRepoNameCompleter.java
----------------------------------------------------------------------
diff --git a/features/command/src/main/java/org/apache/karaf/features/command/completers/AvailableRepoNameCompleter.java b/features/command/src/main/java/org/apache/karaf/features/command/completers/AvailableRepoNameCompleter.java
deleted file mode 100644
index acefe77..0000000
--- a/features/command/src/main/java/org/apache/karaf/features/command/completers/AvailableRepoNameCompleter.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * 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.karaf.features.command.completers;
-
-import java.util.Arrays;
-import java.util.List;
-
-import org.apache.karaf.features.FeaturesService;
-import org.apache.karaf.shell.api.action.lifecycle.Reference;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.apache.karaf.shell.api.console.CommandLine;
-import org.apache.karaf.shell.api.console.Completer;
-import org.apache.karaf.shell.api.console.Session;
-import org.apache.karaf.shell.support.completers.StringsCompleter;
-
-/**
- * Shows the list of feature repos that can be installed with their short name
- */
-@Service
-public class AvailableRepoNameCompleter implements Completer {
-
-    @Reference
-    private FeaturesService featuresService;
-
-    public void setFeaturesService(FeaturesService featuresService) {
-        this.featuresService = featuresService;
-    }
-
-    public int complete(Session session, CommandLine commandLine, final List<String> candidates) {
-        StringsCompleter delegate = new StringsCompleter(Arrays.asList(featuresService.getRepositoryNames()));
-        return delegate.complete(session, commandLine, candidates);
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/command/src/main/java/org/apache/karaf/features/command/completers/FeatureCompleterSupport.java
----------------------------------------------------------------------
diff --git a/features/command/src/main/java/org/apache/karaf/features/command/completers/FeatureCompleterSupport.java b/features/command/src/main/java/org/apache/karaf/features/command/completers/FeatureCompleterSupport.java
deleted file mode 100644
index d01e5af..0000000
--- a/features/command/src/main/java/org/apache/karaf/features/command/completers/FeatureCompleterSupport.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * 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.karaf.features.command.completers;
-
-import java.util.List;
-
-import org.apache.karaf.features.Feature;
-import org.apache.karaf.features.FeaturesService;
-import org.apache.karaf.shell.api.action.lifecycle.Reference;
-import org.apache.karaf.shell.api.console.CommandLine;
-import org.apache.karaf.shell.api.console.Completer;
-import org.apache.karaf.shell.api.console.Session;
-import org.apache.karaf.shell.support.completers.StringsCompleter;
-
-/**
- * Base completer for feature commands.
- */
-public abstract class FeatureCompleterSupport implements Completer {
-
-    /**
-     * Feature service.
-     */
-    @Reference
-    protected FeaturesService featuresService;
-
-    public void setFeaturesService(FeaturesService featuresService) {
-        this.featuresService = featuresService;
-    }
-
-    public int complete(Session session, final CommandLine commandLine, final List<String> candidates) {
-        StringsCompleter delegate = new StringsCompleter();
-        try {
-            for (Feature feature : featuresService.listFeatures()) {
-                if (acceptsFeature(feature)) {
-                    delegate.getStrings().add(feature.getName());
-                }
-            }
-        } catch (Exception e) {
-            // Ignore
-        }
-        return delegate.complete(session, commandLine, candidates);
-    }
-
-    /**
-     * Method for filtering features.
-     *
-     * @param feature The feature.
-     * @return True if feature should be available in completer.
-     */
-    protected abstract boolean acceptsFeature(Feature feature);
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/command/src/main/java/org/apache/karaf/features/command/completers/InstalledRepoNameCompleter.java
----------------------------------------------------------------------
diff --git a/features/command/src/main/java/org/apache/karaf/features/command/completers/InstalledRepoNameCompleter.java b/features/command/src/main/java/org/apache/karaf/features/command/completers/InstalledRepoNameCompleter.java
deleted file mode 100644
index 94e4cf7..0000000
--- a/features/command/src/main/java/org/apache/karaf/features/command/completers/InstalledRepoNameCompleter.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * 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.karaf.features.command.completers;
-
-import java.util.List;
-
-import org.apache.karaf.features.FeaturesService;
-import org.apache.karaf.features.Repository;
-import org.apache.karaf.shell.api.action.lifecycle.Reference;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.apache.karaf.shell.api.console.CommandLine;
-import org.apache.karaf.shell.api.console.Completer;
-import org.apache.karaf.shell.api.console.Session;
-import org.apache.karaf.shell.support.completers.StringsCompleter;
-
-/**
- * {@link Completer} for Feature Repository URLs.
- *
- * Displays a list of currently installed Feature repositories.
- *
- */
-@Service
-public class InstalledRepoNameCompleter implements Completer {
-
-    @Reference
-    private FeaturesService featuresService;
-
-    public void setFeaturesService(FeaturesService featuresService) {
-        this.featuresService = featuresService;
-    }
-
-    public int complete(Session session, final CommandLine commandLine, final List<String> candidates) {
-        StringsCompleter delegate = new StringsCompleter();
-        try {
-            for (Repository repository : featuresService.listRepositories()) {
-                delegate.getStrings().add(repository.getName());
-            }
-        } catch (Exception e) {
-            // Ignore
-        }
-        return delegate.complete(session, commandLine, candidates);
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/command/src/main/java/org/apache/karaf/features/command/completers/InstalledRepoUriCompleter.java
----------------------------------------------------------------------
diff --git a/features/command/src/main/java/org/apache/karaf/features/command/completers/InstalledRepoUriCompleter.java b/features/command/src/main/java/org/apache/karaf/features/command/completers/InstalledRepoUriCompleter.java
deleted file mode 100644
index 7a760c2..0000000
--- a/features/command/src/main/java/org/apache/karaf/features/command/completers/InstalledRepoUriCompleter.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * 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.karaf.features.command.completers;
-
-import java.util.List;
-
-import org.apache.karaf.features.FeaturesService;
-import org.apache.karaf.features.Repository;
-import org.apache.karaf.shell.api.action.lifecycle.Reference;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.apache.karaf.shell.api.console.CommandLine;
-import org.apache.karaf.shell.api.console.Completer;
-import org.apache.karaf.shell.api.console.Session;
-import org.apache.karaf.shell.support.completers.StringsCompleter;
-
-/**
- * {@link Completer} for Feature Repository URLs.
- *
- * Displays a list of currently installed Feature repositories.
- *
- */
-
-@Service
-public class InstalledRepoUriCompleter implements Completer {
-
-    @Reference
-    private FeaturesService featuresService;
-
-    public void setFeaturesService(FeaturesService featuresService) {
-        this.featuresService = featuresService;
-    }
-
-    public int complete(Session session, final CommandLine commandLine, final List<String> candidates) {
-        StringsCompleter delegate = new StringsCompleter();
-        try {
-            for (Repository repository : featuresService.listRepositories()) {
-                delegate.getStrings().add(repository.getURI().toString());
-            }
-        } catch (Exception e) {
-            // Ignore
-        }
-        return delegate.complete(session, commandLine, candidates);
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/command/src/main/java/org/apache/karaf/features/command/completers/RequiredFeatureCompleter.java
----------------------------------------------------------------------
diff --git a/features/command/src/main/java/org/apache/karaf/features/command/completers/RequiredFeatureCompleter.java b/features/command/src/main/java/org/apache/karaf/features/command/completers/RequiredFeatureCompleter.java
deleted file mode 100644
index a51f75f..0000000
--- a/features/command/src/main/java/org/apache/karaf/features/command/completers/RequiredFeatureCompleter.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * 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.karaf.features.command.completers;
-
-import org.apache.karaf.features.Feature;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-
-/**
- * {@link org.apache.karaf.shell.console.Completer} for installed features.
- */
-@Service
-public class RequiredFeatureCompleter extends FeatureCompleterSupport {
-
-    @Override
-    protected boolean acceptsFeature(Feature feature) {
-        return featuresService.isRequired(feature);
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/command/src/main/resources/OSGI-INF/bundle.info
----------------------------------------------------------------------
diff --git a/features/command/src/main/resources/OSGI-INF/bundle.info b/features/command/src/main/resources/OSGI-INF/bundle.info
deleted file mode 100644
index 8f0598b..0000000
--- a/features/command/src/main/resources/OSGI-INF/bundle.info
+++ /dev/null
@@ -1,30 +0,0 @@
-h1. Synopsis
-
-${project.name}
-
-${project.description}
-
-Maven URL:
-[mvn:${project.groupId}/${project.artifactId}/${project.version}]
-
-h1. Description
-
-This bundle provides the Karaf shell commands to manipulate features.
-
-The following commands are available:
-
-* features:addUrl - Adds a list of repository URLs to the features service.
-* features:info- Shows information about selected information.
-* features:install- Installs a feature with the specified name and version.
-* features:list - Lists all existing features available from the defined repositories.
-* features:listVersions- Lists all versions of a feature available from the currently available repositories.
-* features:listRepositories- Displays a list of all defined repositories.
-* features:listUrl- Displays a list of all defined repository URLs.
-* features:refreshUrl- Reloads the list of available features from the repositories.
-* features:removeRepository- Removes the specified repository features service.
-* features:removeUrl- Removes the given list of repository URLs from the features service.
-* features:uninstall- Uninstalls a feature with the specified name and version.
-
-h1. See also
-
-Commands- and Provisioning- sections of the Karaf User Guide.


[25/59] [abbrv] [KARAF-2852] Merge instance/core and instance/command

Posted by gn...@apache.org.
http://git-wip-us.apache.org/repos/asf/karaf/blob/7c2db062/instance/src/main/java/org/apache/karaf/jpm/impl/ProcessImpl.java
----------------------------------------------------------------------
diff --git a/instance/src/main/java/org/apache/karaf/jpm/impl/ProcessImpl.java b/instance/src/main/java/org/apache/karaf/jpm/impl/ProcessImpl.java
new file mode 100644
index 0000000..d831fb7
--- /dev/null
+++ b/instance/src/main/java/org/apache/karaf/jpm/impl/ProcessImpl.java
@@ -0,0 +1,155 @@
+/*
+ * 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.karaf.jpm.impl;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.InterruptedIOException;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.karaf.jpm.Process;
+
+public class ProcessImpl implements Process {
+
+    /**
+     * 
+     */
+    private static final long serialVersionUID = -8140632422386086507L;
+
+    private int pid;
+    //private File input;
+    //private File output;
+    //private File error;
+
+    public ProcessImpl(int pid/*, File input, File output, File error*/) {
+        this.pid = pid;
+        //this.input = input;
+        //this.output = output;
+        //this.error = error;
+    }
+
+    public int getPid() {
+        return pid;
+    }
+
+    public boolean isRunning() throws IOException {
+        if (ScriptUtils.isWindows()) {
+            Map<String, String> props = new HashMap<String, String>();
+            props.put("${pid}", Integer.toString(pid));
+            int ret = ScriptUtils.execute("running", props);
+            return ret == 0;
+        } else {
+            try {
+                java.lang.Process process = new java.lang.ProcessBuilder("ps", "-p", Integer.toString(pid)).start();
+                BufferedReader r = new BufferedReader(new InputStreamReader(process.getInputStream()));
+                r.readLine(); // skip headers
+                String s = r.readLine();
+                boolean running = s != null && s.length() > 0;
+                process.waitFor();
+                return running;
+            } catch (InterruptedException e) {
+                throw new InterruptedIOException();
+            }
+        }
+    }
+
+    public void destroy() throws IOException {
+        int ret;
+        if (ScriptUtils.isWindows()) {
+            Map<String, String> props = new HashMap<String, String>();
+            props.put("${pid}", Integer.toString(pid));
+            ret = ScriptUtils.execute("destroy", props);
+        } else {
+            ret = ScriptUtils.executeProcess(new java.lang.ProcessBuilder("kill", "-9", Integer.toString(pid)));
+        }
+        if (ret != 0) {
+            throw new IOException("Unable to destroy process, it may already be terminated");
+        }
+    }
+
+    /*
+    public OutputStream getInputStream() throws FileNotFoundException {
+        return new FileOutputStream(input);
+    }
+
+    public InputStream getOutputStream() throws FileNotFoundException {
+        return new FileInputStream(output);
+    }
+
+    public InputStream getErrorStream() throws FileNotFoundException {
+        return new FileInputStream(error);
+    }
+    */
+
+    public int waitFor() throws InterruptedException {
+        return 0;
+    }
+
+    public int exitValue() {
+        return 0;
+    }
+
+    public static Process create(File dir, String command) throws IOException {
+        //File input = File.createTempFile("jpm.", ".input");
+        //File output = File.createTempFile("jpm.", ".output");
+        //File error = File.createTempFile("jpm.", ".error");
+        File pidFile = File.createTempFile("jpm.", ".pid");
+        try {
+            Map<String, String> props = new HashMap<String, String>();
+            //props.put("${in.file}", input.getCanonicalPath());
+            //props.put("${out.file}", output.getCanonicalPath());
+            //props.put("${err.file}", error.getCanonicalPath());
+            props.put("${pid.file}", pidFile.getCanonicalPath());
+            props.put("${dir}", dir != null ? dir.getCanonicalPath() : "");
+            if (ScriptUtils.isWindows()) {
+                command = command.replaceAll("\"", "\"\"");
+            }
+            props.put("${command}", command);
+            int ret = ScriptUtils.execute("start", props);
+            if (ret != 0) {
+                throw new IOException("Unable to create process (error code: " + ret + ")");
+            }
+            int pid = readPid(pidFile);
+            return new ProcessImpl(pid/*, input, output, error*/);
+        } finally {
+            pidFile.delete();
+        }
+    }
+
+    public static Process attach(int pid) throws IOException {
+        return new ProcessImpl(pid);
+    }
+
+    private static int readPid(File pidFile) throws IOException {
+        InputStream is = new FileInputStream(pidFile);
+        try {
+            BufferedReader r = new BufferedReader(new InputStreamReader(is));
+            String pidString = r.readLine();
+            return Integer.valueOf(pidString);
+        } finally {
+            try {
+                is.close();
+            } catch (IOException e) {}
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/7c2db062/instance/src/main/java/org/apache/karaf/jpm/impl/ScriptUtils.java
----------------------------------------------------------------------
diff --git a/instance/src/main/java/org/apache/karaf/jpm/impl/ScriptUtils.java b/instance/src/main/java/org/apache/karaf/jpm/impl/ScriptUtils.java
new file mode 100644
index 0000000..a96e28e
--- /dev/null
+++ b/instance/src/main/java/org/apache/karaf/jpm/impl/ScriptUtils.java
@@ -0,0 +1,128 @@
+/*
+ * 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.karaf.jpm.impl;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InterruptedIOException;
+import java.io.OutputStream;
+import java.io.PrintStream;
+import java.util.Map;
+import java.util.Scanner;
+
+public class ScriptUtils {
+
+    public static int execute(String name, Map<String, String> props) throws IOException {
+        File script = File.createTempFile("jpm.", ".script");
+        try {
+            if (isWindows()) {
+                String res = "windows/" + name + ".vbs";
+                ScriptUtils.copyFilteredResource(res, script, props);
+                return executeProcess(new java.lang.ProcessBuilder("cscript",
+                                                                   "/NOLOGO",
+                                                                   "//E:vbs",
+                                                                   script.getCanonicalPath()));
+            } else {
+                String res = "unix/" + name + ".sh";
+                ScriptUtils.copyFilteredResource(res, script, props);
+                return executeProcess(new java.lang.ProcessBuilder("/bin/sh",
+                                                                   script.getCanonicalPath()));
+            }
+        } finally {
+            script.delete();
+        }
+    }
+
+    public static int executeProcess(java.lang.ProcessBuilder builder) throws IOException {
+        try {
+            java.lang.Process process = builder.start();
+            return process.waitFor();
+        } catch (InterruptedException e) {
+            throw new InterruptedIOException();
+        }
+    }
+
+    public static void copyFilteredResource(String resource, File outFile, Map<String, String> props) throws IOException {
+        InputStream is = null;
+        try {
+            is = ScriptUtils.class.getResourceAsStream(resource);
+            // Read it line at a time so that we can use the platform line ending when we write it out.
+            PrintStream out = new PrintStream(new FileOutputStream(outFile));
+            try {
+                Scanner scanner = new Scanner(is);
+                while (scanner.hasNextLine() ) {
+                    String line = scanner.nextLine();
+                    line = filter(line, props);
+                    out.println(line);
+                }
+            } finally {
+                safeClose(out);
+            }
+        } finally {
+            safeClose(is);
+        }
+    }
+
+    private static void safeClose(InputStream is) throws IOException {
+        if (is == null) {
+            return;
+        }
+        try {
+            is.close();
+        } catch (Throwable ignore) {
+        }
+    }
+
+    private static void safeClose(OutputStream is) throws IOException {
+        if (is == null) {
+            return;
+        }
+        try {
+            is.close();
+        } catch (Throwable ignore) {
+        }
+    }
+
+    private static String filter(String line, Map<String, String> props) {
+        for (Map.Entry<String, String> i : props.entrySet()) {
+            int p1 = line.indexOf(i.getKey());
+            if( p1 >= 0 ) {
+                String l1 = line.substring(0, p1);
+                String l2 = line.substring(p1+i.getKey().length());
+                line = l1+i.getValue()+l2;
+            }
+        }
+        return line;
+    }
+
+    private static final boolean windows;
+
+    static {
+        windows = System.getProperty("os.name").toLowerCase().indexOf("windows") != -1;
+    }
+
+    public static boolean isWindows() {
+        return windows;
+    }
+
+    public static String getJavaCommandPath() throws IOException {
+        return new File(System.getProperty("java.home"), isWindows() ? "bin\\java.exe" : "bin/java").getCanonicalPath();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/7c2db062/instance/src/main/resources/META-INF/services/org/apache/karaf/shell/commands
----------------------------------------------------------------------
diff --git a/instance/src/main/resources/META-INF/services/org/apache/karaf/shell/commands b/instance/src/main/resources/META-INF/services/org/apache/karaf/shell/commands
new file mode 100644
index 0000000..92245c7
--- /dev/null
+++ b/instance/src/main/resources/META-INF/services/org/apache/karaf/shell/commands
@@ -0,0 +1,30 @@
+##---------------------------------------------------------------------------
+##  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.
+##---------------------------------------------------------------------------
+org.apache.karaf.instance.core.internal.InstanceServiceImpl
+org.apache.karaf.instance.command.ChangeOptsCommand
+org.apache.karaf.instance.command.ChangeRmiRegistryPortCommand
+org.apache.karaf.instance.command.ChangeRmiServerPortCommand
+org.apache.karaf.instance.command.ChangeSshPortCommand
+org.apache.karaf.instance.command.CloneCommand
+org.apache.karaf.instance.command.ConnectCommand
+org.apache.karaf.instance.command.CreateCommand
+org.apache.karaf.instance.command.DestroyCommand
+org.apache.karaf.instance.command.ListCommand
+org.apache.karaf.instance.command.RenameCommand
+org.apache.karaf.instance.command.StartCommand
+org.apache.karaf.instance.command.StatusCommand
+org.apache.karaf.instance.command.StopCommand

http://git-wip-us.apache.org/repos/asf/karaf/blob/7c2db062/instance/src/main/resources/OSGI-INF/bundle.info
----------------------------------------------------------------------
diff --git a/instance/src/main/resources/OSGI-INF/bundle.info b/instance/src/main/resources/OSGI-INF/bundle.info
new file mode 100644
index 0000000..9d305c3
--- /dev/null
+++ b/instance/src/main/resources/OSGI-INF/bundle.info
@@ -0,0 +1,36 @@
+h1. Synopsis
+
+${project.name}
+
+${project.description}
+
+Maven URL:
+[mvn:${project.groupId}/${project.artifactId}/${project.version}]
+
+h1. Description
+
+This bundle is the core implementation of the Karaf instance feature.
+
+Karaf instance allows you to manage Karaf child instances.
+
+You can create new Karaf instances, configure attributes, rename instances, stop instances, etc.
+
+It also provides JMX MBeans related to the Karaf instance feature.
+
+In particular, an InstanceServiceMBean is provided that can be remotely administered using a JMX client (for instance
+JConsole).
+
+With this InstanceServiceMBean, you have the following operations available:
+* createInstance(name, sshPort, rmiPort, location, javaOpts, features, featureURLs) - Creates a new Karaf instance.
+* changeSshPort(name, port) - Changes the SSH port number of an existing Karaf instance.
+* changeRmiRegistryPort(name, port) - Changes the RMI registry port number of an existing Karaf instance.
+* changeRmiServerPort(name, port) - Changes the RMI server port number of an existing Karaf instance.
+* changeJavaOpts(name, javaopts) - Changes the Java options of an existing Karaf instance.
+* destroyInstance(name) - Destroys an existing Karaf instance.
+* startInstance(name) - Starts an existing Karaf instance.
+* stopInstance(name) - Stops an existing Karaf instance.
+* renameInstance(originalName, newName) - Renames an existing Karaf instance.
+
+h1. See also
+
+Managing child instances - of the Karaf User Guide.

http://git-wip-us.apache.org/repos/asf/karaf/blob/7c2db062/instance/src/main/resources/org/apache/karaf/instance/resources/bin/karaf
----------------------------------------------------------------------
diff --git a/instance/src/main/resources/org/apache/karaf/instance/resources/bin/karaf b/instance/src/main/resources/org/apache/karaf/instance/resources/bin/karaf
new file mode 100644
index 0000000..8967cea
--- /dev/null
+++ b/instance/src/main/resources/org/apache/karaf/instance/resources/bin/karaf
@@ -0,0 +1,25 @@
+#!/bin/sh
+################################################################################
+#
+#    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.
+#
+################################################################################
+
+KARAF_HOME=${SUBST-KARAF-HOME}
+KARAF_BASE=${SUBST-KARAF-BASE}
+
+export KARAF_BASE
+exec ${KARAF_HOME}/bin/karaf "$*"

http://git-wip-us.apache.org/repos/asf/karaf/blob/7c2db062/instance/src/main/resources/org/apache/karaf/instance/resources/bin/karaf.bat
----------------------------------------------------------------------
diff --git a/instance/src/main/resources/org/apache/karaf/instance/resources/bin/karaf.bat b/instance/src/main/resources/org/apache/karaf/instance/resources/bin/karaf.bat
new file mode 100644
index 0000000..e054d83
--- /dev/null
+++ b/instance/src/main/resources/org/apache/karaf/instance/resources/bin/karaf.bat
@@ -0,0 +1,25 @@
+@ECHO OFF
+REM =========================================================================
+REM
+REM Licensed to the Apache Software Foundation (ASF) under one or more
+REM contributor license agreements.  See the NOTICE file distributed with
+REM this work for additional information regarding copyright ownership.
+REM The ASF licenses this file to You under the Apache License, Version 2.0
+REM (the "License"); you may not use this file except in compliance with
+REM the License.  You may obtain a copy of the License at
+REM
+REM    http://www.apache.org/licenses/LICENSE-2.0
+REM
+REM Unless required by applicable law or agreed to in writing, software
+REM distributed under the License is distributed on an "AS IS" BASIS,
+REM WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+REM See the License for the specific language governing permissions and
+REM limitations under the License.
+REM
+REM =========================================================================
+
+SETLOCAL
+SET KARAF_HOME=${SUBST-KARAF-HOME}
+SET KARAF_BASE=${SUBST-KARAF-BASE}
+
+"%KARAF_HOME%\bin\karaf.bat" %*

http://git-wip-us.apache.org/repos/asf/karaf/blob/7c2db062/instance/src/main/resources/org/apache/karaf/instance/resources/bin/start
----------------------------------------------------------------------
diff --git a/instance/src/main/resources/org/apache/karaf/instance/resources/bin/start b/instance/src/main/resources/org/apache/karaf/instance/resources/bin/start
new file mode 100644
index 0000000..d45d749
--- /dev/null
+++ b/instance/src/main/resources/org/apache/karaf/instance/resources/bin/start
@@ -0,0 +1,25 @@
+#!/bin/sh
+################################################################################
+#
+#    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.
+#
+################################################################################
+
+KARAF_HOME=${SUBST-KARAF-HOME}
+KARAF_NAME=${SUBST-KARAF-NAME}
+
+exec ${KARAF_HOME}/bin/instance start ${KARAF_NAME} "$@"
+

http://git-wip-us.apache.org/repos/asf/karaf/blob/7c2db062/instance/src/main/resources/org/apache/karaf/instance/resources/bin/start.bat
----------------------------------------------------------------------
diff --git a/instance/src/main/resources/org/apache/karaf/instance/resources/bin/start.bat b/instance/src/main/resources/org/apache/karaf/instance/resources/bin/start.bat
new file mode 100644
index 0000000..0c530c8
--- /dev/null
+++ b/instance/src/main/resources/org/apache/karaf/instance/resources/bin/start.bat
@@ -0,0 +1,24 @@
+@ECHO OFF
+REM =========================================================================
+REM 
+REM Licensed to the Apache Software Foundation (ASF) under one or more
+REM contributor license agreements.  See the NOTICE file distributed with
+REM this work for additional information regarding copyright ownership.
+REM The ASF licenses this file to You under the Apache License, Version 2.0
+REM (the "License"); you may not use this file except in compliance with
+REM the License.  You may obtain a copy of the License at
+REM 
+REM    http://www.apache.org/licenses/LICENSE-2.0
+REM 
+REM Unless required by applicable law or agreed to in writing, software
+REM distributed under the License is distributed on an "AS IS" BASIS,
+REM WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+REM See the License for the specific language governing permissions and
+REM limitations under the License.
+REM 
+REM =========================================================================
+
+SET KARAF_HOME=${SUBST-KARAF-HOME}
+SET KARAF_NAME=${SUBST-KARAF-NAME}
+
+"%KARAF_HOME%\bin\instance.bat" start %KARAF_NAME%

http://git-wip-us.apache.org/repos/asf/karaf/blob/7c2db062/instance/src/main/resources/org/apache/karaf/instance/resources/bin/stop
----------------------------------------------------------------------
diff --git a/instance/src/main/resources/org/apache/karaf/instance/resources/bin/stop b/instance/src/main/resources/org/apache/karaf/instance/resources/bin/stop
new file mode 100644
index 0000000..fb91985
--- /dev/null
+++ b/instance/src/main/resources/org/apache/karaf/instance/resources/bin/stop
@@ -0,0 +1,25 @@
+#!/bin/sh
+################################################################################
+#
+#    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.
+#
+################################################################################
+
+KARAF_HOME=${SUBST-KARAF-HOME}
+KARAF_NAME=${SUBST-KARAF-NAME}
+
+exec ${KARAF_HOME}/bin/instance stop ${KARAF_NAME} "$@"
+

http://git-wip-us.apache.org/repos/asf/karaf/blob/7c2db062/instance/src/main/resources/org/apache/karaf/instance/resources/bin/stop.bat
----------------------------------------------------------------------
diff --git a/instance/src/main/resources/org/apache/karaf/instance/resources/bin/stop.bat b/instance/src/main/resources/org/apache/karaf/instance/resources/bin/stop.bat
new file mode 100644
index 0000000..8520acb
--- /dev/null
+++ b/instance/src/main/resources/org/apache/karaf/instance/resources/bin/stop.bat
@@ -0,0 +1,24 @@
+@ECHO OFF
+REM =========================================================================
+REM 
+REM Licensed to the Apache Software Foundation (ASF) under one or more
+REM contributor license agreements.  See the NOTICE file distributed with
+REM this work for additional information regarding copyright ownership.
+REM The ASF licenses this file to You under the Apache License, Version 2.0
+REM (the "License"); you may not use this file except in compliance with
+REM the License.  You may obtain a copy of the License at
+REM 
+REM    http://www.apache.org/licenses/LICENSE-2.0
+REM 
+REM Unless required by applicable law or agreed to in writing, software
+REM distributed under the License is distributed on an "AS IS" BASIS,
+REM WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+REM See the License for the specific language governing permissions and
+REM limitations under the License.
+REM 
+REM =========================================================================
+
+SET KARAF_HOME=${SUBST-KARAF-HOME}
+SET KARAF_NAME=${SUBST-KARAF-NAME}
+
+"%KARAF_HOME%\bin\instance.bat" stop %KARAF_NAME%

http://git-wip-us.apache.org/repos/asf/karaf/blob/7c2db062/instance/src/main/resources/org/apache/karaf/instance/resources/etc/org.apache.karaf.management.cfg
----------------------------------------------------------------------
diff --git a/instance/src/main/resources/org/apache/karaf/instance/resources/etc/org.apache.karaf.management.cfg b/instance/src/main/resources/org/apache/karaf/instance/resources/etc/org.apache.karaf.management.cfg
new file mode 100644
index 0000000..57b2957
--- /dev/null
+++ b/instance/src/main/resources/org/apache/karaf/instance/resources/etc/org.apache.karaf.management.cfg
@@ -0,0 +1,63 @@
+################################################################################
+#
+#    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.
+#
+################################################################################
+
+#
+# The properties in this file define the configuration of Apache Karaf's JMX Management
+#
+
+#
+# Port number for RMI registry connection
+#
+rmiRegistryPort = ${SUBST-RMI-REGISTRY-PORT}
+
+#
+# Port number for RMI server connection
+#
+rmiServerPort = ${SUBST-RMI-SERVER-PORT}
+
+#
+# Name of the JAAS realm used for authentication
+#
+jmxRealm = karaf
+
+#
+# The service URL for the JMXConnectorServer
+#
+serviceUrl = service:jmx:rmi://0.0.0.0:${rmiServerPort}/jndi/rmi://0.0.0.0:${rmiRegistryPort}/karaf-${karaf.name}
+
+#
+# Whether any threads started for the JMXConnectorServer should be started as daemon threads
+#
+daemon = true
+
+#
+# Whether the JMXConnectorServer should be started in a separate thread
+#
+threaded = true
+
+#
+# The ObjectName used to register the JMXConnectorServer
+#
+objectName = connector:name=rmi
+
+#
+# Role name used for JMX access authorization
+# If not set, this defaults to the ${karaf.admin.role} configured in etc/system.properties
+#
+# jmxRole=admin

http://git-wip-us.apache.org/repos/asf/karaf/blob/7c2db062/instance/src/main/resources/org/apache/karaf/instance/resources/etc/org.apache.karaf.shell.cfg
----------------------------------------------------------------------
diff --git a/instance/src/main/resources/org/apache/karaf/instance/resources/etc/org.apache.karaf.shell.cfg b/instance/src/main/resources/org/apache/karaf/instance/resources/etc/org.apache.karaf.shell.cfg
new file mode 100644
index 0000000..077f5da
--- /dev/null
+++ b/instance/src/main/resources/org/apache/karaf/instance/resources/etc/org.apache.karaf.shell.cfg
@@ -0,0 +1,75 @@
+################################################################################
+#
+#    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.
+#
+################################################################################
+
+#
+# These properties are used to configure Karaf's ssh shell.
+#
+
+#
+# Via sshPort and sshHost you define the address you can login into Karaf.
+#
+sshPort = ${SUBST-SSH-PORT}
+sshHost = 0.0.0.0
+
+#
+# The sshIdleTimeout defines the inactivity timeout to logout the SSH session.
+# The sshIdleTimeout is in milliseconds, and the default is set to 30 minutes.
+#
+sshIdleTimeout = 1800000
+
+#
+# sshRealm defines which JAAS domain to use for password authentication.
+#
+sshRealm = karaf
+
+#
+# The location of the hostKey file defines where the private/public key of the server
+# is located. If no file is at the defined location it will be ignored.
+#
+hostKey = ${karaf.etc}/host.key
+
+#
+# Role name used for SSH access authorization
+# If not set, this defaults to the ${karaf.admin.role} configured in etc/system.properties
+#
+# sshRole = admin
+
+#
+# Self defined key size in 1024, 2048, 3072, or 4096
+# If not set, this defaults to 1024.
+#
+# keySize = 1024
+
+#
+# Specify host key algorithm, defaults to DSA
+#
+# algorithm = DSA
+
+#
+# Defines the completion mode on the Karaf shell console. The possible values are:
+# - GLOBAL: it's the same behavior as in previous Karaf releases. The completion displays all commands and all aliases
+#           ignoring if you are in a subshell or not.
+# - FIRST: the completion displays all commands and all aliases only when you are not in a subshell. When you are
+#          in a subshell, the completion displays only the commands local to the subshell.
+# - SUBSHELL: the completion displays only the subshells on the root level. When you are in a subshell, the completion
+#             displays only the commands local to the subshell.
+# This property define the default value when you use the Karaf shell console.
+# You can change the completion mode directly in the shell console, using shell:completion command.
+#
+completionMode = GLOBAL
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/karaf/blob/7c2db062/instance/src/main/resources/org/apache/karaf/instance/resources/etc/system.properties
----------------------------------------------------------------------
diff --git a/instance/src/main/resources/org/apache/karaf/instance/resources/etc/system.properties b/instance/src/main/resources/org/apache/karaf/instance/resources/etc/system.properties
new file mode 100644
index 0000000..a683a34
--- /dev/null
+++ b/instance/src/main/resources/org/apache/karaf/instance/resources/etc/system.properties
@@ -0,0 +1,120 @@
+################################################################################
+#
+#    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.
+#
+################################################################################
+
+#
+# The properties defined in this file will be made available through system
+# properties at the very beginning of the Karaf's boot process.
+#
+
+
+# Log level when the pax-logging service is not available
+# This level will only be used while the pax-logging service bundle
+# is not fully available.
+# To change log levels, please refer to the org.ops4j.pax.logging.cfg file
+# instead.
+org.ops4j.pax.logging.DefaultServiceLog.level = ERROR
+
+#
+# Name of this Karaf instance.
+#
+karaf.name = ${SUBST-KARAF-NAME}
+
+#
+# Default repository where bundles will be loaded from before using
+# other Maven repositories.  For the full Maven configuration, see
+# the org.ops4j.pax.url.mvn.cfg file.
+#
+karaf.default.repository = system
+
+#
+# Location of a shell script that will be run when starting a shell
+# session.  This script can be used to create aliases and define
+# additional commands.
+#
+karaf.shell.init.script = ${karaf.etc}/shell.init.script
+
+#
+# Sets the maximum size of the shell command history. If not set,
+# defaults to 500 entries. Setting to 0 will disable history.
+#
+# karaf.shell.history.maxSize = 0
+
+#
+# Deletes the entire karaf.data directory at every start
+#
+karaf.clean.all = false
+
+#
+# Deletes the karaf.data/cache directory at every start
+#
+karaf.clean.cache = false
+
+#
+# Roles to use when logging into a local Karaf console.
+#
+# The syntax is the following:
+#   [classname:]principal
+# where classname is the class name of the principal object
+# (defaults to org.apache.karaf.jaas.modules.RolePrincipal)
+# and principal is the name of the principal of that class
+# (defaults to instance).
+#
+karaf.local.roles = admin,manager,viewer
+
+#
+# Set this empty property to avoid errors when validating xml documents.
+#
+xml.catalog.files =
+
+#
+# Suppress the bell in the console when hitting backspace too many times
+# for example
+#
+jline.nobell = true
+
+#
+# ServiceMix specs options
+#
+org.apache.servicemix.specs.debug = false
+org.apache.servicemix.specs.timeout = 100
+
+#
+# Settings for the OSGi 4.3 Weaving
+# By default, we will not weave any classes. Change this setting to include classes
+# that you application needs to have woven.
+#
+org.apache.aries.proxy.weaving.enabled = none
+# Classes not to weave - Aries default + Xerces which is known to have issues.
+org.apache.aries.proxy.weaving.disabled = org.objectweb.asm.*,org.slf4j.*,org.apache.log4j.*,javax.*,org.apache.xerces.*
+
+#
+# By default, only Karaf shell commands are secured, but additional services can be
+# secured by expanding this filter
+#
+karaf.secured.services = (&(osgi.command.scope=*)(osgi.command.function=*))
+
+#
+# Security properties
+#
+# To enable OSGi security, uncomment the properties below,
+# install the framework-security feature and restart.
+#
+#java.security.policy=${karaf.etc}/all.policy
+#org.osgi.framework.security=osgi
+#org.osgi.framework.trust.repositories=${karaf.etc}/trustStore.ks

http://git-wip-us.apache.org/repos/asf/karaf/blob/7c2db062/instance/src/main/resources/org/apache/karaf/jpm/impl/unix/start.sh
----------------------------------------------------------------------
diff --git a/instance/src/main/resources/org/apache/karaf/jpm/impl/unix/start.sh b/instance/src/main/resources/org/apache/karaf/jpm/impl/unix/start.sh
new file mode 100644
index 0000000..1d1d720
--- /dev/null
+++ b/instance/src/main/resources/org/apache/karaf/jpm/impl/unix/start.sh
@@ -0,0 +1,29 @@
+#!/bin/sh
+################################################################################
+#
+#    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.
+#
+################################################################################
+
+#exec 1>${out.file}
+#exec 2>${err.file}
+exec 1>/dev/null
+exec 2>/dev/null
+if [ "x${dir}" != "x" ]; then
+    cd ${dir}
+fi
+nohup ${command} &
+echo $! > ${pid.file}

http://git-wip-us.apache.org/repos/asf/karaf/blob/7c2db062/instance/src/main/resources/org/apache/karaf/jpm/impl/windows/destroy.vbs
----------------------------------------------------------------------
diff --git a/instance/src/main/resources/org/apache/karaf/jpm/impl/windows/destroy.vbs b/instance/src/main/resources/org/apache/karaf/jpm/impl/windows/destroy.vbs
new file mode 100644
index 0000000..abd60eb
--- /dev/null
+++ b/instance/src/main/resources/org/apache/karaf/jpm/impl/windows/destroy.vbs
@@ -0,0 +1,27 @@
+'===============================================================================
+'
+'    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.
+'
+'===============================================================================
+
+Set objWMIService = GetObject("winmgmts:\\.\root\cimv2")
+Set colProcessList = objWMIService.ExecQuery("Select * from Win32_Process Where ProcessId = ${pid}")
+intRetVal = 1
+For Each objProcess in colProcessList
+    objProcess.Terminate()
+    intRetVal = 0
+Next
+WScript.Quit(intRetVal)

http://git-wip-us.apache.org/repos/asf/karaf/blob/7c2db062/instance/src/main/resources/org/apache/karaf/jpm/impl/windows/running.vbs
----------------------------------------------------------------------
diff --git a/instance/src/main/resources/org/apache/karaf/jpm/impl/windows/running.vbs b/instance/src/main/resources/org/apache/karaf/jpm/impl/windows/running.vbs
new file mode 100644
index 0000000..32c65c5
--- /dev/null
+++ b/instance/src/main/resources/org/apache/karaf/jpm/impl/windows/running.vbs
@@ -0,0 +1,26 @@
+'===============================================================================
+'
+'    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.
+'
+'===============================================================================
+
+Set objWMIService = GetObject("winmgmts:\\.\root\cimv2")
+Set colProcessList = objWMIService.ExecQuery("Select * from Win32_Process Where ProcessId = ${pid}")
+intRetVal = 1
+For Each objProcess in colProcessList
+    intRetVal = 0
+Next
+WScript.Quit(intRetVal)

http://git-wip-us.apache.org/repos/asf/karaf/blob/7c2db062/instance/src/main/resources/org/apache/karaf/jpm/impl/windows/start.vbs
----------------------------------------------------------------------
diff --git a/instance/src/main/resources/org/apache/karaf/jpm/impl/windows/start.vbs b/instance/src/main/resources/org/apache/karaf/jpm/impl/windows/start.vbs
new file mode 100644
index 0000000..6004c86
--- /dev/null
+++ b/instance/src/main/resources/org/apache/karaf/jpm/impl/windows/start.vbs
@@ -0,0 +1,34 @@
+'===============================================================================
+'
+'    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.
+'
+'===============================================================================
+
+Set objWMIService = GetObject("winmgmts:\\.\root\cimv2")
+Set objConfig = objWMIService.Get("Win32_ProcessStartup").SpawnInstance_
+objConfig.ShowWindow = SW_HIDE
+objConfig.CreateFlags = 8
+If Len("${dir}") > 0 Then
+    intReturn = objWMIService.Get("Win32_Process").Create("${command}", "${dir}", objConfig, intProcessID)
+Else
+    intReturn = objWMIService.Get("Win32_Process").Create("${command}", Null, objConfig, intProcessID)
+End If
+If intReturn = 0 Then
+    Set objOutputFile = CreateObject("Scripting.fileSystemObject").CreateTextFile("${pid.file}", TRUE)
+    objOutputFile.WriteLine(intProcessID)
+    objOutputFile.Close
+End If
+WScript.Quit(intReturn)

http://git-wip-us.apache.org/repos/asf/karaf/blob/7c2db062/instance/src/test/java/org/apache/karaf/instance/command/CreateCommandTest.java
----------------------------------------------------------------------
diff --git a/instance/src/test/java/org/apache/karaf/instance/command/CreateCommandTest.java b/instance/src/test/java/org/apache/karaf/instance/command/CreateCommandTest.java
new file mode 100644
index 0000000..359a183
--- /dev/null
+++ b/instance/src/test/java/org/apache/karaf/instance/command/CreateCommandTest.java
@@ -0,0 +1,57 @@
+/*
+ * 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.karaf.instance.command;
+
+import java.util.Arrays;
+import java.util.Collections;
+
+import junit.framework.TestCase;
+
+import org.apache.karaf.instance.core.InstanceService;
+import org.apache.karaf.instance.core.InstanceSettings;
+import org.easymock.EasyMock;
+
+public class CreateCommandTest extends TestCase {
+
+    public void testCreateCommandExecute() throws Exception {
+        InstanceService instanceService = EasyMock.createMock(InstanceService.class);
+        EasyMock.replay(instanceService);
+        
+        CreateCommand cc = new CreateCommand();
+        cc.setInstanceService(instanceService);
+        cc.sshPort = 9941;
+        cc.rmiRegistryPort = 1122;
+        cc.rmiServerPort = 44444;
+        cc.location = "top";
+        cc.javaOpts = "foo";
+        cc.features = Arrays.asList("abc", "def");
+        cc.featureURLs = Collections.singletonList("http://something");
+        cc.instance = "myInstance";
+        cc.verbose = true;
+        
+        EasyMock.verify(instanceService); // check precondition
+        EasyMock.reset(instanceService);
+        InstanceSettings expectedIS =
+            new InstanceSettings(9941, 1122, 44444, "top", "foo", Collections.singletonList("http://something"), Arrays.asList("abc", "def"));
+        EasyMock.expect(instanceService.createInstance("myInstance", expectedIS, true)).andReturn(null);
+        EasyMock.replay(instanceService);
+        
+        cc.doExecute();
+        EasyMock.verify(instanceService);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/7c2db062/instance/src/test/java/org/apache/karaf/instance/core/InstanceSettingsTest.java
----------------------------------------------------------------------
diff --git a/instance/src/test/java/org/apache/karaf/instance/core/InstanceSettingsTest.java b/instance/src/test/java/org/apache/karaf/instance/core/InstanceSettingsTest.java
new file mode 100644
index 0000000..264176b
--- /dev/null
+++ b/instance/src/test/java/org/apache/karaf/instance/core/InstanceSettingsTest.java
@@ -0,0 +1,58 @@
+/*
+ * 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.karaf.instance.core;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import junit.framework.TestCase;
+
+import org.apache.karaf.instance.core.InstanceSettings;
+import org.junit.Assert;
+
+public class InstanceSettingsTest extends TestCase {
+    public void testInstanceSettings() {
+        InstanceSettings is =
+            new InstanceSettings(1, 1, 1, null, null, Collections.<String>emptyList(), Arrays.asList("hi"));
+        assertEquals(1, is.getSshPort());
+        assertEquals(1, is.getRmiRegistryPort());
+        assertEquals(1, is.getRmiServerPort());
+        Assert.assertNull(is.getLocation());
+        assertEquals(Arrays.asList("hi"), is.getFeatures());
+        assertEquals(0, is.getFeatureURLs().size());
+    }
+    
+    public void testEqualsHashCode() {
+        testEqualsHashCode(1, 1, 1, "top", "foo", Collections.<String>emptyList(), Arrays.asList("hi"));
+        testEqualsHashCode(0, 0, 0, null, null, null, null);
+    }
+
+    private void testEqualsHashCode(int sshPort, int rmiRegistryPort, int rmiServerPort, String location, String javaOpts, List<String> featureURLs, List<String> features) {
+        InstanceSettings is = new InstanceSettings(sshPort, rmiRegistryPort, rmiServerPort, location, javaOpts, featureURLs, features);
+        InstanceSettings is2 = new InstanceSettings(sshPort, rmiRegistryPort, rmiServerPort, location, javaOpts, featureURLs, features);
+        assertEquals(is, is2);
+        assertEquals(is.hashCode(), is2.hashCode());
+    }
+    
+    public void testEqualsHashCode2() {
+        InstanceSettings is = new InstanceSettings(1, 1, 1, "top", "foo", Collections.<String>emptyList(), Arrays.asList("hi"));
+        Assert.assertFalse(is.equals(null));
+        Assert.assertFalse(is.equals(new Object()));
+        assertEquals(is, is);
+    }
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/7c2db062/instance/src/test/java/org/apache/karaf/instance/core/internal/InstanceServiceImplTest.java
----------------------------------------------------------------------
diff --git a/instance/src/test/java/org/apache/karaf/instance/core/internal/InstanceServiceImplTest.java b/instance/src/test/java/org/apache/karaf/instance/core/internal/InstanceServiceImplTest.java
new file mode 100644
index 0000000..9c77934
--- /dev/null
+++ b/instance/src/test/java/org/apache/karaf/instance/core/internal/InstanceServiceImplTest.java
@@ -0,0 +1,187 @@
+/*
+ * 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.karaf.instance.core.internal;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Arrays;
+import java.util.Properties;
+
+import org.apache.karaf.instance.core.Instance;
+import org.apache.karaf.instance.core.InstanceSettings;
+import org.junit.BeforeClass;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+import org.junit.rules.TestName;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+public class InstanceServiceImplTest {
+
+    @Rule
+    public TestName name = new TestName();
+
+    @Rule
+    public TemporaryFolder tempFolder = new TemporaryFolder();
+
+    @BeforeClass
+    public static void setUpClass() throws Exception {
+        String buildDirectory = ClassLoader.getSystemResource("etc/startup.properties").getFile()
+                .replace("startup.properties", "");
+        System.setProperty("karaf.etc", buildDirectory);
+    }
+
+    @Test
+    public void testHandleFeatures() throws Exception {
+        InstanceServiceImpl as = new InstanceServiceImpl();
+
+        File f = tempFolder.newFile(getName() + ".test");
+        Properties p = new Properties();
+        p.put("featuresBoot", "abc,def ");
+        p.put("featuresRepositories", "somescheme://xyz");
+        OutputStream os = new FileOutputStream(f);
+        try {
+            p.store(os, "Test comment");
+        } finally {
+            os.close();
+        }
+
+        InstanceSettings s = new InstanceSettings(8122, 1122, 44444, null, null, null, Arrays.asList("test"));
+        as.addFeaturesFromSettings(f, s);
+
+        Properties p2 = new Properties();
+        InputStream is = new FileInputStream(f);
+        try {
+            p2.load(is);
+        } finally {
+            is.close();
+        }
+        assertEquals(2, p2.size());
+        assertEquals("abc,def,test", p2.get("featuresBoot"));
+        assertEquals("somescheme://xyz", p2.get("featuresRepositories"));
+    }
+
+    @Test
+    public void testConfigurationFiles() throws Exception {
+        InstanceServiceImpl service = new InstanceServiceImpl();
+        service.setStorageLocation(tempFolder.newFolder("instances"));
+
+        InstanceSettings settings = new InstanceSettings(8122, 1122, 44444, getName(), null, null, null);
+        Instance instance = service.createInstance(getName(), settings, true);
+
+        assertFileExists(instance.getLocation(), "etc/config.properties");
+        assertFileExists(instance.getLocation(), "etc/users.properties");
+        assertFileExists(instance.getLocation(), "etc/startup.properties");
+
+        assertFileExists(instance.getLocation(), "etc/java.util.logging.properties");
+        assertFileExists(instance.getLocation(), "etc/org.apache.karaf.features.cfg");
+        assertFileExists(instance.getLocation(), "etc/org.apache.felix.fileinstall-deploy.cfg");
+        assertFileExists(instance.getLocation(), "etc/org.apache.karaf.log.cfg");
+        assertFileExists(instance.getLocation(), "etc/org.apache.karaf.management.cfg");
+        assertFileExists(instance.getLocation(), "etc/org.ops4j.pax.logging.cfg");
+        assertFileExists(instance.getLocation(), "etc/org.ops4j.pax.url.mvn.cfg");
+    }
+
+    /**
+     * <p>
+     * Test the renaming of an existing instance.
+     * </p>
+     */
+    @Test
+    public void testRenameInstance() throws Exception {
+        InstanceServiceImpl service = new InstanceServiceImpl();
+        service.setStorageLocation(tempFolder.newFolder("instances"));
+
+        InstanceSettings settings = new InstanceSettings(8122, 1122, 44444, getName(), null, null, null);
+        service.createInstance(getName(), settings, true);
+
+        service.renameInstance(getName(), getName() + "b", true);
+        assertNotNull(service.getInstance(getName() + "b"));
+    }
+
+    /**
+     * <p>
+     * Test the renaming of an existing instance.
+     * </p>
+     */
+    @Test
+    public void testToSimulateRenameInstanceByExternalProcess() throws Exception {
+        InstanceServiceImpl service = new InstanceServiceImpl();
+        File storageLocation = tempFolder.newFolder("instances");
+        service.setStorageLocation(storageLocation);
+
+        InstanceSettings settings = new InstanceSettings(8122, 1122, 44444, getName(), null, null, null);
+        service.createInstance(getName(), settings, true);
+        
+        //to simulate the scenario that the instance name get changed by 
+        //external process, likely the admin command CLI tool, which cause
+        //the instance storage file get updated, the AdminService should be 
+        //able to reload the storage file before check any status for the 
+        //instance
+        
+        File storageFile = new File(storageLocation, InstanceServiceImpl.STORAGE_FILE);
+        assertTrue(storageFile.isFile());
+        Properties storage = loadStorage(storageFile);
+        storage.setProperty("item.0.name", getName() + "b");
+        saveStorage(storage, storageFile, "testToSimulateRenameInstanceByExternalProcess");
+        
+        assertNotNull(service.getInstance(getName() + "b"));
+    }
+
+    private String getName() {
+        return name.getMethodName();
+    }
+
+    private void saveStorage(Properties props, File location, String comment) throws IOException {
+        OutputStream os = null;
+        try {
+            os = new FileOutputStream(location);
+            props.store(os, comment);
+        } finally {
+            if (os != null) {
+                os.close();
+            }
+        }
+    }
+    
+    private Properties loadStorage(File location) throws IOException {
+        InputStream is = null;
+        try {
+            is = new FileInputStream(location);
+            Properties props = new Properties();
+            props.load(is);
+            return props;
+        } finally {
+            if (is != null) {
+                is.close();
+            }
+        }
+    }
+
+    private void assertFileExists(String path, String name) throws IOException {
+        File file = new File(path, name);
+        assertTrue("Expected " + file.getCanonicalPath() + " to exist",
+                   file.exists());
+    }   
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/7c2db062/instance/src/test/java/org/apache/karaf/instance/core/management/internal/InstanceServiceMBeanImplTest.java
----------------------------------------------------------------------
diff --git a/instance/src/test/java/org/apache/karaf/instance/core/management/internal/InstanceServiceMBeanImplTest.java b/instance/src/test/java/org/apache/karaf/instance/core/management/internal/InstanceServiceMBeanImplTest.java
new file mode 100644
index 0000000..bb67041
--- /dev/null
+++ b/instance/src/test/java/org/apache/karaf/instance/core/management/internal/InstanceServiceMBeanImplTest.java
@@ -0,0 +1,239 @@
+/*
+ * 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.karaf.instance.core.management.internal;
+
+import java.util.Arrays;
+import java.util.Collections;
+
+import javax.management.openmbean.CompositeData;
+import javax.management.openmbean.TabularData;
+
+import junit.framework.TestCase;
+
+import org.apache.karaf.instance.core.Instance;
+import org.apache.karaf.instance.core.InstanceService;
+import org.apache.karaf.instance.core.InstanceSettings;
+import org.apache.karaf.instance.core.InstancesMBean;
+import org.apache.karaf.instance.core.internal.InstancesMBeanImpl;
+import org.easymock.EasyMock;
+import org.junit.Assert;
+
+public class InstanceServiceMBeanImplTest extends TestCase {
+
+    public void testCreateInstance() throws Exception {
+        final InstanceSettings instanceSettings = new InstanceSettings(123, 456,789, "somewhere", "someopts",
+                Collections.<String>emptyList(), Arrays.asList("webconsole", "funfeat"));
+        
+        final Instance inst = EasyMock.createMock(Instance.class);
+        EasyMock.expect(inst.getPid()).andReturn(42);
+        EasyMock.replay(inst);
+
+        org.apache.karaf.instance.core.InstanceService instanceService = EasyMock.createMock(org.apache.karaf.instance.core.InstanceService.class);
+        EasyMock.expect(instanceService.createInstance("t1", instanceSettings, false)).andReturn(inst);
+        EasyMock.replay(instanceService);
+        
+        InstancesMBeanImpl ab = new InstancesMBeanImpl(instanceService);
+        assertEquals(42, ab.createInstance("t1", 123, 456, 789, "somewhere", "someopts", " webconsole,  funfeat", ""));
+    }
+    
+    public void testCreateInstance2() throws Exception {
+        final InstanceSettings instanceSettings = new InstanceSettings(0, 0, 0, null, null,
+                Collections.<String>emptyList(), Collections.<String>emptyList());
+        
+        InstanceService instanceService = EasyMock.createMock(InstanceService.class);
+        EasyMock.expect(instanceService.createInstance("t1", instanceSettings, false)).andReturn(null);
+        EasyMock.replay(instanceService);
+        
+        InstancesMBean ab = new InstancesMBeanImpl(instanceService);
+        assertEquals(-1, ab.createInstance("t1", 0, 0, 0, "", "", "", ""));
+    }
+    
+    public void testGetInstances() throws Exception {       
+        Instance i1 = EasyMock.createMock(Instance.class);
+        EasyMock.expect(i1.getPid()).andReturn(1234);
+        EasyMock.expect(i1.getSshPort()).andReturn(8818);
+        EasyMock.expect(i1.getRmiRegistryPort()).andReturn(1122);
+        EasyMock.expect(i1.getRmiServerPort()).andReturn(44444);
+        EasyMock.expect(i1.getName()).andReturn("i1");
+        EasyMock.expect(i1.isRoot()).andReturn(true);
+        EasyMock.expect(i1.getLocation()).andReturn("somewhere");
+        EasyMock.expect(i1.getJavaOpts()).andReturn("someopts");
+        EasyMock.expect(i1.getState()).andReturn("Stopped");
+        EasyMock.replay(i1);
+        Instance i2 = EasyMock.createNiceMock(Instance.class);
+        EasyMock.expect(i2.getName()).andReturn("i2");
+        EasyMock.replay(i2);
+        
+        InstanceService instanceService = EasyMock.createMock(InstanceService.class);
+        EasyMock.expect(instanceService.getInstances()).andReturn(new Instance[]{i1, i2});
+        EasyMock.replay(instanceService);
+
+        InstancesMBeanImpl instanceServiceMBean = new InstancesMBeanImpl(instanceService);
+        TabularData tabularData = instanceServiceMBean.getInstances();
+        Assert.assertEquals(2, tabularData.size());
+        CompositeData cd1 = tabularData.get(new Object[]{"i1"});
+        Assert.assertTrue(cd1.containsValue("i1"));
+        Assert.assertTrue(cd1.containsValue(true));
+        Assert.assertTrue(cd1.containsValue(1234));
+        Assert.assertTrue(cd1.containsValue(8818));
+        Assert.assertTrue(cd1.containsValue(1122));
+        Assert.assertTrue(cd1.containsValue(44444));
+        Assert.assertTrue(cd1.containsValue("somewhere"));
+        Assert.assertTrue(cd1.containsValue("someopts"));
+        Assert.assertTrue(cd1.containsValue("Stopped"));
+
+        CompositeData cd2 = tabularData.get(new Object [] {"i2"});
+        Assert.assertTrue(cd2.containsValue("i2"));
+    }
+    
+    public void testStartInstanceWithJavaOpts() throws Exception {
+        Instance inst = EasyMock.createMock(Instance.class);
+        inst.start("-x -y -z");
+        EasyMock.expectLastCall();
+        EasyMock.replay(inst);
+
+        InstanceService instanceService = EasyMock.createMock(InstanceService.class);
+        EasyMock.expect(instanceService.getInstance("test instance")).andReturn(inst);
+        EasyMock.replay(instanceService);
+
+        InstancesMBean instanceServiceMBean = new InstancesMBeanImpl(instanceService);
+
+        instanceServiceMBean.startInstance("test instance", "-x -y -z");
+        EasyMock.verify(instanceService);
+        EasyMock.verify(inst);
+    }
+
+    public void testStartInstanceWithNoJavaOpts() throws Exception {
+        Instance inst = EasyMock.createMock(Instance.class);
+        inst.start(null);
+        EasyMock.expectLastCall();
+        EasyMock.replay(inst);
+
+        InstanceService instanceService = EasyMock.createMock(InstanceService.class);
+        EasyMock.expect(instanceService.getInstance("test instance")).andReturn(inst);
+        EasyMock.replay(instanceService);
+
+        InstancesMBean instanceServiceMBean = new InstancesMBeanImpl(instanceService);
+
+        instanceServiceMBean.startInstance("test instance", null);
+        EasyMock.verify(instanceService);
+        EasyMock.verify(inst);
+    }
+
+    public void testStopInstance() throws Exception {
+        Instance inst = EasyMock.createMock(Instance.class);
+        inst.stop();
+        EasyMock.expectLastCall();
+        EasyMock.replay(inst);
+
+        InstanceService instanceService = EasyMock.createMock(InstanceService.class);
+        EasyMock.expect(instanceService.getInstance("test instance")).andReturn(inst);
+        EasyMock.replay(instanceService);
+        
+        InstancesMBean instanceServiceMBean = new InstancesMBeanImpl(instanceService);
+
+        instanceServiceMBean.stopInstance("test instance");
+        EasyMock.verify(instanceService);
+        EasyMock.verify(inst);
+    }
+
+    public void testDestroyInstance() throws Exception {
+        Instance inst = EasyMock.createMock(Instance.class);
+        inst.destroy();
+        EasyMock.expectLastCall();
+        EasyMock.replay(inst);
+
+        InstanceService instanceService = EasyMock.createMock(InstanceService.class);
+        EasyMock.expect(instanceService.getInstance("test instance")).andReturn(inst);
+        EasyMock.replay(instanceService);
+        
+        InstancesMBean instanceServiceMBean = new InstancesMBeanImpl(instanceService);
+
+        instanceServiceMBean.destroyInstance("test instance");
+        EasyMock.verify(instanceService);
+        EasyMock.verify(inst);
+    }
+
+    public void testSshChangePort() throws Exception {
+        Instance inst = EasyMock.createMock(Instance.class);
+        inst.changeSshPort(7788);
+        EasyMock.expectLastCall();
+        EasyMock.replay(inst);
+
+        InstanceService instanceService = EasyMock.createMock(InstanceService.class);
+        EasyMock.expect(instanceService.getInstance("test instance")).andReturn(inst);
+        EasyMock.replay(instanceService);
+        
+        InstancesMBean instanceServiceMBean = new InstancesMBeanImpl(instanceService);
+
+        instanceServiceMBean.changeSshPort("test instance", 7788);
+        EasyMock.verify(instanceService);
+        EasyMock.verify(inst);
+    }
+    
+    public void testRmiRegistryChangePort() throws Exception {
+        Instance inst = EasyMock.createMock(Instance.class);
+        inst.changeRmiRegistryPort(1123);
+        EasyMock.expectLastCall();
+        EasyMock.replay(inst);
+        
+        InstanceService instanceService = EasyMock.createMock(InstanceService.class);
+        EasyMock.expect(instanceService.getInstance("test instance")).andReturn(inst);
+        EasyMock.replay(instanceService);
+        
+        InstancesMBean instanceServiceMBean = new InstancesMBeanImpl(instanceService);
+        
+        instanceServiceMBean.changeRmiRegistryPort("test instance", 1123);
+        EasyMock.verify(instanceService);
+        EasyMock.verify(inst);
+    }
+
+    public void testRmiServerChangePort() throws Exception {
+        Instance inst = EasyMock.createMock(Instance.class);
+        inst.changeRmiServerPort(44444);
+        EasyMock.expectLastCall();
+        EasyMock.replay(inst);
+
+        InstanceService instanceService = EasyMock.createMock(InstanceService.class);
+        EasyMock.expect(instanceService.getInstance("test instance")).andReturn(inst);
+        EasyMock.replay(instanceService);
+
+        InstancesMBean instanceServiceMBean = new InstancesMBeanImpl(instanceService);
+
+        instanceServiceMBean.changeRmiServerPort("test instance", 44444);
+        EasyMock.verify(instanceService);
+        EasyMock.verify(inst);
+    }
+
+    public void testChangeOptions() throws Exception {
+        Instance inst = EasyMock.createMock(Instance.class);
+        inst.changeJavaOpts("new opts");
+        EasyMock.expectLastCall();
+        EasyMock.replay(inst);
+
+        InstanceService instanceService = EasyMock.createMock(InstanceService.class);
+        EasyMock.expect(instanceService.getInstance("test instance")).andReturn(inst);
+        EasyMock.replay(instanceService);
+
+        InstancesMBean instanceServiceMBean = new InstancesMBeanImpl(instanceService);
+
+        instanceServiceMBean.changeJavaOpts("test instance", "new opts");
+        EasyMock.verify(instanceService);
+        EasyMock.verify(inst);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/7c2db062/instance/src/test/java/org/apache/karaf/instance/core/management/internal/InstanceToTableMapperTest.java
----------------------------------------------------------------------
diff --git a/instance/src/test/java/org/apache/karaf/instance/core/management/internal/InstanceToTableMapperTest.java b/instance/src/test/java/org/apache/karaf/instance/core/management/internal/InstanceToTableMapperTest.java
new file mode 100644
index 0000000..c9541d3
--- /dev/null
+++ b/instance/src/test/java/org/apache/karaf/instance/core/management/internal/InstanceToTableMapperTest.java
@@ -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.karaf.instance.core.management.internal;
+
+import java.util.Collection;
+import java.util.Collections;
+
+import javax.management.openmbean.CompositeData;
+import javax.management.openmbean.TabularData;
+
+import junit.framework.TestCase;
+
+import org.apache.karaf.instance.core.Instance;
+import org.apache.karaf.instance.core.internal.InstanceToTableMapper;
+import org.easymock.EasyMock;
+import org.junit.Assert;
+
+public class InstanceToTableMapperTest extends TestCase {
+    public void testJMXInstance() throws Exception {
+        Instance instance = EasyMock.createMock(Instance.class);
+        EasyMock.expect(instance.getPid()).andReturn(1712);
+        EasyMock.expect(instance.getName()).andReturn("MyInstance");
+        EasyMock.expect(instance.isRoot()).andReturn(false);
+        EasyMock.expect(instance.getSshPort()).andReturn(0);
+        EasyMock.expect(instance.getRmiRegistryPort()).andReturn(0);
+        EasyMock.expect(instance.getRmiServerPort()).andReturn(0);
+        EasyMock.expect(instance.getState()).andThrow(new Exception("gotcha"));
+        EasyMock.expect(instance.getLocation()).andReturn("somewhere");
+        EasyMock.expect(instance.getJavaOpts()).andReturn("someopts");
+        EasyMock.replay(instance);
+        
+        TabularData td = InstanceToTableMapper.tableFrom(Collections.singletonList(instance));
+        Collection<?> keys = (Collection<?>) td.keySet().iterator().next();
+        Assert.assertEquals("MyInstance", keys.iterator().next());
+        
+        CompositeData cd = td.get(keys.toArray());
+        Assert.assertEquals(1712, cd.get("Pid"));
+        Assert.assertEquals("MyInstance", cd.get("Name"));
+        Assert.assertEquals(false, cd.get("Is Root"));
+        Assert.assertEquals(0, cd.get("SSH Port"));
+        Assert.assertEquals(0, cd.get("RMI Registry Port"));
+        Assert.assertEquals(0, cd.get("RMI Server Port"));
+        Assert.assertEquals("Error", cd.get("State"));
+        Assert.assertEquals("somewhere", cd.get("Location"));
+        Assert.assertEquals("someopts", cd.get("JavaOpts"));
+    }
+
+    public void testJMXInstance2() throws Exception {
+        Instance instance = EasyMock.createMock(Instance.class);
+        EasyMock.expect(instance.getPid()).andReturn(1712);
+        EasyMock.expect(instance.getName()).andReturn("MyInstance");
+        EasyMock.expect(instance.isRoot()).andReturn(true);
+        EasyMock.expect(instance.getSshPort()).andReturn(0);
+        EasyMock.expect(instance.getRmiRegistryPort()).andReturn(0);
+        EasyMock.expect(instance.getRmiServerPort()).andReturn(0);
+        EasyMock.expect(instance.getState()).andReturn("Started");
+        EasyMock.expect(instance.getLocation()).andReturn(null);
+        EasyMock.expect(instance.getJavaOpts()).andReturn(null);
+        EasyMock.replay(instance);
+        
+        TabularData td = InstanceToTableMapper.tableFrom(Collections.singletonList(instance));        
+        Collection<?> keys = (Collection<?>) td.keySet().iterator().next();
+        Assert.assertEquals("MyInstance", keys.iterator().next());
+        
+        CompositeData cd = td.get(keys.toArray());
+        Assert.assertEquals(1712, cd.get("Pid"));
+        Assert.assertEquals("MyInstance", cd.get("Name"));
+        Assert.assertEquals(true, cd.get("Is Root"));
+        Assert.assertEquals(0, cd.get("SSH Port"));
+        Assert.assertEquals(0, cd.get("RMI Registry Port"));
+        Assert.assertEquals(0, cd.get("RMI Server Port"));
+        Assert.assertEquals("Started", cd.get("State"));
+        Assert.assertNull(cd.get("Location"));
+        Assert.assertNull(cd.get("JavaOpts"));
+    }
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/7c2db062/instance/src/test/java/org/apache/karaf/instance/main/ExecuteTest.java
----------------------------------------------------------------------
diff --git a/instance/src/test/java/org/apache/karaf/instance/main/ExecuteTest.java b/instance/src/test/java/org/apache/karaf/instance/main/ExecuteTest.java
new file mode 100644
index 0000000..1e49a88
--- /dev/null
+++ b/instance/src/test/java/org/apache/karaf/instance/main/ExecuteTest.java
@@ -0,0 +1,126 @@
+/*
+ * 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.karaf.instance.main;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.PrintStream;
+import java.io.IOException;
+import java.util.Properties;
+
+import junit.framework.TestCase;
+
+public class ExecuteTest extends TestCase {
+    private String userDir;
+    
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        Execute.exitAllowed = false;
+        userDir = System.getProperty("user.dir");
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        super.tearDown();
+        Execute.exitAllowed = true;
+        System.setProperty("user.dir", userDir);
+    }
+
+    public void testListCommands() throws Exception {
+        PrintStream oldOut = System.out;
+        
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        PrintStream capturedOut = new PrintStream(baos); 
+        System.setOut(capturedOut);
+
+        try {
+            Execute.main(new String [] {});            
+        } catch (RuntimeException re) {
+            assertEquals("0", re.getMessage());
+
+            String s = new String(baos.toByteArray());            
+            assertTrue(s.contains("list"));
+            assertTrue(s.contains("create"));
+            assertTrue(s.contains("destroy"));
+        } finally {
+            System.setOut(oldOut);
+        }
+    }
+    
+    public void testNonexistingCommand() throws Exception {
+        try {
+            Execute.main(new String [] {"bheuaark"});
+        } catch (RuntimeException re) {
+            assertEquals("-1", re.getMessage());
+        }
+    }
+    
+    public void testNoStorageFile() throws Exception {
+        PrintStream oldErr = System.err;
+        
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        PrintStream capturedErr = new PrintStream(baos); 
+        System.setErr(capturedErr);
+
+        try {
+            Execute.main(new String [] {"create"});            
+        } catch (RuntimeException re) {
+            assertEquals("-2", re.getMessage());
+            
+            String s = new String(baos.toByteArray());            
+            assertTrue(s.contains("karaf.instances"));
+            assertTrue(s.contains("instance.properties"));
+        } finally {
+            System.setErr(oldErr);
+        } 
+    }
+    
+    public void testSetDir() throws Exception {
+        Properties oldProps = (Properties) System.getProperties().clone();
+        final File tempFile = createTempDir(getName());
+        assertFalse("Precondition failed", 
+            tempFile.getParentFile().getParentFile().getCanonicalPath().equals(System.getProperty("user.dir")));
+
+        System.setProperty("karaf.instances", tempFile.getCanonicalPath());
+        try {
+            Execute.main(new String [] {"list"});            
+            assertTrue(tempFile.getParentFile().getParentFile().getCanonicalPath().equals(System.getProperty("user.dir")));
+        } finally {
+            System.setProperties(oldProps);
+            assertNull("Postcondition failed", System.getProperty("karaf.instances"));
+            delete(tempFile);
+        }        
+    }
+    
+    private static File createTempDir(String name) throws IOException {
+        final File tempFile = File.createTempFile(name, null);
+        tempFile.delete();
+        tempFile.mkdirs();
+        return tempFile.getCanonicalFile();
+    }
+
+    private static void delete(File tmp) {
+        if (tmp.isDirectory()) {
+            for (File f : tmp.listFiles()) {
+                delete(f);
+            }
+        }
+        tmp.delete();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/7c2db062/instance/src/test/java/org/apache/karaf/jpm/MainTest.java
----------------------------------------------------------------------
diff --git a/instance/src/test/java/org/apache/karaf/jpm/MainTest.java b/instance/src/test/java/org/apache/karaf/jpm/MainTest.java
new file mode 100644
index 0000000..e7f7c83
--- /dev/null
+++ b/instance/src/test/java/org/apache/karaf/jpm/MainTest.java
@@ -0,0 +1,24 @@
+/*
+ * 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.karaf.jpm;
+
+public class MainTest {
+
+    public static void main(String[] args) throws Exception {
+        Thread.sleep(Long.parseLong(args[0]));
+    }
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/7c2db062/instance/src/test/java/org/apache/karaf/jpm/ProcessTest.java
----------------------------------------------------------------------
diff --git a/instance/src/test/java/org/apache/karaf/jpm/ProcessTest.java b/instance/src/test/java/org/apache/karaf/jpm/ProcessTest.java
new file mode 100644
index 0000000..9cdc5ad
--- /dev/null
+++ b/instance/src/test/java/org/apache/karaf/jpm/ProcessTest.java
@@ -0,0 +1,69 @@
+/*
+ * 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.karaf.jpm;
+
+import java.io.File;
+
+import junit.framework.TestCase;
+
+import org.apache.karaf.jpm.impl.ProcessBuilderFactoryImpl;
+import org.apache.karaf.jpm.impl.ScriptUtils;
+
+public class ProcessTest extends TestCase {
+
+    public void testCreate() throws Exception {
+        String javaPath = new File(System.getProperty("java.home"), ScriptUtils.isWindows() ? "bin\\java.exe" : "bin/java").getCanonicalPath();
+        System.err.println(javaPath);
+        StringBuilder command = new StringBuilder();
+        command.append("\"").append(javaPath).append("\"");
+        command.append(" -Dprop=\"key\"");
+        command.append(" -classpath ");
+        String clRes = getClass().getName().replace('.', '/') + ".class";
+        String str = getClass().getClassLoader().getResource(clRes).toString();
+        str = str.substring("file:".length(), str.indexOf(clRes));
+        command.append(str);
+        command.append(" ");
+        command.append(MainTest.class.getName());
+        command.append(" ");
+        command.append(60000);
+        System.err.println("Executing: " + command.toString());
+
+        ProcessBuilder builder = new ProcessBuilderFactoryImpl().newBuilder();
+        org.apache.karaf.jpm.Process p = builder.command(command.toString()).start();
+        assertNotNull(p);
+        System.err.println("Process: " + p.getPid());
+        assertNotNull(p.getPid());
+        Thread.sleep(1000);
+        System.err.println("Running: " + p.isRunning());
+        assertTrue(p.isRunning());
+        System.err.println("Destroying");
+        p.destroy();
+        Thread.sleep(1000);
+        System.err.println("Running: " + p.isRunning());
+        assertFalse(p.isRunning());
+    }
+
+    /*
+     * When the process creation fails, no error is reported by the script
+     * 
+    public void testFailure() throws Exception {
+        ProcessBuilder builder = ProcessBuilderFactory.newInstance().newBuilder();
+        Process p = builder.command("ec").start();
+        fail("An exception should have been thrown");
+    }
+    */
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/7c2db062/instance/src/test/resources/etc/startup.properties
----------------------------------------------------------------------
diff --git a/instance/src/test/resources/etc/startup.properties b/instance/src/test/resources/etc/startup.properties
new file mode 100644
index 0000000..df7c9bc
--- /dev/null
+++ b/instance/src/test/resources/etc/startup.properties
@@ -0,0 +1,20 @@
+################################################################################
+#
+#    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.
+#
+################################################################################
+
+# Fake startup.properties for unit tests as the startup properties in generated by the karaf-maven-plugin
\ No newline at end of file


[58/59] [abbrv] git commit: [KARAF-2852] Merge jndi/core and jndi/command

Posted by gn...@apache.org.
[KARAF-2852] Merge jndi/core and jndi/command

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

Branch: refs/heads/master
Commit: 85c65dd697e437ffc28c9c768090a0b0d8741686
Parents: 1bcdb17
Author: Guillaume Nodet <gn...@gmail.com>
Authored: Thu Apr 10 10:20:22 2014 +0200
Committer: Guillaume Nodet <gn...@gmail.com>
Committed: Thu Apr 10 16:03:15 2014 +0200

----------------------------------------------------------------------
 .../enterprise/src/main/feature/feature.xml     |   1 -
 jndi/NOTICE                                     |  71 +++++
 jndi/command/NOTICE                             |  71 -----
 jndi/command/pom.xml                            |  87 ------
 .../apache/karaf/jndi/command/AliasCommand.java |  50 ---
 .../apache/karaf/jndi/command/BindCommand.java  |  50 ---
 .../karaf/jndi/command/ContextsCommand.java     |  64 ----
 .../karaf/jndi/command/CreateCommand.java       |  45 ---
 .../karaf/jndi/command/DeleteCommand.java       |  45 ---
 .../apache/karaf/jndi/command/NamesCommand.java |  65 ----
 .../karaf/jndi/command/UnbindCommand.java       |  45 ---
 .../command/completers/ContextsCompleter.java   |  60 ----
 .../jndi/command/completers/NamesCompleter.java |  59 ----
 .../command/completers/ServicesIdCompleter.java |  66 ----
 .../src/main/resources/OSGI-INF/bundle.info     |  26 --
 jndi/core/NOTICE                                |  71 -----
 jndi/core/pom.xml                               |  89 ------
 .../java/org/apache/karaf/jndi/JndiMBean.java   | 104 ------
 .../java/org/apache/karaf/jndi/JndiService.java | 103 ------
 .../karaf/jndi/KarafInitialContextFactory.java  |  33 --
 .../karaf/jndi/internal/JndiMBeanImpl.java      | 122 --------
 .../karaf/jndi/internal/JndiServiceImpl.java    | 313 -------------------
 .../resources/OSGI-INF/blueprint/jndi-core.xml  |  53 ----
 .../src/main/resources/OSGI-INF/bundle.info     |  19 --
 jndi/pom.xml                                    |  72 ++++-
 .../java/org/apache/karaf/jndi/JndiMBean.java   | 104 ++++++
 .../java/org/apache/karaf/jndi/JndiService.java | 103 ++++++
 .../karaf/jndi/KarafInitialContextFactory.java  |  33 ++
 .../apache/karaf/jndi/command/AliasCommand.java |  50 +++
 .../apache/karaf/jndi/command/BindCommand.java  |  50 +++
 .../karaf/jndi/command/ContextsCommand.java     |  64 ++++
 .../karaf/jndi/command/CreateCommand.java       |  45 +++
 .../karaf/jndi/command/DeleteCommand.java       |  45 +++
 .../apache/karaf/jndi/command/NamesCommand.java |  65 ++++
 .../karaf/jndi/command/UnbindCommand.java       |  45 +++
 .../command/completers/ContextsCompleter.java   |  60 ++++
 .../jndi/command/completers/NamesCompleter.java |  59 ++++
 .../command/completers/ServicesIdCompleter.java |  66 ++++
 .../karaf/jndi/internal/JndiMBeanImpl.java      | 122 ++++++++
 .../karaf/jndi/internal/JndiServiceImpl.java    | 313 +++++++++++++++++++
 .../resources/OSGI-INF/blueprint/jndi-core.xml  |  53 ++++
 jndi/src/main/resources/OSGI-INF/bundle.info    |  19 ++
 42 files changed, 1431 insertions(+), 1649 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/karaf/blob/85c65dd6/assemblies/features/enterprise/src/main/feature/feature.xml
----------------------------------------------------------------------
diff --git a/assemblies/features/enterprise/src/main/feature/feature.xml b/assemblies/features/enterprise/src/main/feature/feature.xml
index 69065ba..823d3ba 100644
--- a/assemblies/features/enterprise/src/main/feature/feature.xml
+++ b/assemblies/features/enterprise/src/main/feature/feature.xml
@@ -182,7 +182,6 @@
         <bundle start-level="30">mvn:org.apache.aries.jndi/org.apache.aries.jndi.rmi/${aries.jndi.version}</bundle>
         <bundle start-level="30">mvn:org.apache.aries.jndi/org.apache.aries.jndi.url/${aries.jndi.version}</bundle>
         <bundle start-level="30">mvn:org.apache.aries.jndi/org.apache.aries.jndi.legacy.support/${aries.jndi.version}</bundle>
-        <bundle>mvn:org.apache.karaf.jndi/org.apache.karaf.jndi.command/${project.version}</bundle>
     </feature>
 
     <feature name="jdbc" description="JDBC service and commands" version="${project.version}" resolver="(obr)">

http://git-wip-us.apache.org/repos/asf/karaf/blob/85c65dd6/jndi/NOTICE
----------------------------------------------------------------------
diff --git a/jndi/NOTICE b/jndi/NOTICE
new file mode 100644
index 0000000..b70f1f9
--- /dev/null
+++ b/jndi/NOTICE
@@ -0,0 +1,71 @@
+Apache Karaf
+Copyright 2010-2014 The Apache Software Foundation
+
+
+I. Included Software
+
+This product includes software developed at
+The Apache Software Foundation (http://www.apache.org/).
+Licensed under the Apache License 2.0.
+
+This product uses software developed at
+The OSGi Alliance (http://www.osgi.org/).
+Copyright (c) OSGi Alliance (2000, 2010).
+Licensed under the Apache License 2.0.
+
+This product includes software developed at
+OW2 (http://www.ow2.org/).
+Licensed under the BSD License.
+
+This product includes software developed at
+OPS4J (http://www.ops4j.org/).
+Licensed under the Apache License 2.0.
+
+This product includes software developed at
+Eclipse Foundation (http://www.eclipse.org/).
+Licensed under the EPL.
+
+This product includes software written by
+Antony Lesuisse.
+Licensed under Public Domain.
+
+
+II. Used Software
+
+This product uses software developed at
+FUSE Source (http://www.fusesource.org/).
+Licensed under the Apache License 2.0.
+
+This product uses software developed at
+AOP Alliance (http://aopalliance.sourceforge.net/).
+Licensed under the Public Domain.
+
+This product uses software developed at
+Tanuki Software (http://www.tanukisoftware.com/).
+Licensed under the Apache License 2.0.
+
+This product uses software developed at
+Jasypt (http://jasypt.sourceforge.net/).
+Licensed under the Apache License 2.0.
+
+This product uses software developed at
+JLine (http://jline.sourceforge.net).
+Licensed under the BSD License.
+
+This product uses software developed at
+SLF4J (http://www.slf4j.org/).
+Licensed under the MIT License.
+
+This product uses software developed at
+SpringSource (http://www.springsource.org/).
+Licensed under the Apache License 2.0.
+
+This product includes software from http://www.json.org.
+Copyright (c) 2002 JSON.org
+
+
+III. License Summary
+- Apache License 2.0
+- BSD License
+- EPL License
+- MIT License

http://git-wip-us.apache.org/repos/asf/karaf/blob/85c65dd6/jndi/command/NOTICE
----------------------------------------------------------------------
diff --git a/jndi/command/NOTICE b/jndi/command/NOTICE
deleted file mode 100644
index b70f1f9..0000000
--- a/jndi/command/NOTICE
+++ /dev/null
@@ -1,71 +0,0 @@
-Apache Karaf
-Copyright 2010-2014 The Apache Software Foundation
-
-
-I. Included Software
-
-This product includes software developed at
-The Apache Software Foundation (http://www.apache.org/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-The OSGi Alliance (http://www.osgi.org/).
-Copyright (c) OSGi Alliance (2000, 2010).
-Licensed under the Apache License 2.0.
-
-This product includes software developed at
-OW2 (http://www.ow2.org/).
-Licensed under the BSD License.
-
-This product includes software developed at
-OPS4J (http://www.ops4j.org/).
-Licensed under the Apache License 2.0.
-
-This product includes software developed at
-Eclipse Foundation (http://www.eclipse.org/).
-Licensed under the EPL.
-
-This product includes software written by
-Antony Lesuisse.
-Licensed under Public Domain.
-
-
-II. Used Software
-
-This product uses software developed at
-FUSE Source (http://www.fusesource.org/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-AOP Alliance (http://aopalliance.sourceforge.net/).
-Licensed under the Public Domain.
-
-This product uses software developed at
-Tanuki Software (http://www.tanukisoftware.com/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-Jasypt (http://jasypt.sourceforge.net/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-JLine (http://jline.sourceforge.net).
-Licensed under the BSD License.
-
-This product uses software developed at
-SLF4J (http://www.slf4j.org/).
-Licensed under the MIT License.
-
-This product uses software developed at
-SpringSource (http://www.springsource.org/).
-Licensed under the Apache License 2.0.
-
-This product includes software from http://www.json.org.
-Copyright (c) 2002 JSON.org
-
-
-III. License Summary
-- Apache License 2.0
-- BSD License
-- EPL License
-- MIT License

http://git-wip-us.apache.org/repos/asf/karaf/blob/85c65dd6/jndi/command/pom.xml
----------------------------------------------------------------------
diff --git a/jndi/command/pom.xml b/jndi/command/pom.xml
deleted file mode 100644
index 5dddd2e..0000000
--- a/jndi/command/pom.xml
+++ /dev/null
@@ -1,87 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-
-    <!--
-
-        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.
-    -->
-
-    <modelVersion>4.0.0</modelVersion>
-
-    <parent>
-        <groupId>org.apache.karaf.jndi</groupId>
-        <artifactId>jndi</artifactId>
-        <version>4.0.0-SNAPSHOT</version>
-        <relativePath>../pom.xml</relativePath>
-    </parent>
-
-    <artifactId>org.apache.karaf.jndi.command</artifactId>
-    <packaging>bundle</packaging>
-    <name>Apache Karaf :: JNDI :: Command</name>
-    <description>This bundle provides a set of commands to manipulate JNDI service.</description>
-
-    <properties>
-        <appendedResourcesDirectory>${basedir}/../../etc/appended-resources</appendedResourcesDirectory>
-    </properties>
-
-    <dependencies>
-        <dependency>
-            <groupId>org.apache.karaf.jndi</groupId>
-            <artifactId>org.apache.karaf.jndi.core</artifactId>
-        </dependency>
-
-        <dependency>
-            <groupId>org.osgi</groupId>
-            <artifactId>org.osgi.core</artifactId>
-        </dependency>
-
-        <dependency>
-            <groupId>org.apache.karaf.shell</groupId>
-            <artifactId>org.apache.karaf.shell.core</artifactId>
-        </dependency>
-    </dependencies>
-
-    <build>
-        <resources>
-            <resource>
-                <directory>${project.basedir}/src/main/resources</directory>
-                <includes>
-                    <include>**/*</include>
-                </includes>
-            </resource>
-            <resource>
-                <directory>${project.basedir}/src/main/resources</directory>
-                <filtering>true</filtering>
-                <includes>
-                    <include>**/*.info</include>
-                </includes>
-            </resource>
-        </resources>
-        <plugins>
-            <plugin>
-                <groupId>org.apache.felix</groupId>
-                <artifactId>maven-bundle-plugin</artifactId>
-                <configuration>
-                    <instructions>
-                        <Export-Package>!*</Export-Package>
-                        <Karaf-Commands>*</Karaf-Commands>
-                    </instructions>
-                </configuration>
-            </plugin>
-        </plugins>
-    </build>
-
-</project>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/karaf/blob/85c65dd6/jndi/command/src/main/java/org/apache/karaf/jndi/command/AliasCommand.java
----------------------------------------------------------------------
diff --git a/jndi/command/src/main/java/org/apache/karaf/jndi/command/AliasCommand.java b/jndi/command/src/main/java/org/apache/karaf/jndi/command/AliasCommand.java
deleted file mode 100644
index 08e3912..0000000
--- a/jndi/command/src/main/java/org/apache/karaf/jndi/command/AliasCommand.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * 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.karaf.jndi.command;
-
-import org.apache.karaf.jndi.JndiService;
-import org.apache.karaf.jndi.command.completers.ContextsCompleter;
-import org.apache.karaf.jndi.command.completers.NamesCompleter;
-import org.apache.karaf.shell.api.action.Action;
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Completion;
-import org.apache.karaf.shell.api.action.lifecycle.Reference;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-
-@Command(scope = "jndi", name = "alias", description = "Create a JNDI alias on a given name.")
-@Service
-public class AliasCommand implements Action {
-
-    @Argument(index = 0, name = "name", description = "The JNDI name", required = true, multiValued = false)
-    @Completion(NamesCompleter.class)
-    String name;
-
-    @Argument(index = 1, name = "alias", description = "The JNDI alias", required = true, multiValued = false)
-    @Completion(ContextsCompleter.class)
-    String alias;
-
-    @Reference
-    JndiService jndiService;
-
-    @Override
-    public Object execute() throws Exception {
-        jndiService.alias(name, alias);
-        return null;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/85c65dd6/jndi/command/src/main/java/org/apache/karaf/jndi/command/BindCommand.java
----------------------------------------------------------------------
diff --git a/jndi/command/src/main/java/org/apache/karaf/jndi/command/BindCommand.java b/jndi/command/src/main/java/org/apache/karaf/jndi/command/BindCommand.java
deleted file mode 100644
index b181762..0000000
--- a/jndi/command/src/main/java/org/apache/karaf/jndi/command/BindCommand.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * 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.karaf.jndi.command;
-
-import org.apache.karaf.jndi.JndiService;
-import org.apache.karaf.jndi.command.completers.ContextsCompleter;
-import org.apache.karaf.jndi.command.completers.ServicesIdCompleter;
-import org.apache.karaf.shell.api.action.Action;
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Completion;
-import org.apache.karaf.shell.api.action.lifecycle.Reference;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-
-@Command(scope = "jndi", name = "bind", description = "Bind an OSGi service in the JNDI context")
-@Service
-public class BindCommand implements Action {
-
-    @Argument(index = 0, name = "service", description = "The ID of the OSGi service to bind", required = true, multiValued = false)
-    @Completion(ServicesIdCompleter.class)
-    Long serviceId;
-
-    @Argument(index = 1, name = "name", description = "The JNDI name to bind the OSGi service", required = true, multiValued = false)
-    @Completion(ContextsCompleter.class)
-    String name;
-
-    @Reference
-    JndiService jndiService;
-
-    @Override
-    public Object execute() throws Exception {
-        jndiService.bind(serviceId, name);
-        return null;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/85c65dd6/jndi/command/src/main/java/org/apache/karaf/jndi/command/ContextsCommand.java
----------------------------------------------------------------------
diff --git a/jndi/command/src/main/java/org/apache/karaf/jndi/command/ContextsCommand.java b/jndi/command/src/main/java/org/apache/karaf/jndi/command/ContextsCommand.java
deleted file mode 100644
index 2209479..0000000
--- a/jndi/command/src/main/java/org/apache/karaf/jndi/command/ContextsCommand.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * 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.karaf.jndi.command;
-
-import org.apache.karaf.jndi.JndiService;
-import org.apache.karaf.jndi.command.completers.ContextsCompleter;
-import org.apache.karaf.shell.api.action.Action;
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Completion;
-import org.apache.karaf.shell.api.action.lifecycle.Reference;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.apache.karaf.shell.support.table.ShellTable;
-
-import java.util.List;
-
-@Command(scope = "jndi", name = "contexts", description = "List the JNDI sub-contexts.")
-@Service
-public class ContextsCommand implements Action {
-
-    @Argument(index = 0, name = "context", description = "The base JNDI context", required = false, multiValued = false)
-    @Completion(ContextsCompleter.class)
-    String context;
-
-    @Reference
-    JndiService jndiService;
-
-    @Override
-    public Object execute() throws Exception {
-        ShellTable table = new ShellTable();
-
-        table.column("JNDI Sub-Context");
-
-        List<String> contexts;
-        if (context == null) {
-            contexts = jndiService.contexts();
-        } else {
-            contexts = jndiService.contexts(context);
-        }
-
-        for (String c : contexts) {
-            table.addRow().addContent(c);
-        }
-
-        table.print(System.out);
-
-        return null;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/85c65dd6/jndi/command/src/main/java/org/apache/karaf/jndi/command/CreateCommand.java
----------------------------------------------------------------------
diff --git a/jndi/command/src/main/java/org/apache/karaf/jndi/command/CreateCommand.java b/jndi/command/src/main/java/org/apache/karaf/jndi/command/CreateCommand.java
deleted file mode 100644
index 86663bf..0000000
--- a/jndi/command/src/main/java/org/apache/karaf/jndi/command/CreateCommand.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * 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.karaf.jndi.command;
-
-import org.apache.karaf.jndi.JndiService;
-import org.apache.karaf.jndi.command.completers.ContextsCompleter;
-import org.apache.karaf.shell.api.action.Action;
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Completion;
-import org.apache.karaf.shell.api.action.lifecycle.Reference;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-
-@Command(scope = "jndi",  name = "create", description = "Create a new JNDI sub-context.")
-@Service
-public class CreateCommand implements Action {
-
-    @Argument(index = 0, name = "context", description = "The JNDI sub-context name", required = true, multiValued = false)
-    @Completion(ContextsCompleter.class)
-    String context;
-
-    @Reference
-    JndiService jndiService;
-
-    @Override
-    public Object execute() throws Exception {
-        jndiService.create(context);
-        return null;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/85c65dd6/jndi/command/src/main/java/org/apache/karaf/jndi/command/DeleteCommand.java
----------------------------------------------------------------------
diff --git a/jndi/command/src/main/java/org/apache/karaf/jndi/command/DeleteCommand.java b/jndi/command/src/main/java/org/apache/karaf/jndi/command/DeleteCommand.java
deleted file mode 100644
index 3cd3a40..0000000
--- a/jndi/command/src/main/java/org/apache/karaf/jndi/command/DeleteCommand.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * 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.karaf.jndi.command;
-
-import org.apache.karaf.jndi.JndiService;
-import org.apache.karaf.jndi.command.completers.ContextsCompleter;
-import org.apache.karaf.shell.api.action.Action;
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Completion;
-import org.apache.karaf.shell.api.action.lifecycle.Reference;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-
-@Command(scope = "jndi", name = "delete", description = "Delete a JNDI sub-context.")
-@Service
-public class DeleteCommand implements Action {
-
-    @Argument(index = 0, name = "context", description = "The JNDI sub-context name", required = true, multiValued = false)
-    @Completion(ContextsCompleter.class)
-    String context;
-
-    @Reference
-    JndiService jndiService;
-
-    @Override
-    public Object execute() throws Exception {
-        jndiService.delete(context);
-        return null;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/85c65dd6/jndi/command/src/main/java/org/apache/karaf/jndi/command/NamesCommand.java
----------------------------------------------------------------------
diff --git a/jndi/command/src/main/java/org/apache/karaf/jndi/command/NamesCommand.java b/jndi/command/src/main/java/org/apache/karaf/jndi/command/NamesCommand.java
deleted file mode 100644
index 0345f11..0000000
--- a/jndi/command/src/main/java/org/apache/karaf/jndi/command/NamesCommand.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * 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.karaf.jndi.command;
-
-import org.apache.karaf.jndi.JndiService;
-import org.apache.karaf.jndi.command.completers.ContextsCompleter;
-import org.apache.karaf.shell.api.action.Action;
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Completion;
-import org.apache.karaf.shell.api.action.lifecycle.Reference;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.apache.karaf.shell.support.table.ShellTable;
-
-import java.util.Map;
-
-@Command(scope = "jndi", name = "names", description = "List the JNDI names.")
-@Service
-public class NamesCommand implements Action {
-
-    @Argument(index = 0, name = "context", description = "The JNDI context to display the names", required = false, multiValued = false)
-    @Completion(ContextsCompleter.class)
-    String context;
-
-    @Reference
-    JndiService jndiService;
-
-    @Override
-    public Object execute() throws Exception {
-        ShellTable table = new ShellTable();
-
-        table.column("JNDI Name");
-        table.column("Class Name");
-
-        Map<String, String> names;
-        if (context == null) {
-            names = jndiService.names();
-        } else {
-            names = jndiService.names(context);
-        }
-
-        for (String name : names.keySet()) {
-            table.addRow().addContent(name, names.get(name));
-        }
-
-        table.print(System.out);
-
-        return null;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/85c65dd6/jndi/command/src/main/java/org/apache/karaf/jndi/command/UnbindCommand.java
----------------------------------------------------------------------
diff --git a/jndi/command/src/main/java/org/apache/karaf/jndi/command/UnbindCommand.java b/jndi/command/src/main/java/org/apache/karaf/jndi/command/UnbindCommand.java
deleted file mode 100644
index b93c7b9..0000000
--- a/jndi/command/src/main/java/org/apache/karaf/jndi/command/UnbindCommand.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * 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.karaf.jndi.command;
-
-import org.apache.karaf.jndi.JndiService;
-import org.apache.karaf.jndi.command.completers.NamesCompleter;
-import org.apache.karaf.shell.api.action.Action;
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Completion;
-import org.apache.karaf.shell.api.action.lifecycle.Reference;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-
-@Command(scope = "jndi", name = "unbind", description = "Unbind a JNDI name.")
-@Service
-public class UnbindCommand implements Action {
-
-    @Argument(index = 0, name = "name", description = "The JNDI name to unbind", required = true, multiValued = false)
-    @Completion(NamesCompleter.class)
-    String name;
-
-    @Reference
-    JndiService jndiService;
-
-    @Override
-    public Object execute() throws Exception {
-        jndiService.unbind(name);
-        return null;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/85c65dd6/jndi/command/src/main/java/org/apache/karaf/jndi/command/completers/ContextsCompleter.java
----------------------------------------------------------------------
diff --git a/jndi/command/src/main/java/org/apache/karaf/jndi/command/completers/ContextsCompleter.java b/jndi/command/src/main/java/org/apache/karaf/jndi/command/completers/ContextsCompleter.java
deleted file mode 100644
index 8f2ac29..0000000
--- a/jndi/command/src/main/java/org/apache/karaf/jndi/command/completers/ContextsCompleter.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * 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.karaf.jndi.command.completers;
-
-import org.apache.karaf.jndi.JndiService;
-import org.apache.karaf.shell.api.action.lifecycle.Reference;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.apache.karaf.shell.api.console.CommandLine;
-import org.apache.karaf.shell.api.console.Completer;
-import org.apache.karaf.shell.api.console.Session;
-import org.apache.karaf.shell.support.completers.StringsCompleter;
-
-import java.util.List;
-
-/**
- * Completers on the JNDI contexts.
- */
-@Service
-public class ContextsCompleter implements Completer {
-
-    @Reference
-    private JndiService jndiService;
-
-    @Override
-    public int complete(Session session, CommandLine commandLine, List<String> candidates) {
-        StringsCompleter delegate = new StringsCompleter();
-        try {
-            List<String> contexts = jndiService.contexts();
-            for (String context : contexts) {
-                delegate.getStrings().add(context);
-            }
-        } catch (Exception e) {
-            // nothing to do
-        }
-        return delegate.complete(session, commandLine, candidates);
-    }
-
-    public JndiService getJndiService() {
-        return jndiService;
-    }
-
-    public void setJndiService(JndiService jndiService) {
-        this.jndiService = jndiService;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/85c65dd6/jndi/command/src/main/java/org/apache/karaf/jndi/command/completers/NamesCompleter.java
----------------------------------------------------------------------
diff --git a/jndi/command/src/main/java/org/apache/karaf/jndi/command/completers/NamesCompleter.java b/jndi/command/src/main/java/org/apache/karaf/jndi/command/completers/NamesCompleter.java
deleted file mode 100644
index d94e3f4..0000000
--- a/jndi/command/src/main/java/org/apache/karaf/jndi/command/completers/NamesCompleter.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * 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.karaf.jndi.command.completers;
-
-import org.apache.karaf.jndi.JndiService;
-import org.apache.karaf.shell.api.action.lifecycle.Reference;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.apache.karaf.shell.api.console.CommandLine;
-import org.apache.karaf.shell.api.console.Completer;
-import org.apache.karaf.shell.api.console.Session;
-import org.apache.karaf.shell.support.completers.StringsCompleter;
-
-import java.util.List;
-
-/**
- * Completer to the JNDI names.
- */
-@Service
-public class NamesCompleter implements Completer {
-
-    @Reference
-    private JndiService jndiService;
-
-    @Override
-    public int complete(Session session, CommandLine commandLine, List<String> candidates) {
-        StringsCompleter delegate = new StringsCompleter();
-        try {
-            for (String name : jndiService.names().keySet()) {
-                delegate.getStrings().add(name);
-            }
-        } catch (Exception e) {
-            // nothing to do
-        }
-        return delegate.complete(session, commandLine, candidates);
-    }
-
-    public JndiService getJndiService() {
-        return jndiService;
-    }
-
-    public void setJndiService(JndiService jndiService) {
-        this.jndiService = jndiService;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/85c65dd6/jndi/command/src/main/java/org/apache/karaf/jndi/command/completers/ServicesIdCompleter.java
----------------------------------------------------------------------
diff --git a/jndi/command/src/main/java/org/apache/karaf/jndi/command/completers/ServicesIdCompleter.java b/jndi/command/src/main/java/org/apache/karaf/jndi/command/completers/ServicesIdCompleter.java
deleted file mode 100644
index c7cdb80..0000000
--- a/jndi/command/src/main/java/org/apache/karaf/jndi/command/completers/ServicesIdCompleter.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * 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.karaf.jndi.command.completers;
-
-import org.apache.karaf.shell.api.action.lifecycle.Reference;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.apache.karaf.shell.api.console.CommandLine;
-import org.apache.karaf.shell.api.console.Completer;
-import org.apache.karaf.shell.api.console.Session;
-import org.apache.karaf.shell.support.completers.StringsCompleter;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.Constants;
-import org.osgi.framework.ServiceReference;
-
-import java.util.List;
-
-/**
- * Completer on the OSGi services ID.
- */
-@Service
-public class ServicesIdCompleter implements Completer {
-
-    @Reference
-    private BundleContext bundleContext;
-
-    @Override
-    public int complete(Session session, CommandLine commandLine, List<String> candidates) {
-        StringsCompleter delegate = new StringsCompleter();
-        Bundle[] bundles = bundleContext.getBundles();
-        for (Bundle bundle : bundles) {
-            ServiceReference[] references = bundle.getRegisteredServices();
-            if (references != null) {
-                for (ServiceReference reference : references) {
-                    if (reference.getProperty(Constants.SERVICE_ID) != null) {
-                        delegate.getStrings().add(reference.getProperty(Constants.SERVICE_ID).toString());
-                    }
-                }
-            }
-        }
-        return delegate.complete(session, commandLine, candidates);
-    }
-
-    public BundleContext getBundleContext() {
-        return bundleContext;
-    }
-
-    public void setBundleContext(BundleContext bundleContext) {
-        this.bundleContext = bundleContext;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/85c65dd6/jndi/command/src/main/resources/OSGI-INF/bundle.info
----------------------------------------------------------------------
diff --git a/jndi/command/src/main/resources/OSGI-INF/bundle.info b/jndi/command/src/main/resources/OSGI-INF/bundle.info
deleted file mode 100644
index d97d132..0000000
--- a/jndi/command/src/main/resources/OSGI-INF/bundle.info
+++ /dev/null
@@ -1,26 +0,0 @@
-h1. Synopsis
-
-${project.name}
-
-${project.description}
-
-Maven URL:
-[mvn:${project.groupId}/${project.artifactId}/${project.version}]
-
-h1. Description
-
-This bundle provides the shell commands to manipulate the JNDI service.
-
-The following commands are available:
-
-* jndi:alias
-* jndi:bind
-* jndi:create
-* jndi:contexts
-* jndi:delete
-* jndi:names
-* jndi:unbind
-
-h1. See also
-
-JNDI - section of the Karaf User Guide
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/karaf/blob/85c65dd6/jndi/core/NOTICE
----------------------------------------------------------------------
diff --git a/jndi/core/NOTICE b/jndi/core/NOTICE
deleted file mode 100644
index b70f1f9..0000000
--- a/jndi/core/NOTICE
+++ /dev/null
@@ -1,71 +0,0 @@
-Apache Karaf
-Copyright 2010-2014 The Apache Software Foundation
-
-
-I. Included Software
-
-This product includes software developed at
-The Apache Software Foundation (http://www.apache.org/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-The OSGi Alliance (http://www.osgi.org/).
-Copyright (c) OSGi Alliance (2000, 2010).
-Licensed under the Apache License 2.0.
-
-This product includes software developed at
-OW2 (http://www.ow2.org/).
-Licensed under the BSD License.
-
-This product includes software developed at
-OPS4J (http://www.ops4j.org/).
-Licensed under the Apache License 2.0.
-
-This product includes software developed at
-Eclipse Foundation (http://www.eclipse.org/).
-Licensed under the EPL.
-
-This product includes software written by
-Antony Lesuisse.
-Licensed under Public Domain.
-
-
-II. Used Software
-
-This product uses software developed at
-FUSE Source (http://www.fusesource.org/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-AOP Alliance (http://aopalliance.sourceforge.net/).
-Licensed under the Public Domain.
-
-This product uses software developed at
-Tanuki Software (http://www.tanukisoftware.com/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-Jasypt (http://jasypt.sourceforge.net/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-JLine (http://jline.sourceforge.net).
-Licensed under the BSD License.
-
-This product uses software developed at
-SLF4J (http://www.slf4j.org/).
-Licensed under the MIT License.
-
-This product uses software developed at
-SpringSource (http://www.springsource.org/).
-Licensed under the Apache License 2.0.
-
-This product includes software from http://www.json.org.
-Copyright (c) 2002 JSON.org
-
-
-III. License Summary
-- Apache License 2.0
-- BSD License
-- EPL License
-- MIT License

http://git-wip-us.apache.org/repos/asf/karaf/blob/85c65dd6/jndi/core/pom.xml
----------------------------------------------------------------------
diff --git a/jndi/core/pom.xml b/jndi/core/pom.xml
deleted file mode 100644
index bf1f75c..0000000
--- a/jndi/core/pom.xml
+++ /dev/null
@@ -1,89 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-
-    <!--
-
-        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.
-    -->
-
-    <modelVersion>4.0.0</modelVersion>
-
-    <parent>
-        <groupId>org.apache.karaf.jndi</groupId>
-        <artifactId>jndi</artifactId>
-        <version>4.0.0-SNAPSHOT</version>
-        <relativePath>../pom.xml</relativePath>
-    </parent>
-
-    <artifactId>org.apache.karaf.jndi.core</artifactId>
-    <packaging>bundle</packaging>
-    <name>Apache Karaf :: JNDI :: Core</name>
-    <description>This bundle provides core implementation of the JNDI management service.</description>
-
-    <properties>
-        <appendedResourcesDirectory>${basedir}/../../etc/appended-resources</appendedResourcesDirectory>
-    </properties>
-
-    <dependencies>
-        <dependency>
-            <groupId>org.apache.xbean</groupId>
-            <artifactId>xbean-naming</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.osgi</groupId>
-            <artifactId>org.osgi.core</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.aries.proxy</groupId>
-            <artifactId>org.apache.aries.proxy.api</artifactId>
-        </dependency>
-    </dependencies>
-
-    <build>
-        <resources>
-            <resource>
-                <directory>${project.basedir}/src/main/resources</directory>
-                <includes>
-                    <include>**/*</include>
-                </includes>
-            </resource>
-            <resource>
-                <directory>${project.basedir}/src/main/resources</directory>
-                <filtering>true</filtering>
-                <includes>
-                    <include>**/*.info</include>
-                </includes>
-            </resource>
-        </resources>
-        <plugins>
-            <plugin>
-                <groupId>org.apache.felix</groupId>
-                <artifactId>maven-bundle-plugin</artifactId>
-                <configuration>
-                    <instructions>
-                        <Export-Package>
-                            org.apache.karaf.jndi
-                        </Export-Package>
-                        <Private-Package>
-                            org.apache.karaf.jndi.internal
-                        </Private-Package>
-                    </instructions>
-                </configuration>
-            </plugin>
-        </plugins>
-    </build>
-
-</project>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/karaf/blob/85c65dd6/jndi/core/src/main/java/org/apache/karaf/jndi/JndiMBean.java
----------------------------------------------------------------------
diff --git a/jndi/core/src/main/java/org/apache/karaf/jndi/JndiMBean.java b/jndi/core/src/main/java/org/apache/karaf/jndi/JndiMBean.java
deleted file mode 100644
index 0b2be41..0000000
--- a/jndi/core/src/main/java/org/apache/karaf/jndi/JndiMBean.java
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * 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.karaf.jndi;
-
-import javax.management.MBeanException;
-import java.util.List;
-import java.util.Map;
-
-/**
- * JNDI Service MBean
- */
-public interface JndiMBean {
-
-    /**
-     * Get a map of JNDI names/class names (as attribute).
-     *
-     * @return the MBean attribute containing the map of names/class names.
-     * @throws MBeanException
-     */
-    public Map<String, String> getNames() throws MBeanException;
-
-    /**
-     * Get a list of JNDI sub-contexts (as attribute).
-     *
-     * @return the MBean attribute containing the list of sub-contexts.
-     * @throws MBeanException
-     */
-    public List<String> getContexts() throws MBeanException;
-
-    /**
-     * Get a map of JNDI names/class names children of a given base context.
-     *
-     * @param context the base context.
-     * @return the map of names/class names.
-     * @throws MBeanException
-     */
-    public Map<String, String> getNames(String context) throws MBeanException;
-
-    /**
-     * Get a list of JNDI sub-contexts children of a given base context.
-     *
-     * @param context the base context.
-     * @return the list of sub-contexts.
-     * @throws MBeanException
-     */
-    public List<String> getContexts(String context) throws MBeanException;
-
-    /**
-     * Create a JNDI sub-context.
-     *
-     * @param context the JNDI sub-context name.
-     * @throws MBeanException
-     */
-    public void create(String context) throws MBeanException;
-
-    /**
-     * Delete a JNDI sub-context.
-     *
-     * @param context the JNDI sub-context name.
-     * @throws MBeanException
-     */
-    public void delete(String context) throws MBeanException;
-
-    /**
-     * Create another JNDI name (alias) for a given one.
-     *
-     * @param name the "source" JNDI name.
-     * @param alias the JNDI alias name.
-     * @throws MBeanException
-     */
-    public void alias(String name, String alias) throws MBeanException;
-
-    /**
-     * Bind an OSGi service with a JNDI name.
-     *
-     * @param serviceId the OSGi service id (service.id property on the service, created by the framework).
-     * @param name the JNDI name.
-     * @throws MBeanException
-     */
-    public void bind(Long serviceId, String name) throws MBeanException;
-
-    /**
-     * Unbind a given JNDI name.
-     *
-     * @param name the JNDI name.
-     * @throws MBeanException
-     */
-    public void unbind(String name) throws MBeanException;
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/85c65dd6/jndi/core/src/main/java/org/apache/karaf/jndi/JndiService.java
----------------------------------------------------------------------
diff --git a/jndi/core/src/main/java/org/apache/karaf/jndi/JndiService.java b/jndi/core/src/main/java/org/apache/karaf/jndi/JndiService.java
deleted file mode 100644
index c9f9c57..0000000
--- a/jndi/core/src/main/java/org/apache/karaf/jndi/JndiService.java
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * 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.karaf.jndi;
-
-import java.util.List;
-import java.util.Map;
-
-/**
- * JNDI Service.
- */
-public interface JndiService {
-
-    /**
-     * List the current JNDI names (with the bound class name).
-     *
-     * @return the JNDI names.
-     * @throws Exception
-     */
-    Map<String, String> names() throws Exception;
-
-    /**
-     * List the current JNDI names in the given context.
-     *
-     * @param context the JNDI context.
-     * @return the JNDI names in the context.
-     * @throws Exception
-     */
-    Map<String, String> names(String context) throws Exception;
-
-    /**
-     * List all JNDI sub-contexts.
-     *
-     * @return a list containing the sub-context names.
-     * @throws Exception
-     */
-    List<String> contexts() throws Exception;
-
-    /**
-     * List the JNDI sub-context from a given context.
-     *
-     * @param context the base JNDI context.
-     * @return a list containing the sub-context names.
-     * @throws Exception
-     */
-    List<String> contexts(String context) throws Exception;
-
-    /**
-     * Create a sub-context.
-     *
-     * @param context the new sub-context name to create.
-     * @throws Exception
-     */
-    void create(String context) throws Exception;
-
-    /**
-     * Delete a sub-context.
-     *
-     * @param context the sub-context name to delete.
-     * @throws Exception
-     */
-    void delete(String context) throws Exception;
-
-    /**
-     * Create an alias on a given JNDI name.
-     *
-     * @param name the JNDI name.
-     * @param alias the alias.
-     * @throws Exception
-     */
-    void alias(String name, String alias) throws Exception;
-
-    /**
-     * Bind a given OSGi service to a JNDI name.
-     *
-     * @param serviceId the OSGi service ID.
-     * @param name the JNDI name.
-     * @throws Exception
-     */
-    void bind(long serviceId, String name) throws Exception;
-
-    /**
-     * Unbind an existing name.
-     *
-     * @param name the JNDI name to unbind.
-     * @throws Exception
-     */
-    void unbind(String name) throws Exception;
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/85c65dd6/jndi/core/src/main/java/org/apache/karaf/jndi/KarafInitialContextFactory.java
----------------------------------------------------------------------
diff --git a/jndi/core/src/main/java/org/apache/karaf/jndi/KarafInitialContextFactory.java b/jndi/core/src/main/java/org/apache/karaf/jndi/KarafInitialContextFactory.java
deleted file mode 100644
index a540556..0000000
--- a/jndi/core/src/main/java/org/apache/karaf/jndi/KarafInitialContextFactory.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * 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.karaf.jndi;
-
-import org.apache.xbean.naming.context.WritableContext;
-import org.apache.xbean.naming.global.GlobalContextManager;
-
-/**
- * A very simple writable initial context factory.
- * @see org.apache.xbean.naming.context.WritableContext for details.
- */
-public class KarafInitialContextFactory extends GlobalContextManager {
-
-    public KarafInitialContextFactory() throws Exception {
-        super();
-        setGlobalContext(new WritableContext());
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/85c65dd6/jndi/core/src/main/java/org/apache/karaf/jndi/internal/JndiMBeanImpl.java
----------------------------------------------------------------------
diff --git a/jndi/core/src/main/java/org/apache/karaf/jndi/internal/JndiMBeanImpl.java b/jndi/core/src/main/java/org/apache/karaf/jndi/internal/JndiMBeanImpl.java
deleted file mode 100644
index 2433618..0000000
--- a/jndi/core/src/main/java/org/apache/karaf/jndi/internal/JndiMBeanImpl.java
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * 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.karaf.jndi.internal;
-
-import org.apache.karaf.jndi.JndiService;
-import org.apache.karaf.jndi.JndiMBean;
-
-import javax.management.MBeanException;
-import java.util.List;
-import java.util.Map;
-
-/**
- * Implementation of the JndiMBean
- */
-public class JndiMBeanImpl implements JndiMBean {
-
-    private JndiService jndiService;
-
-    @Override
-    public Map<String, String> getNames() throws MBeanException {
-        try {
-            return this.jndiService.names();
-        } catch (Throwable t) {
-            throw new MBeanException(null, t.getMessage());
-        }
-    }
-
-    @Override
-    public List<String> getContexts() throws MBeanException {
-        try {
-            return this.jndiService.contexts();
-        } catch (Throwable t) {
-            throw new MBeanException(null, t.getMessage());
-        }
-    }
-
-    @Override
-    public Map<String, String> getNames(String context) throws MBeanException {
-        try {
-            return this.jndiService.names(context);
-        } catch (Throwable t) {
-            throw new MBeanException(null, t.getMessage());
-        }
-    }
-
-    @Override
-    public List<String> getContexts(String context) throws MBeanException {
-        try {
-            return this.jndiService.contexts(context);
-        } catch (Throwable t) {
-            throw new MBeanException(null, t.getMessage());
-        }
-    }
-
-    @Override
-    public void alias(String name, String alias) throws MBeanException {
-        try {
-            this.jndiService.alias(name, alias);
-        } catch (Throwable t) {
-            throw new MBeanException(null, t.getMessage());
-        }
-    }
-
-    @Override
-    public void bind(Long serviceId, String name) throws MBeanException {
-        try {
-            this.jndiService.bind(serviceId, name);
-        } catch (Throwable t) {
-            throw new MBeanException(null, t.getMessage());
-        }
-    }
-
-    @Override
-    public void unbind(String name) throws MBeanException {
-        try {
-            this.jndiService.unbind(name);
-        } catch (Throwable t) {
-            throw new MBeanException(null, t.getMessage());
-        }
-    }
-
-    @Override
-    public void create(String context) throws MBeanException {
-        try {
-            this.jndiService.create(context);
-        } catch (Throwable t) {
-            throw new MBeanException(null, t.getMessage());
-        }
-    }
-
-    @Override
-    public void delete(String context) throws MBeanException {
-        try {
-            this.jndiService.delete(context);
-        } catch (Throwable t) {
-            throw new MBeanException(null, t.getMessage());
-        }
-    }
-
-    public JndiService getJndiService() {
-        return jndiService;
-    }
-
-    public void setJndiService(JndiService jndiService) {
-        this.jndiService = jndiService;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/85c65dd6/jndi/core/src/main/java/org/apache/karaf/jndi/internal/JndiServiceImpl.java
----------------------------------------------------------------------
diff --git a/jndi/core/src/main/java/org/apache/karaf/jndi/internal/JndiServiceImpl.java b/jndi/core/src/main/java/org/apache/karaf/jndi/internal/JndiServiceImpl.java
deleted file mode 100644
index 68d6b94..0000000
--- a/jndi/core/src/main/java/org/apache/karaf/jndi/internal/JndiServiceImpl.java
+++ /dev/null
@@ -1,313 +0,0 @@
-/*
- * 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.karaf.jndi.internal;
-
-import org.apache.aries.proxy.ProxyManager;
-import org.apache.karaf.jndi.JndiService;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.Constants;
-import org.osgi.framework.ServiceReference;
-
-import javax.naming.*;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-/**
- * Implementation of the JNDI Service.
- */
-public class JndiServiceImpl implements JndiService {
-
-    private BundleContext bundleContext;
-    private ProxyManager proxyManager;
-
-    private final static String OSGI_JNDI_CONTEXT_PREFIX = "osgi:service/";
-    private final static String OSGI_JNDI_SERVICE_PROPERTY = "osgi.jndi.service.name";
-
-    @Override
-    public Map<String, String> names() throws Exception {
-        Map<String, String> result = names("/");
-        result.putAll(names(OSGI_JNDI_CONTEXT_PREFIX));
-        return result;
-    }
-
-    @Override
-    public Map<String, String> names(String name) throws Exception {
-        Map<String, String> map = new HashMap<String, String>();
-        if (name.startsWith(OSGI_JNDI_CONTEXT_PREFIX)) {
-            // OSGi service binding
-            // make a lookup using directly the OSGi service
-            Bundle[] bundles = bundleContext.getBundles();
-            for (Bundle bundle : bundles) {
-                ServiceReference<?>[] services = bundle.getRegisteredServices();
-                if (services != null) {
-                    for (ServiceReference service : services) {
-                        if (service.getProperty(OSGI_JNDI_SERVICE_PROPERTY) != null) {
-                            Object actualService = bundleContext.getService(service);
-                            if (proxyManager.isProxy(actualService)) {
-                                actualService = proxyManager.unwrap(actualService).call();
-                            }
-                            map.put(OSGI_JNDI_CONTEXT_PREFIX + service.getProperty(OSGI_JNDI_SERVICE_PROPERTY), actualService.getClass().getName());
-                            bundleContext.ungetService(service);
-                        }
-                    }
-                }
-            }
-        } else {
-            // "real" JNDI lookup
-            Context context = new InitialContext();
-            NamingEnumeration<NameClassPair> pairs = context.list(name);
-            while (pairs.hasMoreElements()) {
-                NameClassPair pair = pairs.nextElement();
-                Object o;
-                if (name != null) {
-                    o = context.lookup(name + "/" + pair.getName());
-                } else {
-                    o = context.lookup(pair.getName());
-                }
-                if (o instanceof Context) {
-                    StringBuilder sb = new StringBuilder();
-                    sb.append("/" + pair.getName());
-                    names((Context) o, sb, map);
-                } else {
-                    map.put("/" + pair.getName(), pair.getClassName());
-                }
-            }
-        }
-        return map;
-    }
-
-    public List<String> contexts() throws Exception {
-        return contexts("/");
-    }
-
-    public List<String> contexts(String name) throws Exception {
-        List<String> contexts = new ArrayList<String>();
-        Context context = new InitialContext();
-        NamingEnumeration<NameClassPair> pairs = context.list(name);
-        while (pairs.hasMoreElements()) {
-            NameClassPair pair = pairs.nextElement();
-            Object o;
-            if (name != null) {
-                o = context.lookup(name + "/" + pair.getName());
-            } else {
-                o = context.lookup(pair.getName());
-            }
-            if (o instanceof Context) {
-                StringBuilder sb = new StringBuilder();
-                sb.append("/" + pair.getName());
-                contexts((Context) o, sb, contexts);
-            }
-        }
-        return contexts;
-    }
-
-    private void contexts(Context context, StringBuilder sb, List<String> contexts) throws Exception {
-        NamingEnumeration list = context.listBindings("");
-        while (list.hasMore()) {
-            Binding item = (Binding) list.next();
-            String name = item.getName();
-            Object o = item.getObject();
-            if (o instanceof Context) {
-                if (((Context) o).list("").hasMoreElements()) {
-                    sb.append("/").append(name);
-                    contexts((Context) o, sb, contexts);
-                } else {
-                    contexts.add(sb.toString() + "/" + name);
-                }
-            }
-        }
-    }
-
-    /**
-     * Recursively list a context/names
-     *
-     * @param ctx the startup context.
-     * @param sb the string builder where to construct the full qualified name.
-     * @param map the final map containing name/class name pairs.
-     * @throws Exception
-     */
-    private static final void names(Context ctx, StringBuilder sb, Map<String, String> map) throws Exception {
-        NamingEnumeration list = ctx.listBindings("");
-        while (list.hasMore()) {
-            Binding item = (Binding) list.next();
-            String className = item.getClassName();
-            String name = item.getName();
-            Object o = item.getObject();
-            if (o instanceof Context) {
-                sb.append("/").append(name);
-                names((Context) o, sb, map);
-            } else {
-                map.put(sb.toString() + "/" + name, className);
-            }
-        }
-    }
-
-    @Override
-    public void create(String name) throws Exception {
-        Context context = new InitialContext();
-        String[] splitted = name.split("/");
-        if (splitted.length > 0) {
-            for (int i = 0; i < splitted.length; i++) {
-                try {
-                    Object o = context.lookup(splitted[i]);
-                    if (!(o instanceof Context)) {
-                        throw new NamingException("Name " + splitted[i] + " already exists");
-                    }
-                } catch (NameNotFoundException e) {
-                    context.createSubcontext(splitted[i]);
-                }
-                context = (Context) context.lookup(splitted[i]);
-            }
-        } else {
-            context.createSubcontext(name);
-        }
-    }
-
-    @Override
-    public void delete(String name) throws Exception {
-        Context context = new InitialContext();
-        context.destroySubcontext(name);
-    }
-
-    @Override
-    public void bind(long serviceId, String name) throws Exception {
-        Context context = new InitialContext();
-        Bundle[] bundles = bundleContext.getBundles();
-        for (Bundle bundle : bundles) {
-            ServiceReference<?>[] services = bundle.getRegisteredServices();
-            if (services != null) {
-                for (ServiceReference service : services) {
-                    if (service.getProperty(Constants.SERVICE_ID) != null && ((Long) service.getProperty(Constants.SERVICE_ID)) == serviceId) {
-                        Object actualService = bundleContext.getService(service);
-                        if (proxyManager.isProxy(actualService)) {
-                            actualService = proxyManager.unwrap(actualService).call();
-                        }
-                        try {
-                            String[] splitted = name.split("/");
-                            if (splitted.length > 0) {
-                                for (int i = 0; i < splitted.length - 1; i++) {
-                                    try {
-                                        Object o = context.lookup(splitted[i]);
-                                        if (!(o instanceof Context)) {
-                                            throw new NamingException("Name " + splitted[i] + " already exists");
-                                        }
-                                    } catch (NameNotFoundException nnfe) {
-                                        context.createSubcontext(splitted[i]);
-                                    }
-                                    context = (Context) context.lookup(splitted[i]);
-                                }
-                                name = splitted[splitted.length - 1];
-                            }
-                            context.bind(name, actualService);
-                        } finally {
-                            bundleContext.ungetService(service);
-                        }
-                    }
-                }
-            }
-        }
-    }
-
-    @Override
-    public void alias(String name, String alias) throws Exception {
-        Context context = new InitialContext();
-        if (name.startsWith(OSGI_JNDI_CONTEXT_PREFIX)) {
-            // get the object
-            Bundle[] bundles = bundleContext.getBundles();
-            for (Bundle bundle : bundles) {
-                ServiceReference<?>[] services = bundle.getRegisteredServices();
-                if (services != null) {
-                    for (ServiceReference service : services) {
-                        if (service.getProperty(OSGI_JNDI_SERVICE_PROPERTY) != null && ((String) service.getProperty(OSGI_JNDI_SERVICE_PROPERTY)).equals(name.substring(OSGI_JNDI_CONTEXT_PREFIX.length()))) {
-                            Object actualService = bundleContext.getService(service);
-                            try {
-                                if (proxyManager.isProxy(actualService)) {
-                                    actualService = proxyManager.unwrap(actualService).call();
-                                }
-                                String[] splitted = alias.split("/");
-                                if (splitted.length > 0) {
-                                    for (int i = 0; i < splitted.length - 1; i++) {
-                                        try {
-                                            Object o = context.lookup(splitted[i]);
-                                            if (!(o instanceof Context)) {
-                                                throw new NamingException("Name " + splitted[i] + " already exists");
-                                            }
-                                        } catch (NameNotFoundException nnfe) {
-                                            context.createSubcontext(splitted[i]);
-                                        }
-                                        context = (Context) context.lookup(splitted[i]);
-                                    }
-                                    alias = splitted[splitted.length -1];
-                                }
-                                context.bind(alias, actualService);
-                            } finally {
-                                bundleContext.ungetService(service);
-                            }
-                        }
-                    }
-                }
-            }
-        } else {
-            Object object = context.lookup(name);
-            String[] splitted = alias.split("/");
-            if (splitted.length > 0) {
-                for (int i = 0; i < splitted.length - 1; i++) {
-                    try {
-                        Object o = context.lookup(splitted[i]);
-                        if (!(o instanceof Context)) {
-                            throw new NamingException("Name " + splitted[i] + " already exists");
-                        }
-                    } catch (NameNotFoundException nnfe) {
-                        context.createSubcontext(splitted[i]);
-                    }
-                    context = (Context) context.lookup(splitted[i]);
-                }
-                alias = splitted[splitted.length - 1];
-            }
-            context.bind(alias, object);
-        }
-    }
-
-    @Override
-    public void unbind(String name) throws Exception {
-        InitialContext context = new InitialContext();
-        if (name.startsWith(OSGI_JNDI_CONTEXT_PREFIX)) {
-            throw new IllegalArgumentException("You can't unbind a name from the " + OSGI_JNDI_CONTEXT_PREFIX + " JNDI context.");
-        }
-        context.unbind(name);
-    }
-
-    public BundleContext getBundleContext() {
-        return bundleContext;
-    }
-
-    public void setBundleContext(BundleContext bundleContext) {
-        this.bundleContext = bundleContext;
-    }
-
-    public ProxyManager getProxyManager() {
-        return proxyManager;
-    }
-
-    public void setProxyManager(ProxyManager proxyManager) {
-        this.proxyManager = proxyManager;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/85c65dd6/jndi/core/src/main/resources/OSGI-INF/blueprint/jndi-core.xml
----------------------------------------------------------------------
diff --git a/jndi/core/src/main/resources/OSGI-INF/blueprint/jndi-core.xml b/jndi/core/src/main/resources/OSGI-INF/blueprint/jndi-core.xml
deleted file mode 100644
index e6be3b1..0000000
--- a/jndi/core/src/main/resources/OSGI-INF/blueprint/jndi-core.xml
+++ /dev/null
@@ -1,53 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-
-        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.
-    -->
-<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
-           xmlns:ext="http://aries.apache.org/blueprint/xmlns/blueprint-ext/v1.0.0"
-           default-activation="lazy">
-
-    <ext:property-placeholder placeholder-prefix="$[" placeholder-suffix="]"/>
-
-    <bean id="karafInitialContextFactory" class="org.apache.karaf.jndi.KarafInitialContextFactory"/>
-
-    <reference id="proxyManager" interface="org.apache.aries.proxy.ProxyManager"/>
-
-    <service ref="karafInitialContextFactory" interface="javax.naming.spi.InitialContextFactory"/>
-
-    <bean id="jndiService" class="org.apache.karaf.jndi.internal.JndiServiceImpl">
-        <property name="bundleContext" ref="blueprintBundleContext"/>
-        <property name="proxyManager" ref="proxyManager"/>
-    </bean>
-
-    <service ref="jndiService" interface="org.apache.karaf.jndi.JndiService">
-        <service-properties>
-            <!-- bind the JNDI service itself in the JNDI context -->
-            <entry key="osgi.jndi.service.name" value="jndi"/>
-        </service-properties>
-    </service>
-
-    <!-- Management -->
-    <bean id="jndiMBeanImpl" class="org.apache.karaf.jndi.internal.JndiMBeanImpl">
-        <property name="jndiService" ref="jndiService"/>
-    </bean>
-
-    <service ref="jndiMBeanImpl" auto-export="interfaces">
-        <service-properties>
-            <entry key="jmx.objectname" value="org.apache.karaf:type=jndi,name=$[karaf.name]"/>
-        </service-properties>
-    </service>
-
-</blueprint>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/karaf/blob/85c65dd6/jndi/core/src/main/resources/OSGI-INF/bundle.info
----------------------------------------------------------------------
diff --git a/jndi/core/src/main/resources/OSGI-INF/bundle.info b/jndi/core/src/main/resources/OSGI-INF/bundle.info
deleted file mode 100644
index 4a7a606..0000000
--- a/jndi/core/src/main/resources/OSGI-INF/bundle.info
+++ /dev/null
@@ -1,19 +0,0 @@
-h1. Synopsis
-
-${project.name}
-
-${project.description}
-
-Maven URL:
-[mvn:${project.groupId}/${project.artifactId}/${project.version}]
-
-h1. Description
-
-This bundle is the core implementation of the JNDI service support.
-
-JNDI allows to expose any OSGi services as JNDI names. Karaf JNDI also provides a set of commands and a MBean to list
-the current JNDI names, create JNDI aliases, ...
-
-h1. See also
-
-JNDI - section of the Karaf User Guide

http://git-wip-us.apache.org/repos/asf/karaf/blob/85c65dd6/jndi/pom.xml
----------------------------------------------------------------------
diff --git a/jndi/pom.xml b/jndi/pom.xml
index eb3a43e..f2db373 100644
--- a/jndi/pom.xml
+++ b/jndi/pom.xml
@@ -29,13 +29,69 @@
     </parent>
 
     <groupId>org.apache.karaf.jndi</groupId>
-    <artifactId>jndi</artifactId>
-    <packaging>pom</packaging>
-    <name>Apache Karaf :: JNDI</name>
-
-    <modules>
-        <module>core</module>
-        <module>command</module>
-    </modules>
+    <artifactId>org.apache.karaf.jndi.core</artifactId>
+    <packaging>bundle</packaging>
+    <name>Apache Karaf :: JNDI :: Core</name>
+    <description>This bundle provides core implementation of the JNDI management service.</description>
+
+    <properties>
+        <appendedResourcesDirectory>${basedir}/../../etc/appended-resources</appendedResourcesDirectory>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.xbean</groupId>
+            <artifactId>xbean-naming</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>org.osgi.core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.aries.proxy</groupId>
+            <artifactId>org.apache.aries.proxy.api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.karaf.shell</groupId>
+            <artifactId>org.apache.karaf.shell.core</artifactId>
+            <optional>true</optional>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <resources>
+            <resource>
+                <directory>${project.basedir}/src/main/resources</directory>
+                <includes>
+                    <include>**/*</include>
+                </includes>
+            </resource>
+            <resource>
+                <directory>${project.basedir}/src/main/resources</directory>
+                <filtering>true</filtering>
+                <includes>
+                    <include>**/*.info</include>
+                </includes>
+            </resource>
+        </resources>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+                <configuration>
+                    <instructions>
+                        <Export-Package>
+                            org.apache.karaf.jndi
+                        </Export-Package>
+                        <Private-Package>
+                            org.apache.karaf.jndi.command,
+                            org.apache.karaf.jndi.internal
+                        </Private-Package>
+                        <Karaf-Commands>*</Karaf-Commands>
+                    </instructions>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
 
 </project>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/karaf/blob/85c65dd6/jndi/src/main/java/org/apache/karaf/jndi/JndiMBean.java
----------------------------------------------------------------------
diff --git a/jndi/src/main/java/org/apache/karaf/jndi/JndiMBean.java b/jndi/src/main/java/org/apache/karaf/jndi/JndiMBean.java
new file mode 100644
index 0000000..0b2be41
--- /dev/null
+++ b/jndi/src/main/java/org/apache/karaf/jndi/JndiMBean.java
@@ -0,0 +1,104 @@
+/*
+ * 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.karaf.jndi;
+
+import javax.management.MBeanException;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * JNDI Service MBean
+ */
+public interface JndiMBean {
+
+    /**
+     * Get a map of JNDI names/class names (as attribute).
+     *
+     * @return the MBean attribute containing the map of names/class names.
+     * @throws MBeanException
+     */
+    public Map<String, String> getNames() throws MBeanException;
+
+    /**
+     * Get a list of JNDI sub-contexts (as attribute).
+     *
+     * @return the MBean attribute containing the list of sub-contexts.
+     * @throws MBeanException
+     */
+    public List<String> getContexts() throws MBeanException;
+
+    /**
+     * Get a map of JNDI names/class names children of a given base context.
+     *
+     * @param context the base context.
+     * @return the map of names/class names.
+     * @throws MBeanException
+     */
+    public Map<String, String> getNames(String context) throws MBeanException;
+
+    /**
+     * Get a list of JNDI sub-contexts children of a given base context.
+     *
+     * @param context the base context.
+     * @return the list of sub-contexts.
+     * @throws MBeanException
+     */
+    public List<String> getContexts(String context) throws MBeanException;
+
+    /**
+     * Create a JNDI sub-context.
+     *
+     * @param context the JNDI sub-context name.
+     * @throws MBeanException
+     */
+    public void create(String context) throws MBeanException;
+
+    /**
+     * Delete a JNDI sub-context.
+     *
+     * @param context the JNDI sub-context name.
+     * @throws MBeanException
+     */
+    public void delete(String context) throws MBeanException;
+
+    /**
+     * Create another JNDI name (alias) for a given one.
+     *
+     * @param name the "source" JNDI name.
+     * @param alias the JNDI alias name.
+     * @throws MBeanException
+     */
+    public void alias(String name, String alias) throws MBeanException;
+
+    /**
+     * Bind an OSGi service with a JNDI name.
+     *
+     * @param serviceId the OSGi service id (service.id property on the service, created by the framework).
+     * @param name the JNDI name.
+     * @throws MBeanException
+     */
+    public void bind(Long serviceId, String name) throws MBeanException;
+
+    /**
+     * Unbind a given JNDI name.
+     *
+     * @param name the JNDI name.
+     * @throws MBeanException
+     */
+    public void unbind(String name) throws MBeanException;
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/85c65dd6/jndi/src/main/java/org/apache/karaf/jndi/JndiService.java
----------------------------------------------------------------------
diff --git a/jndi/src/main/java/org/apache/karaf/jndi/JndiService.java b/jndi/src/main/java/org/apache/karaf/jndi/JndiService.java
new file mode 100644
index 0000000..c9f9c57
--- /dev/null
+++ b/jndi/src/main/java/org/apache/karaf/jndi/JndiService.java
@@ -0,0 +1,103 @@
+/*
+ * 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.karaf.jndi;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * JNDI Service.
+ */
+public interface JndiService {
+
+    /**
+     * List the current JNDI names (with the bound class name).
+     *
+     * @return the JNDI names.
+     * @throws Exception
+     */
+    Map<String, String> names() throws Exception;
+
+    /**
+     * List the current JNDI names in the given context.
+     *
+     * @param context the JNDI context.
+     * @return the JNDI names in the context.
+     * @throws Exception
+     */
+    Map<String, String> names(String context) throws Exception;
+
+    /**
+     * List all JNDI sub-contexts.
+     *
+     * @return a list containing the sub-context names.
+     * @throws Exception
+     */
+    List<String> contexts() throws Exception;
+
+    /**
+     * List the JNDI sub-context from a given context.
+     *
+     * @param context the base JNDI context.
+     * @return a list containing the sub-context names.
+     * @throws Exception
+     */
+    List<String> contexts(String context) throws Exception;
+
+    /**
+     * Create a sub-context.
+     *
+     * @param context the new sub-context name to create.
+     * @throws Exception
+     */
+    void create(String context) throws Exception;
+
+    /**
+     * Delete a sub-context.
+     *
+     * @param context the sub-context name to delete.
+     * @throws Exception
+     */
+    void delete(String context) throws Exception;
+
+    /**
+     * Create an alias on a given JNDI name.
+     *
+     * @param name the JNDI name.
+     * @param alias the alias.
+     * @throws Exception
+     */
+    void alias(String name, String alias) throws Exception;
+
+    /**
+     * Bind a given OSGi service to a JNDI name.
+     *
+     * @param serviceId the OSGi service ID.
+     * @param name the JNDI name.
+     * @throws Exception
+     */
+    void bind(long serviceId, String name) throws Exception;
+
+    /**
+     * Unbind an existing name.
+     *
+     * @param name the JNDI name to unbind.
+     * @throws Exception
+     */
+    void unbind(String name) throws Exception;
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/85c65dd6/jndi/src/main/java/org/apache/karaf/jndi/KarafInitialContextFactory.java
----------------------------------------------------------------------
diff --git a/jndi/src/main/java/org/apache/karaf/jndi/KarafInitialContextFactory.java b/jndi/src/main/java/org/apache/karaf/jndi/KarafInitialContextFactory.java
new file mode 100644
index 0000000..a540556
--- /dev/null
+++ b/jndi/src/main/java/org/apache/karaf/jndi/KarafInitialContextFactory.java
@@ -0,0 +1,33 @@
+/*
+ * 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.karaf.jndi;
+
+import org.apache.xbean.naming.context.WritableContext;
+import org.apache.xbean.naming.global.GlobalContextManager;
+
+/**
+ * A very simple writable initial context factory.
+ * @see org.apache.xbean.naming.context.WritableContext for details.
+ */
+public class KarafInitialContextFactory extends GlobalContextManager {
+
+    public KarafInitialContextFactory() throws Exception {
+        super();
+        setGlobalContext(new WritableContext());
+    }
+
+}


[46/59] [abbrv] [KARAF-2852] Merge wrapper/core and wrapper/command

Posted by gn...@apache.org.
http://git-wip-us.apache.org/repos/asf/karaf/blob/4182735c/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/windows/wrapper.dll
----------------------------------------------------------------------
diff --git a/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/windows/wrapper.dll b/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/windows/wrapper.dll
new file mode 100644
index 0000000..cb553c1
Binary files /dev/null and b/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/windows/wrapper.dll differ

http://git-wip-us.apache.org/repos/asf/karaf/blob/4182735c/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/windows64/karaf-service.bat
----------------------------------------------------------------------
diff --git a/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/windows64/karaf-service.bat b/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/windows64/karaf-service.bat
new file mode 100644
index 0000000..0dd0474
--- /dev/null
+++ b/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/windows64/karaf-service.bat
@@ -0,0 +1,51 @@
+@echo off
+
+REM ------------------------------------------------------------------------
+REM Licensed to the Apache Software Foundation (ASF) under one or more
+REM contributor license agreements.  See the NOTICE file distributed with
+REM this work for additional information regarding copyright ownership.
+REM The ASF licenses this file to You under the Apache License, Version 2.0
+REM (the "License"); you may not use this file except in compliance with
+REM the License.  You may obtain a copy of the License at
+REM
+REM http://www.apache.org/licenses/LICENSE-2.0
+REM
+REM Unless required by applicable law or agreed to in writing, software
+REM distributed under the License is distributed on an "AS IS" BASIS,
+REM WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+REM See the License for the specific language governing permissions and
+REM limitations under the License.
+REM ------------------------------------------------------------------------
+
+setlocal
+
+set APP_NAME=${name}
+set APP_LONG_NAME=${displayName}
+set APP_BASE=${karaf.base}
+set APP_ETC=${karaf.etc}
+
+if ""%1"" == ""run"" goto doRun
+if ""%1"" == ""install"" goto doInstall
+if ""%1"" == ""remove"" goto doRemove
+
+echo Usage:  karaf-service ( commands ... )
+echo commands:
+echo   run               Start %APP_NAME% in the current console
+echo   install           Install %APP_NAME% as a Windows service
+echo   remove            Remove the %APP_NAME% Windows service
+goto end
+
+:doRun
+"%APP_BASE%\bin\%APP_NAME%-wrapper.exe" -c "%APP_ETC%\%APP_NAME%-wrapper.conf"
+goto end
+
+:doInstall
+"%APP_BASE%\bin\%APP_NAME%-wrapper.exe" -i "%APP_ETC%\%APP_NAME%-wrapper.conf"
+goto end
+
+:doRemove
+"%APP_BASE%\bin\%APP_NAME%-wrapper.exe" -r "%APP_ETC%\%APP_NAME%-wrapper.conf"
+goto end
+
+:end
+if not "%PAUSE%" == "" pause

http://git-wip-us.apache.org/repos/asf/karaf/blob/4182735c/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/windows64/karaf-wrapper.conf
----------------------------------------------------------------------
diff --git a/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/windows64/karaf-wrapper.conf b/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/windows64/karaf-wrapper.conf
new file mode 100644
index 0000000..def40f7
--- /dev/null
+++ b/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/windows64/karaf-wrapper.conf
@@ -0,0 +1,135 @@
+# ------------------------------------------------------------------------
+# 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.
+# ------------------------------------------------------------------------
+
+#********************************************************************
+# Wrapper Properties
+#********************************************************************
+set.default.JAVA_HOME=${java.home}
+set.default.KARAF_HOME=${karaf.home}
+set.default.KARAF_BASE=${karaf.base}
+set.default.KARAF_DATA=${karaf.data}
+set.default.KARAF_ETC=${karaf.etc}
+
+# Java Application
+wrapper.working.dir=%KARAF_BASE%
+wrapper.java.command=%JAVA_HOME%/bin/java
+wrapper.java.mainclass=org.apache.karaf.wrapper.internal.Main
+wrapper.java.classpath.1=%KARAF_HOME%/lib/karaf-wrapper.jar
+wrapper.java.classpath.2=%KARAF_HOME%/lib/karaf.jar
+wrapper.java.classpath.3=%KARAF_HOME%/lib/karaf-jmx-boot.jar
+wrapper.java.classpath.4=%KARAF_HOME%/lib/karaf-jaas-boot.jar
+wrapper.java.classpath.5=%KARAF_HOME%/lib/karaf-wrapper-main.jar
+wrapper.java.classpath.6=%KARAF_HOME%/lib/karaf-org.osgi.core.jar
+wrapper.java.library.path.1=%KARAF_HOME%/lib/
+
+# Application Parameters.  Add parameters as needed starting from 1
+#wrapper.app.parameter.1=
+
+# JVM Parameters
+# note that n is the parameter number starting from 1.
+wrapper.java.additional.1=-Dkaraf.home="%KARAF_HOME%"
+wrapper.java.additional.2=-Dkaraf.base="%KARAF_BASE%"
+wrapper.java.additional.3=-Dkaraf.data="%KARAF_DATA%"
+wrapper.java.additional.4=-Dkaraf.etc="%KARAF_ETC%"
+wrapper.java.additional.5=-Dcom.sun.management.jmxremote
+wrapper.java.additional.6=-Djavax.management.builder.initial=org.apache.karaf.management.boot.KarafMBeanServerBuilder
+wrapper.java.additional.7=-Dkaraf.startLocalConsole=false
+wrapper.java.additional.8=-Dkaraf.startRemoteShell=true
+wrapper.java.additional.9=-Djava.endorsed.dirs="%JAVA_HOME%/jre/lib/endorsed;%JAVA_HOME%/lib/endorsed;%KARAF_HOME%/lib/endorsed"
+wrapper.java.additional.10=-Djava.ext.dirs="%JAVA_HOME%/jre/lib/ext;%JAVA_HOME%/lib/ext;%KARAF_HOME%/lib/ext"
+
+# Uncomment to enable jmx
+#wrapper.java.additional.n=-Dcom.sun.management.jmxremote.port=1616
+#wrapper.java.additional.n=-Dcom.sun.management.jmxremote.authenticate=false
+#wrapper.java.additional.n=-Dcom.sun.management.jmxremote.ssl=false
+
+# Uncomment to enable YourKit profiling
+#wrapper.java.additional.n=-Xrunyjpagent
+
+# Uncomment to enable remote debugging
+#wrapper.java.additional.n=-Xdebug -Xnoagent -Djava.compiler=NONE
+#wrapper.java.additional.n=-Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005
+
+# Initial Java Heap Size (in MB)
+#wrapper.java.initmemory=3
+
+# Maximum Java Heap Size (in MB)
+wrapper.java.maxmemory=512
+
+
+#********************************************************************
+# Wrapper Logging Properties
+#********************************************************************
+# Format of output for the console.  (See docs for formats)
+wrapper.console.format=PM
+
+# Log Level for console output.  (See docs for log levels)
+wrapper.console.loglevel=INFO
+
+# Log file to use for wrapper output logging.
+wrapper.logfile=%KARAF_DATA%/log/wrapper.log
+
+# Format of output for the log file.  (See docs for formats)
+wrapper.logfile.format=LPTM
+
+# Log Level for log file output.  (See docs for log levels)
+wrapper.logfile.loglevel=INFO
+
+# Maximum size that the log file will be allowed to grow to before
+#  the log is rolled. Size is specified in bytes.  The default value
+#  of 0, disables log rolling.  May abbreviate with the 'k' (kb) or
+#  'm' (mb) suffix.  For example: 10m = 10 megabytes.
+wrapper.logfile.maxsize=10m
+
+# Maximum number of rolled log files which will be allowed before old
+#  files are deleted.  The default value of 0 implies no limit.
+wrapper.logfile.maxfiles=5
+
+# Log Level for sys/event log output.  (See docs for log levels)
+wrapper.syslog.loglevel=NONE
+
+#********************************************************************
+# Wrapper Windows Properties
+#********************************************************************
+# Title to use when running as a console
+wrapper.console.title=${name}
+
+#********************************************************************
+# Wrapper Windows NT/2000/XP Service Properties
+#********************************************************************
+# WARNING - Do not modify any of these properties when an application
+#  using this configuration file has been installed as a service.
+#  Please uninstall the service before modifying this section.  The
+#  service can then be reinstalled.
+
+# Name of the service
+wrapper.ntservice.name=${name}
+
+# Display name of the service
+wrapper.ntservice.displayname=${displayName}
+
+# Description of the service
+wrapper.ntservice.description=${description}
+
+# Service dependencies.  Add dependencies as needed starting from 1
+wrapper.ntservice.dependency.1=
+
+# Mode in which the service is installed.  AUTO_START or DEMAND_START
+wrapper.ntservice.starttype=${startType}
+
+# Allow the service to interact with the desktop.
+wrapper.ntservice.interactive=false

http://git-wip-us.apache.org/repos/asf/karaf/blob/4182735c/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/windows64/karaf-wrapper.exe
----------------------------------------------------------------------
diff --git a/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/windows64/karaf-wrapper.exe b/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/windows64/karaf-wrapper.exe
new file mode 100755
index 0000000..db2ddda
Binary files /dev/null and b/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/windows64/karaf-wrapper.exe differ

http://git-wip-us.apache.org/repos/asf/karaf/blob/4182735c/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/windows64/wrapper.dll
----------------------------------------------------------------------
diff --git a/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/windows64/wrapper.dll b/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/windows64/wrapper.dll
new file mode 100644
index 0000000..f07fc9e
Binary files /dev/null and b/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/windows64/wrapper.dll differ


[08/59] [abbrv] [KARAF-2852] Merge features/core and features/command

Posted by gn...@apache.org.
http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/src/main/java/org/apache/karaf/features/RegionsPersistence.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/RegionsPersistence.java b/features/src/main/java/org/apache/karaf/features/RegionsPersistence.java
new file mode 100644
index 0000000..96ca7da
--- /dev/null
+++ b/features/src/main/java/org/apache/karaf/features/RegionsPersistence.java
@@ -0,0 +1,26 @@
+/*
+ * 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.karaf.features;
+
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleException;
+
+public interface RegionsPersistence {
+    void install(Bundle b, String regionName) throws BundleException;
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/src/main/java/org/apache/karaf/features/Repository.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/Repository.java b/features/src/main/java/org/apache/karaf/features/Repository.java
new file mode 100644
index 0000000..6ee96da
--- /dev/null
+++ b/features/src/main/java/org/apache/karaf/features/Repository.java
@@ -0,0 +1,36 @@
+/*
+ * 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.karaf.features;
+
+import java.net.URI;
+
+/**
+ * A repository of features.
+ */
+public interface Repository {
+
+    String getName();
+
+    URI getURI();
+
+    URI[] getRepositories() throws Exception;
+
+    Feature[] getFeatures() throws Exception;
+    
+    boolean isValid();
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/src/main/java/org/apache/karaf/features/RepositoryEvent.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/RepositoryEvent.java b/features/src/main/java/org/apache/karaf/features/RepositoryEvent.java
new file mode 100644
index 0000000..68f287b
--- /dev/null
+++ b/features/src/main/java/org/apache/karaf/features/RepositoryEvent.java
@@ -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.karaf.features;
+
+import java.util.EventObject;
+
+public class RepositoryEvent extends EventObject {
+
+    public static enum EventType {
+        RepositoryAdded,
+        RepositoryRemoved,
+    }
+
+    private final EventType type;
+    private final Repository repository;
+    private final boolean replay;
+
+    public RepositoryEvent(Repository repository, EventType type, boolean replay) {
+        super(repository);
+        this.type = type;
+        this.repository = repository;
+        this.replay = replay;
+    }
+
+    public EventType getType() {
+        return type;
+    }
+
+    public Repository getRepository() {
+        return repository;
+    }
+
+    public boolean isReplay() {
+        return replay;
+    }
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/src/main/java/org/apache/karaf/features/Requirement.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/Requirement.java b/features/src/main/java/org/apache/karaf/features/Requirement.java
new file mode 100644
index 0000000..4446335
--- /dev/null
+++ b/features/src/main/java/org/apache/karaf/features/Requirement.java
@@ -0,0 +1,23 @@
+/*
+ * 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.karaf.features;
+
+public interface Requirement {
+
+    String getValue();
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/src/main/java/org/apache/karaf/features/Resolver.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/Resolver.java b/features/src/main/java/org/apache/karaf/features/Resolver.java
new file mode 100644
index 0000000..d2fa941
--- /dev/null
+++ b/features/src/main/java/org/apache/karaf/features/Resolver.java
@@ -0,0 +1,25 @@
+/*
+ * 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.karaf.features;
+
+import java.util.List;
+
+public interface Resolver {
+
+    List<BundleInfo> resolve(Feature feature) throws Exception;
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/src/main/java/org/apache/karaf/features/command/FeaturesCommandSupport.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/command/FeaturesCommandSupport.java b/features/src/main/java/org/apache/karaf/features/command/FeaturesCommandSupport.java
new file mode 100644
index 0000000..076650d
--- /dev/null
+++ b/features/src/main/java/org/apache/karaf/features/command/FeaturesCommandSupport.java
@@ -0,0 +1,42 @@
+/*
+ * 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.karaf.features.command;
+
+import org.apache.karaf.features.FeaturesService;
+import org.apache.karaf.shell.api.action.Action;
+import org.apache.karaf.shell.api.action.lifecycle.Reference;
+
+public abstract class FeaturesCommandSupport implements Action {
+
+    @Reference
+    private FeaturesService featuresService;
+
+    @Override
+    public Object execute() throws Exception {
+        if (featuresService == null) {
+            throw new IllegalStateException("FeaturesService not found");
+        }
+        doExecute(featuresService);
+        return null;
+    }
+
+    protected abstract void doExecute(FeaturesService admin) throws Exception;
+
+    public void setFeaturesService(FeaturesService featuresService) {
+        this.featuresService = featuresService;
+    }
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/src/main/java/org/apache/karaf/features/command/InfoFeatureCommand.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/command/InfoFeatureCommand.java b/features/src/main/java/org/apache/karaf/features/command/InfoFeatureCommand.java
new file mode 100644
index 0000000..7084a6e
--- /dev/null
+++ b/features/src/main/java/org/apache/karaf/features/command/InfoFeatureCommand.java
@@ -0,0 +1,292 @@
+/*
+ * 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.karaf.features.command;
+
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.karaf.features.BundleInfo;
+import org.apache.karaf.features.Conditional;
+import org.apache.karaf.features.ConfigFileInfo;
+import org.apache.karaf.features.Dependency;
+import org.apache.karaf.features.Feature;
+import org.apache.karaf.features.FeaturesService;
+import org.apache.karaf.features.command.completers.AllFeatureCompleter;
+import org.apache.karaf.shell.api.action.Argument;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.Completion;
+import org.apache.karaf.shell.api.action.Option;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+
+@Command(scope = "feature", name = "info", description = "Shows information about selected feature.")
+@Service
+public class InfoFeatureCommand extends FeaturesCommandSupport {
+
+    private static final String INDENT = "  ";
+    private static final String FEATURE_CONTENT = "Feature";
+    private static final String CONDITIONAL_CONTENT = "Conditional(%s)";
+
+	@Argument(index = 0, name = "name", description = "The name of the feature", required = true, multiValued = false)
+    @Completion(AllFeatureCompleter.class)
+    private String name;
+
+    @Argument(index = 1, name = "version", description = "The version of the feature", required = false, multiValued = false)
+    private String version;
+
+    @Option(name = "-c", aliases={"--configuration"}, description="Display configuration info", required = false, multiValued = false)
+    private boolean config;
+
+    @Option(name = "-d", aliases={"--dependency"}, description="Display dependencies info", required = false, multiValued = false)
+    private boolean dependency;
+
+    @Option(name = "-b", aliases={"--bundle"}, description="Display bundles info", required = false, multiValued = false)
+    private boolean bundle;
+
+    @Option(name = "--conditional", description="Display conditional info", required = false, multiValued = false)
+    private boolean conditional;
+
+    @Option(name = "-t", aliases={"--tree"}, description="Display feature tree", required = false, multiValued = false)
+    private boolean tree;
+
+    protected void doExecute(FeaturesService admin) throws Exception {
+        Feature feature = null;
+
+        if (version != null && version.length() > 0) {
+            feature = admin.getFeature(name, version);
+        } else {
+            feature = admin.getFeature(name);
+        }
+
+        if (feature == null) {
+            System.out.println("Feature not found");
+            return;
+        }
+
+        // default behavior
+        if (!config && !dependency && !bundle && !conditional) {
+            config = true;
+            dependency = true;
+            bundle = true;
+            conditional = true;
+        }
+
+        System.out.println("Feature " + feature.getName() + " " + feature.getVersion());
+        if (feature.getDescription() != null) {
+        	System.out.println("Description:");
+        	System.out.println(INDENT + feature.getDescription());
+        }
+        
+        if(feature.getDetails() != null) {
+        	System.out.println("Details:");
+        	printWithIndent(feature.getDetails());
+        }
+
+        if (config) {
+            displayConfigInformation(feature, FEATURE_CONTENT);
+            displayConfigFileInformation(feature, FEATURE_CONTENT);
+        }
+
+        if (dependency) {
+            displayDependencyInformation(feature, FEATURE_CONTENT);
+        }
+
+        if (bundle) {
+            displayBundleInformation(feature, FEATURE_CONTENT);
+        }
+
+        if(conditional) {
+           displayConditionalInfo(feature);
+        }
+
+        if (tree) {
+            if (config || dependency || bundle) {
+                System.out.println("\nFeature tree");
+            }
+
+            int unresolved = displayFeatureTree(admin, feature.getName(), feature.getVersion(), "");
+            if (unresolved > 0) {
+                System.out.println("Tree contains " + unresolved + " unresolved dependencies");
+                System.out.println(" * means that node declares dependency but the dependent feature is not available.");
+            }
+        }
+    }
+
+    private void printWithIndent(String details) {
+    	String[] lines = details.split("\r?\n");
+    	for (String line : lines) {
+			System.out.println(INDENT + line);
+		}
+	}
+
+	private void displayBundleInformation(Feature feature, String contentType) {
+        List<BundleInfo> bundleInfos = feature.getBundles();
+        if (bundleInfos.isEmpty()) {
+            System.out.println(contentType + " has no bundles.");
+        } else {
+            System.out.println(contentType + " contains followed bundles:");
+            for (BundleInfo featureBundle : bundleInfos) {
+                int startLevel = featureBundle.getStartLevel();
+                StringBuilder sb = new StringBuilder();
+                sb.append(INDENT).append(featureBundle.getLocation());
+                if(startLevel > 0) {
+                    sb.append(" start-level=").append(startLevel);
+                }
+                System.out.println(sb.toString());
+            }
+        }
+    }
+
+    private void displayDependencyInformation(Feature feature, String contentType) {
+        List<Dependency> dependencies = feature.getDependencies();
+        if (dependencies.isEmpty()) {
+            System.out.println(contentType + " has no dependencies.");
+        } else {
+            System.out.println(contentType + " depends on:");
+            for (Dependency featureDependency : dependencies) {
+                System.out.println(INDENT + featureDependency.getName() + " " + featureDependency.getVersion());
+            }
+        }
+    }
+
+    private void displayConfigInformation(Feature feature, String contentType) {
+        Map<String, Map<String, String>> configurations = feature.getConfigurations();
+        if (configurations.isEmpty()) {
+            System.out.println(contentType + " has no configuration");
+        } else {
+            System.out.println(contentType + " configuration:");
+            for (String name : configurations.keySet()) {
+                System.out.println(INDENT + name);
+            }
+        }
+    }
+    
+    private void displayConfigFileInformation(Feature feature, String contentType) {
+    	List<ConfigFileInfo> configurationFiles = feature.getConfigurationFiles();
+    	if (configurationFiles.isEmpty()) {
+    		System.out.println(contentType + " has no configuration files");
+    	} else {
+    		System.out.println(contentType + " configuration files: ");
+    		for (ConfigFileInfo configFileInfo : configurationFiles) {
+				System.out.println(INDENT + configFileInfo.getFinalname());
+			}
+    	}    	
+    }
+
+    /**
+     * Called originally with featureName and featureVersion that have already been resolved successfully.
+     *
+     * @param admin
+     * @param featureName
+     * @param featureVersion
+     * @param prefix
+     * @return
+     * @throws Exception
+     */
+    private int displayFeatureTree(FeaturesService admin, String featureName, String featureVersion, String prefix) throws Exception {
+        int unresolved = 0;
+
+        Feature resolved = admin.getFeature(featureName, featureVersion);
+        if (resolved != null) {
+            System.out.println(prefix + " " + resolved.getName() + " " + resolved.getVersion());
+        } else {
+            System.out.println(prefix + " " + featureName + " " + featureVersion + " *");
+            unresolved++;
+        }
+
+        if (resolved != null) {
+            if (bundle) {
+                List<String> bundleLocation = new LinkedList<String>();
+                List<BundleInfo> bundles = resolved.getBundles();
+                for (BundleInfo bundleInfo : bundles) {
+                    bundleLocation.add(bundleInfo.getLocation());
+                }
+
+                if (conditional) {
+                    for (Conditional cond : resolved.getConditional()) {
+                        List<? extends Dependency> condition = cond.getCondition();
+                        List<BundleInfo> conditionalBundles = cond.getBundles();
+                        for (BundleInfo bundleInfo : conditionalBundles) {
+                            bundleLocation.add(bundleInfo.getLocation() + "(condition:"+condition+")");
+                        }
+                    }
+                }
+                for (int i = 0, j = bundleLocation.size(); i < j; i++) {
+                    System.out.println(prefix + " " + (i + 1 == j ? "\\" : "+") + " " + bundleLocation.get(i));
+                }
+            }
+            prefix += "   ";
+            List<Dependency> dependencies = resolved.getDependencies();
+            for (int i = 0, j = dependencies.size(); i < j; i++) {
+                Dependency toDisplay =  dependencies.get(i);
+                unresolved += displayFeatureTree(admin, toDisplay.getName(), toDisplay.getVersion(), prefix +1);
+            }
+
+            if (conditional) {
+                for (Conditional cond : resolved.getConditional()) {
+                    List<Dependency> conditionDependencies = cond.getDependencies();
+                    for (int i = 0, j = conditionDependencies.size(); i < j; i++) {
+                        Dependency toDisplay =  dependencies.get(i);
+                        unresolved += displayFeatureTree(admin, toDisplay.getName(), toDisplay.getVersion(), prefix +1);
+                    }
+                }
+            }
+        }
+
+        return unresolved;
+    }
+
+    private void displayConditionalInfo(Feature feature) {
+        List<? extends Conditional> conditionals = feature.getConditional();
+        if (conditionals.isEmpty()) {
+            System.out.println("Feature has no conditionals.");
+        } else {
+            System.out.println("Feature contains followed conditionals:");
+            for (Conditional featureConditional : conditionals) {
+                String conditionDescription = getConditionDescription(featureConditional);
+                Feature wrappedConditional = featureConditional.asFeature(feature.getName(), feature.getVersion());
+                if (config) {
+                    displayConfigInformation(wrappedConditional, String.format(CONDITIONAL_CONTENT, conditionDescription));
+                    displayConfigFileInformation(wrappedConditional, String.format(CONDITIONAL_CONTENT, conditionDescription));
+                }
+
+                if (dependency) {
+                    displayDependencyInformation(wrappedConditional, String.format(CONDITIONAL_CONTENT, conditionDescription));
+                }
+
+                if (bundle) {
+                    displayBundleInformation(wrappedConditional, String.format(CONDITIONAL_CONTENT, conditionDescription));
+                }
+            }
+        }
+    }
+
+    private String getConditionDescription(Conditional cond) {
+        StringBuffer sb = new StringBuffer();
+        Iterator<? extends Dependency> di = cond.getCondition().iterator();
+        while (di.hasNext()) {
+            Dependency dep = di.next();
+            sb.append(dep.getName()).append("/").append(dep.getVersion());
+            if (di.hasNext()) {
+                sb.append(" ");
+            }
+        }
+        return sb.toString();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/src/main/java/org/apache/karaf/features/command/InstallFeatureCommand.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/command/InstallFeatureCommand.java b/features/src/main/java/org/apache/karaf/features/command/InstallFeatureCommand.java
new file mode 100644
index 0000000..b7f8184
--- /dev/null
+++ b/features/src/main/java/org/apache/karaf/features/command/InstallFeatureCommand.java
@@ -0,0 +1,69 @@
+/*
+ * 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.karaf.features.command;
+
+import java.util.EnumSet;
+import java.util.HashSet;
+import java.util.List;
+
+import org.apache.karaf.features.FeaturesService;
+import org.apache.karaf.features.command.completers.AvailableFeatureCompleter;
+import org.apache.karaf.shell.api.action.Argument;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.Completion;
+import org.apache.karaf.shell.api.action.Option;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+
+@Command(scope = "feature", name = "install", description = "Installs a feature with the specified name and version.")
+@Service
+public class InstallFeatureCommand extends FeaturesCommandSupport {
+
+    private static String DEFAULT_VERSION = "0.0.0";
+
+    @Argument(index = 0, name = "feature", description = "The name and version of the features to install. A feature id looks like name/version. The version is optional.", required = true, multiValued = true)
+    @Completion(AvailableFeatureCompleter.class)
+    List<String> features;
+
+    @Option(name = "-r", aliases = "--no-auto-refresh", description = "Do not automatically refresh bundles", required = false, multiValued = false)
+    boolean noRefresh;
+
+    @Option(name = "-s", aliases = "--no-auto-start", description = "Do not start the bundles", required = false, multiValued = false)
+    boolean noStart;
+
+    @Option(name = "-v", aliases = "--verbose", description = "Explain what is being done", required = false, multiValued = false)
+    boolean verbose;
+
+    @Option(name = "-t", aliases = "--simulate", description = "Perform a simulation only", required = false, multiValued = false)
+    boolean simulate;
+
+    protected void doExecute(FeaturesService admin) throws Exception {
+        EnumSet<FeaturesService.Option> options = EnumSet.noneOf(FeaturesService.Option.class);
+        if (simulate) {
+            options.add(FeaturesService.Option.Simulate);
+        }
+        if (noStart) {
+            options.add(FeaturesService.Option.NoAutoStartBundles);
+        }
+        if (noRefresh) {
+            options.add(FeaturesService.Option.NoAutoRefreshBundles);
+        }
+        if (verbose) {
+            options.add(FeaturesService.Option.Verbose);
+        }
+        admin.installFeatures(new HashSet<String>(features), options);
+    }
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/src/main/java/org/apache/karaf/features/command/ListFeatureVersionsCommand.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/command/ListFeatureVersionsCommand.java b/features/src/main/java/org/apache/karaf/features/command/ListFeatureVersionsCommand.java
new file mode 100644
index 0000000..b2c5e42
--- /dev/null
+++ b/features/src/main/java/org/apache/karaf/features/command/ListFeatureVersionsCommand.java
@@ -0,0 +1,62 @@
+/*
+ * 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.karaf.features.command;
+
+import java.util.Arrays;
+
+import org.apache.karaf.features.Feature;
+import org.apache.karaf.features.FeaturesService;
+import org.apache.karaf.features.Repository;
+import org.apache.karaf.features.command.completers.AllFeatureCompleter;
+import org.apache.karaf.shell.api.action.Argument;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.Completion;
+import org.apache.karaf.shell.api.action.Option;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.apache.karaf.shell.support.table.ShellTable;
+
+@Command(scope = "feature", name = "version-list", description = "Lists all versions of a feature available from the currently available repositories.")
+@Service
+public class ListFeatureVersionsCommand extends FeaturesCommandSupport {
+
+	@Argument(index = 0, name = "feature", description = "Name of feature.", required = true, multiValued = false)
+    @Completion(AllFeatureCompleter.class)
+	String feature;
+
+    @Option(name = "--no-format", description = "Disable table rendered output", required = false, multiValued = false)
+    boolean noFormat;
+
+    protected void doExecute(FeaturesService admin) throws Exception {
+        ShellTable table = new ShellTable();
+        table.column("Version");
+        table.column("Repository");
+        table.column("Repository URL");
+        table.emptyTableText("No versions available for features '" + feature + "'");
+             
+        for (Repository r : Arrays.asList(admin.listRepositories())) {
+            for (Feature f : r.getFeatures()) {
+
+                if (f.getName().equals(feature)) {
+                    table.addRow().addContent(f.getVersion(), r.getName(), r.getURI());
+                }
+            }
+        }
+
+        table.print(System.out, !noFormat);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/src/main/java/org/apache/karaf/features/command/ListFeaturesCommand.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/command/ListFeaturesCommand.java b/features/src/main/java/org/apache/karaf/features/command/ListFeaturesCommand.java
new file mode 100644
index 0000000..e86ff64
--- /dev/null
+++ b/features/src/main/java/org/apache/karaf/features/command/ListFeaturesCommand.java
@@ -0,0 +1,106 @@
+/*
+ * 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.karaf.features.command;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
+import org.apache.karaf.features.Feature;
+import org.apache.karaf.features.FeaturesService;
+import org.apache.karaf.features.Repository;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.Option;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.apache.karaf.shell.support.table.ShellTable;
+
+@Command(scope = "feature", name = "list", description = "Lists all existing features available from the defined repositories.")
+@Service
+public class ListFeaturesCommand extends FeaturesCommandSupport {
+
+    @Option(name = "-i", aliases = {"--installed"}, description = "Display a list of all installed features only", required = false, multiValued = false)
+    boolean onlyInstalled;
+
+    @Option(name = "-r", aliases = {"--required"}, description = "Display a list of all required features only", required = false, multiValued = false)
+    boolean onlyRequired;
+
+    @Option(name = "-o", aliases = {"--ordered"}, description = "Display a list using alphabetical order ", required = false, multiValued = false)
+    boolean ordered;
+
+    @Option(name = "--no-format", description = "Disable table rendered output", required = false, multiValued = false)
+    boolean noFormat;
+
+    protected void doExecute(FeaturesService featuresService) throws Exception {
+        boolean needsLegend = false;
+        
+        ShellTable table = new ShellTable();
+        table.column("Name");
+        table.column("Version");
+        table.column("Required");
+        table.column("Installed");
+        table.column("Repository");
+        table.column("Description").maxSize(50);
+        table.emptyTableText(onlyInstalled ? "No features installed" : "No features available");
+
+        List<Repository> repos = Arrays.asList(featuresService.listRepositories());
+        for (Repository r : repos) {
+            List<Feature> features = Arrays.asList(r.getFeatures());
+            if (ordered) {
+                Collections.sort(features, new FeatureComparator());
+            }
+            for (Feature f : features) {
+                if (onlyInstalled && !featuresService.isInstalled(f)) {
+                    // Filter out not installed features if we only want to see the installed ones
+                    continue;
+                }
+                if (onlyRequired && !featuresService.isRequired(f)) {
+                    // Filter out not installed features if we only want to see the installed ones
+                    continue;
+                }
+                table.addRow().addContent(
+                        f.getName(),
+                        f.getVersion(),
+                        featuresService.isRequired(f) ? "x" : "",
+                        featuresService.isInstalled(f) ? "x" : "",
+                        r.getName(),
+                        f.getDescription());
+                if (isInstalledViaDeployDir(r.getName())) {
+                    needsLegend = true;
+                }
+            }
+        }
+
+        table.print(System.out, !noFormat);
+
+        if (needsLegend) {
+            System.out.println("* Installed via deploy directory");
+        }
+
+    }
+
+    private boolean isInstalledViaDeployDir(String st) {
+        return (st == null || st.length() <= 1) ? false : (st.charAt(st.length() - 1) == '*');
+    }
+
+    class FeatureComparator implements Comparator<Feature> {
+        public int compare(Feature o1, Feature o2) {
+            return o1.getName().toLowerCase().compareTo( o2.getName().toLowerCase() );
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/src/main/java/org/apache/karaf/features/command/RepoAddCommand.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/command/RepoAddCommand.java b/features/src/main/java/org/apache/karaf/features/command/RepoAddCommand.java
new file mode 100644
index 0000000..16faf42
--- /dev/null
+++ b/features/src/main/java/org/apache/karaf/features/command/RepoAddCommand.java
@@ -0,0 +1,54 @@
+/*
+ * 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.karaf.features.command;
+
+import java.net.URI;
+
+import org.apache.karaf.features.FeaturesService;
+import org.apache.karaf.features.command.completers.AvailableRepoNameCompleter;
+import org.apache.karaf.shell.api.action.Argument;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.Completion;
+import org.apache.karaf.shell.api.action.Option;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+
+@Command(scope = "feature", name = "repo-add", description = "Add a features repository")
+@Service
+public class RepoAddCommand extends FeaturesCommandSupport {
+
+    @Argument(index = 0, name = "name/url", description = "Shortcut name of the features repository or the full URL", required = true, multiValued = false)
+    @Completion(AvailableRepoNameCompleter.class)
+    private String nameOrUrl;
+    
+    @Argument(index = 1, name = "version", description = "The version of the features repository if using features repository name as first argument. It should be empty if using the URL", required = false, multiValued = false)
+    private String version;
+
+    @Option(name = "-i", aliases = { "--install" }, description = "Install all features contained in the features repository", required = false, multiValued = false)
+    private boolean install;
+
+    @Override
+    protected void doExecute(FeaturesService featuresService) throws Exception {
+        String effectiveVersion = (version == null) ? "LATEST" : version;
+        URI uri = featuresService.getRepositoryUriFor(nameOrUrl, effectiveVersion);
+        if (uri == null) {
+            uri = new URI(nameOrUrl);
+        }
+        System.out.println("Adding feature url " + uri);
+        featuresService.addRepository(uri, install);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/src/main/java/org/apache/karaf/features/command/RepoListCommand.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/command/RepoListCommand.java b/features/src/main/java/org/apache/karaf/features/command/RepoListCommand.java
new file mode 100644
index 0000000..591a1c6
--- /dev/null
+++ b/features/src/main/java/org/apache/karaf/features/command/RepoListCommand.java
@@ -0,0 +1,71 @@
+/*
+ * 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.karaf.features.command;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.karaf.features.FeaturesService;
+import org.apache.karaf.features.Repository;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.Option;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.apache.karaf.shell.support.MultiException;
+import org.apache.karaf.shell.support.table.ShellTable;
+
+@Command(scope = "feature", name = "repo-list", description = "Displays a list of all defined repositories.")
+@Service
+public class RepoListCommand extends FeaturesCommandSupport {
+
+    @Option(name="-r", description="Reload all feature urls", required = false, multiValued = false)
+    boolean reload;
+
+    @Option(name = "--no-format", description = "Disable table rendered output", required = false, multiValued = false)
+    boolean noFormat;
+    
+    protected void doExecute(FeaturesService featuresService) throws Exception {
+        if (reload) {
+            reloadAllRepos(featuresService);
+        }
+        
+        ShellTable table = new ShellTable();
+        table.column("Repository");
+        table.column("URL");
+        table.emptyTableText("No repositories available");
+
+        Repository[] repos = featuresService.listRepositories();
+     	for (Repository repo : repos) {
+     	    table.addRow().addContent(repo.getName(), repo.getURI().toString()); 
+     	}
+     	table.print(System.out, !noFormat);
+    }
+
+    private void reloadAllRepos(FeaturesService featuresService) throws Exception {
+        System.out.println("Reloading all repositories from their urls");
+        System.out.println();
+        List<Exception> exceptions = new ArrayList<Exception>();
+        for (Repository repo : featuresService.listRepositories()) {
+            try {
+                featuresService.addRepository(repo.getURI());
+            } catch (Exception e) {
+                exceptions.add(e);
+            }
+        }
+        MultiException.throwIf("Unable to reload repositories", exceptions);
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/src/main/java/org/apache/karaf/features/command/RepoRefreshCommand.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/command/RepoRefreshCommand.java b/features/src/main/java/org/apache/karaf/features/command/RepoRefreshCommand.java
new file mode 100644
index 0000000..8c7ed79
--- /dev/null
+++ b/features/src/main/java/org/apache/karaf/features/command/RepoRefreshCommand.java
@@ -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.karaf.features.command;
+
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.karaf.features.FeaturesService;
+import org.apache.karaf.features.Repository;
+import org.apache.karaf.features.command.completers.InstalledRepoUriCompleter;
+import org.apache.karaf.shell.api.action.Argument;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.Completion;
+
+@Command(scope = "feature", name = "repo-refresh", description = "Refresh a features repository")
+public class RepoRefreshCommand extends FeaturesCommandSupport {
+    @Argument(index = 0, name = "Feature name or uri", description = "Shortcut name of the feature repository or the full URI", required = false, multiValued = false)
+    @Completion(InstalledRepoUriCompleter.class)
+    private String nameOrUrl;
+    
+    @Argument(index = 1, name = "Feature version", description = "The version of the feature if using the feature name. Should be empty if using the uri", required = false, multiValued = false)
+    private String version;
+
+    @Override
+    protected void doExecute(FeaturesService featuresService) throws Exception {
+        List<URI> uris = new ArrayList<URI>();
+    	if (nameOrUrl != null) {
+    		String effectiveVersion = (version == null) ? "LATEST" : version;
+        	URI uri = featuresService.getRepositoryUriFor(nameOrUrl, effectiveVersion);
+        	if (uri == null) {
+        		uri = new URI(nameOrUrl);
+        	}
+            uris.add(uri);
+    	} else {
+            Repository[] repos = featuresService.listRepositories();
+            for (Repository repo : repos) {
+                uris.add(repo.getURI());
+            }
+    	}
+        for (URI uri : uris) {
+            try {
+                System.out.println("Refreshing feature url " + uri);
+                featuresService.refreshRepository(uri);
+            } catch (Exception e) {
+                System.err.println("Error refreshing " + uri.toString() + ": " + e.getMessage());
+            }
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/src/main/java/org/apache/karaf/features/command/RepoRemoveCommand.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/command/RepoRemoveCommand.java b/features/src/main/java/org/apache/karaf/features/command/RepoRemoveCommand.java
new file mode 100644
index 0000000..0710b72
--- /dev/null
+++ b/features/src/main/java/org/apache/karaf/features/command/RepoRemoveCommand.java
@@ -0,0 +1,56 @@
+/*
+ * 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.karaf.features.command;
+
+import java.net.URI;
+
+import org.apache.karaf.features.FeaturesService;
+import org.apache.karaf.features.Repository;
+import org.apache.karaf.features.command.completers.InstalledRepoNameCompleter;
+import org.apache.karaf.shell.api.action.Argument;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.Completion;
+import org.apache.karaf.shell.api.action.Option;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+
+@Command(scope = "feature", name = "repo-remove", description = "Removes the specified repository features service.")
+@Service
+public class RepoRemoveCommand extends FeaturesCommandSupport {
+
+    @Argument(index = 0, name = "repository", description = "Name or url of the repository to remove.", required = true, multiValued = false)
+    @Completion(InstalledRepoNameCompleter.class)
+    private String repository;
+
+    @Option(name = "-u", aliases = { "--uninstall-all" }, description = "Uninstall all features from the repository", required = false, multiValued = false)
+    private boolean uninstall;
+
+    protected void doExecute(FeaturesService featuresService) throws Exception {
+    	URI uri = null;
+    	for (Repository r : featuresService.listRepositories()) {
+    		if (r.getName() != null && r.getName().equals(repository)) {
+    			uri = r.getURI();
+    			break;
+    		}
+    	}
+
+    	if (uri == null) {
+    	    uri = new URI(repository);
+    	}
+
+    	featuresService.removeRepository(uri, uninstall);
+    }
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/src/main/java/org/apache/karaf/features/command/UninstallFeatureCommand.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/command/UninstallFeatureCommand.java b/features/src/main/java/org/apache/karaf/features/command/UninstallFeatureCommand.java
new file mode 100644
index 0000000..e62f697
--- /dev/null
+++ b/features/src/main/java/org/apache/karaf/features/command/UninstallFeatureCommand.java
@@ -0,0 +1,62 @@
+/*
+ * 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.karaf.features.command;
+
+import java.util.EnumSet;
+import java.util.HashSet;
+import java.util.List;
+
+import org.apache.karaf.features.FeaturesService;
+import org.apache.karaf.features.command.completers.RequiredFeatureCompleter;
+import org.apache.karaf.shell.api.action.Argument;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.Completion;
+import org.apache.karaf.shell.api.action.Option;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+
+@Command(scope = "feature", name = "uninstall", description = "Uninstalls a feature with the specified name and version.")
+@Service
+public class UninstallFeatureCommand extends FeaturesCommandSupport {
+
+    @Argument(index = 0, name = "features", description = "The name and version of the features to uninstall. A feature id looks like name/version. The version is optional.", required = true, multiValued = true)
+    @Completion(RequiredFeatureCompleter.class)
+    List<String> features;
+
+    @Option(name = "-r", aliases = "--no-auto-refresh", description = "Do not automatically refresh bundles", required = false, multiValued = false)
+    boolean noRefresh;
+
+    @Option(name = "-v", aliases = "--verbose", description = "Explain what is being done", required = false, multiValued = false)
+    boolean verbose;
+
+    @Option(name = "-t", aliases = "--simulate", description = "Perform a simulation only", required = false, multiValued = false)
+    boolean simulate;
+
+    protected void doExecute(FeaturesService admin) throws Exception {
+        // iterate in the provided feature
+        EnumSet<FeaturesService.Option> options = EnumSet.noneOf(FeaturesService.Option.class);
+        if (simulate) {
+            options.add(FeaturesService.Option.Simulate);
+        }
+        if (noRefresh) {
+            options.add(FeaturesService.Option.NoAutoRefreshBundles);
+        }
+        if (verbose) {
+            options.add(FeaturesService.Option.Verbose);
+        }
+        admin.uninstallFeatures(new HashSet<String>(features), options);
+    }
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/src/main/java/org/apache/karaf/features/command/completers/AllFeatureCompleter.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/command/completers/AllFeatureCompleter.java b/features/src/main/java/org/apache/karaf/features/command/completers/AllFeatureCompleter.java
new file mode 100644
index 0000000..7444b95
--- /dev/null
+++ b/features/src/main/java/org/apache/karaf/features/command/completers/AllFeatureCompleter.java
@@ -0,0 +1,33 @@
+/*
+ * 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.karaf.features.command.completers;
+
+import org.apache.karaf.features.Feature;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+
+/**
+ * {@link org.apache.karaf.shell.console.Completer} for available features.
+ */
+@Service
+public class AllFeatureCompleter extends FeatureCompleterSupport {
+
+    @Override
+    protected boolean acceptsFeature(Feature feature) {
+        return true;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/src/main/java/org/apache/karaf/features/command/completers/AvailableFeatureCompleter.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/command/completers/AvailableFeatureCompleter.java b/features/src/main/java/org/apache/karaf/features/command/completers/AvailableFeatureCompleter.java
new file mode 100644
index 0000000..79cd280
--- /dev/null
+++ b/features/src/main/java/org/apache/karaf/features/command/completers/AvailableFeatureCompleter.java
@@ -0,0 +1,33 @@
+/*
+ * 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.karaf.features.command.completers;
+
+import org.apache.karaf.features.Feature;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+
+/**
+ * {@link org.apache.karaf.shell.console.Completer} for features not installed yet.
+ */
+@Service
+public class AvailableFeatureCompleter extends FeatureCompleterSupport {
+
+    @Override
+    protected boolean acceptsFeature(Feature feature) {
+        return !featuresService.isInstalled(feature);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/src/main/java/org/apache/karaf/features/command/completers/AvailableRepoNameCompleter.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/command/completers/AvailableRepoNameCompleter.java b/features/src/main/java/org/apache/karaf/features/command/completers/AvailableRepoNameCompleter.java
new file mode 100644
index 0000000..acefe77
--- /dev/null
+++ b/features/src/main/java/org/apache/karaf/features/command/completers/AvailableRepoNameCompleter.java
@@ -0,0 +1,48 @@
+/*
+ * 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.karaf.features.command.completers;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.apache.karaf.features.FeaturesService;
+import org.apache.karaf.shell.api.action.lifecycle.Reference;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.apache.karaf.shell.api.console.CommandLine;
+import org.apache.karaf.shell.api.console.Completer;
+import org.apache.karaf.shell.api.console.Session;
+import org.apache.karaf.shell.support.completers.StringsCompleter;
+
+/**
+ * Shows the list of feature repos that can be installed with their short name
+ */
+@Service
+public class AvailableRepoNameCompleter implements Completer {
+
+    @Reference
+    private FeaturesService featuresService;
+
+    public void setFeaturesService(FeaturesService featuresService) {
+        this.featuresService = featuresService;
+    }
+
+    public int complete(Session session, CommandLine commandLine, final List<String> candidates) {
+        StringsCompleter delegate = new StringsCompleter(Arrays.asList(featuresService.getRepositoryNames()));
+        return delegate.complete(session, commandLine, candidates);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/src/main/java/org/apache/karaf/features/command/completers/FeatureCompleterSupport.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/command/completers/FeatureCompleterSupport.java b/features/src/main/java/org/apache/karaf/features/command/completers/FeatureCompleterSupport.java
new file mode 100644
index 0000000..d01e5af
--- /dev/null
+++ b/features/src/main/java/org/apache/karaf/features/command/completers/FeatureCompleterSupport.java
@@ -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.karaf.features.command.completers;
+
+import java.util.List;
+
+import org.apache.karaf.features.Feature;
+import org.apache.karaf.features.FeaturesService;
+import org.apache.karaf.shell.api.action.lifecycle.Reference;
+import org.apache.karaf.shell.api.console.CommandLine;
+import org.apache.karaf.shell.api.console.Completer;
+import org.apache.karaf.shell.api.console.Session;
+import org.apache.karaf.shell.support.completers.StringsCompleter;
+
+/**
+ * Base completer for feature commands.
+ */
+public abstract class FeatureCompleterSupport implements Completer {
+
+    /**
+     * Feature service.
+     */
+    @Reference
+    protected FeaturesService featuresService;
+
+    public void setFeaturesService(FeaturesService featuresService) {
+        this.featuresService = featuresService;
+    }
+
+    public int complete(Session session, final CommandLine commandLine, final List<String> candidates) {
+        StringsCompleter delegate = new StringsCompleter();
+        try {
+            for (Feature feature : featuresService.listFeatures()) {
+                if (acceptsFeature(feature)) {
+                    delegate.getStrings().add(feature.getName());
+                }
+            }
+        } catch (Exception e) {
+            // Ignore
+        }
+        return delegate.complete(session, commandLine, candidates);
+    }
+
+    /**
+     * Method for filtering features.
+     *
+     * @param feature The feature.
+     * @return True if feature should be available in completer.
+     */
+    protected abstract boolean acceptsFeature(Feature feature);
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/src/main/java/org/apache/karaf/features/command/completers/InstalledRepoNameCompleter.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/command/completers/InstalledRepoNameCompleter.java b/features/src/main/java/org/apache/karaf/features/command/completers/InstalledRepoNameCompleter.java
new file mode 100644
index 0000000..94e4cf7
--- /dev/null
+++ b/features/src/main/java/org/apache/karaf/features/command/completers/InstalledRepoNameCompleter.java
@@ -0,0 +1,58 @@
+/*
+ * 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.karaf.features.command.completers;
+
+import java.util.List;
+
+import org.apache.karaf.features.FeaturesService;
+import org.apache.karaf.features.Repository;
+import org.apache.karaf.shell.api.action.lifecycle.Reference;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.apache.karaf.shell.api.console.CommandLine;
+import org.apache.karaf.shell.api.console.Completer;
+import org.apache.karaf.shell.api.console.Session;
+import org.apache.karaf.shell.support.completers.StringsCompleter;
+
+/**
+ * {@link Completer} for Feature Repository URLs.
+ *
+ * Displays a list of currently installed Feature repositories.
+ *
+ */
+@Service
+public class InstalledRepoNameCompleter implements Completer {
+
+    @Reference
+    private FeaturesService featuresService;
+
+    public void setFeaturesService(FeaturesService featuresService) {
+        this.featuresService = featuresService;
+    }
+
+    public int complete(Session session, final CommandLine commandLine, final List<String> candidates) {
+        StringsCompleter delegate = new StringsCompleter();
+        try {
+            for (Repository repository : featuresService.listRepositories()) {
+                delegate.getStrings().add(repository.getName());
+            }
+        } catch (Exception e) {
+            // Ignore
+        }
+        return delegate.complete(session, commandLine, candidates);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/src/main/java/org/apache/karaf/features/command/completers/InstalledRepoUriCompleter.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/command/completers/InstalledRepoUriCompleter.java b/features/src/main/java/org/apache/karaf/features/command/completers/InstalledRepoUriCompleter.java
new file mode 100644
index 0000000..7a760c2
--- /dev/null
+++ b/features/src/main/java/org/apache/karaf/features/command/completers/InstalledRepoUriCompleter.java
@@ -0,0 +1,59 @@
+/*
+ * 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.karaf.features.command.completers;
+
+import java.util.List;
+
+import org.apache.karaf.features.FeaturesService;
+import org.apache.karaf.features.Repository;
+import org.apache.karaf.shell.api.action.lifecycle.Reference;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.apache.karaf.shell.api.console.CommandLine;
+import org.apache.karaf.shell.api.console.Completer;
+import org.apache.karaf.shell.api.console.Session;
+import org.apache.karaf.shell.support.completers.StringsCompleter;
+
+/**
+ * {@link Completer} for Feature Repository URLs.
+ *
+ * Displays a list of currently installed Feature repositories.
+ *
+ */
+
+@Service
+public class InstalledRepoUriCompleter implements Completer {
+
+    @Reference
+    private FeaturesService featuresService;
+
+    public void setFeaturesService(FeaturesService featuresService) {
+        this.featuresService = featuresService;
+    }
+
+    public int complete(Session session, final CommandLine commandLine, final List<String> candidates) {
+        StringsCompleter delegate = new StringsCompleter();
+        try {
+            for (Repository repository : featuresService.listRepositories()) {
+                delegate.getStrings().add(repository.getURI().toString());
+            }
+        } catch (Exception e) {
+            // Ignore
+        }
+        return delegate.complete(session, commandLine, candidates);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/src/main/java/org/apache/karaf/features/command/completers/RequiredFeatureCompleter.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/command/completers/RequiredFeatureCompleter.java b/features/src/main/java/org/apache/karaf/features/command/completers/RequiredFeatureCompleter.java
new file mode 100644
index 0000000..a51f75f
--- /dev/null
+++ b/features/src/main/java/org/apache/karaf/features/command/completers/RequiredFeatureCompleter.java
@@ -0,0 +1,33 @@
+/*
+ * 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.karaf.features.command.completers;
+
+import org.apache.karaf.features.Feature;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+
+/**
+ * {@link org.apache.karaf.shell.console.Completer} for installed features.
+ */
+@Service
+public class RequiredFeatureCompleter extends FeatureCompleterSupport {
+
+    @Override
+    protected boolean acceptsFeature(Feature feature) {
+        return featuresService.isRequired(feature);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/src/main/java/org/apache/karaf/features/internal/deployment/DeploymentBuilder.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/deployment/DeploymentBuilder.java b/features/src/main/java/org/apache/karaf/features/internal/deployment/DeploymentBuilder.java
new file mode 100644
index 0000000..00a91c4
--- /dev/null
+++ b/features/src/main/java/org/apache/karaf/features/internal/deployment/DeploymentBuilder.java
@@ -0,0 +1,334 @@
+/*
+ * 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.karaf.features.internal.deployment;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.jar.Attributes;
+import java.util.jar.Manifest;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipInputStream;
+
+import org.apache.felix.resolver.ResolverImpl;
+import org.apache.felix.utils.version.VersionRange;
+import org.apache.felix.utils.version.VersionTable;
+import org.apache.karaf.features.BundleInfo;
+import org.apache.karaf.features.Conditional;
+import org.apache.karaf.features.Dependency;
+import org.apache.karaf.features.Feature;
+import org.apache.karaf.features.Repository;
+import org.apache.karaf.features.internal.repository.AggregateRepository;
+import org.apache.karaf.features.internal.repository.StaticRepository;
+import org.apache.karaf.features.internal.resolver.FeatureNamespace;
+import org.apache.karaf.features.internal.resolver.FeatureResource;
+import org.apache.karaf.features.internal.resolver.RequirementImpl;
+import org.apache.karaf.features.internal.resolver.ResolveContextImpl;
+import org.apache.karaf.features.internal.resolver.ResourceBuilder;
+import org.apache.karaf.features.internal.resolver.ResourceImpl;
+import org.apache.karaf.features.internal.resolver.Slf4jResolverLog;
+import org.apache.karaf.features.internal.service.Overrides;
+import org.apache.karaf.features.internal.util.Macro;
+import org.apache.karaf.features.internal.util.MultiException;
+import org.osgi.framework.BundleException;
+import org.osgi.framework.Version;
+import org.osgi.framework.namespace.IdentityNamespace;
+import org.osgi.resource.Capability;
+import org.osgi.resource.Requirement;
+import org.osgi.resource.Resource;
+import org.osgi.resource.Wire;
+import org.osgi.service.resolver.ResolutionException;
+import org.osgi.service.resolver.ResolveContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ */
+public class DeploymentBuilder {
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(DeploymentBuilder.class);
+
+    public static final String REQ_PROTOCOL = "req:";
+
+    private final Collection<Repository> repositories;
+
+    private final List<org.osgi.service.repository.Repository> resourceRepos;
+
+    String featureRange = "${range;[====,====]}";
+
+    Downloader downloader;
+    ResourceImpl requirements;
+    Map<String, Resource> resources;
+    Set<Resource> optionals;
+    Map<String, StreamProvider> providers;
+
+    Set<Feature> featuresToRegister = new HashSet<Feature>();
+
+    public DeploymentBuilder(Downloader downloader,
+                             Collection<Repository> repositories) {
+        this.downloader = downloader;
+        this.repositories = repositories;
+        this.resourceRepos = new ArrayList<org.osgi.service.repository.Repository>();
+    }
+
+    public void addResourceRepository(org.osgi.service.repository.Repository repository) {
+        resourceRepos.add(repository);
+    }
+
+    public Map<String, StreamProvider> getProviders() {
+        return providers;
+    }
+
+    public void setFeatureRange(String featureRange) {
+        this.featureRange = featureRange;
+    }
+
+    public Map<String, Resource> download(
+                         Set<String> features,
+                         Set<String> bundles,
+                         Set<String> reqs,
+                         Set<String> overrides,
+                         Set<String> optionals)
+                throws IOException, MultiException, InterruptedException, ResolutionException, BundleException {
+        this.resources = new ConcurrentHashMap<String, Resource>();
+        this.optionals = new HashSet<Resource>();
+        this.providers = new ConcurrentHashMap<String, StreamProvider>();
+        this.requirements = new ResourceImpl("dummy", "dummy", Version.emptyVersion);
+        // First, gather all bundle resources
+        for (String feature : features) {
+            registerMatchingFeatures(feature);
+        }
+        for (String bundle : bundles) {
+            downloadAndBuildResource(bundle);
+        }
+        for (String req : reqs) {
+            buildRequirement(req);
+        }
+        for (String override : overrides) {
+            // TODO: ignore download failures for overrides
+            downloadAndBuildResource(Overrides.extractUrl(override));
+        }
+        for (String optional : optionals) {
+            downloadAndBuildResource(optional);
+        }
+        // Wait for all resources to be created
+        downloader.await();
+        // Do override replacement
+        Overrides.override(resources, overrides);
+        // Build features resources
+        for (Feature feature : featuresToRegister) {
+            Resource resource = FeatureResource.build(feature, featureRange, resources);
+            resources.put("feature:" + feature.getName() + "/" + feature.getVersion(), resource);
+            for (Conditional cond : feature.getConditional()) {
+                this.optionals.add(FeatureResource.build(feature, cond, featureRange, resources));
+            }
+        }
+        // Build requirements
+        for (String feature : features) {
+            requireFeature(feature);
+        }
+        for (String bundle : bundles) {
+            requireResource(bundle);
+        }
+        for (String req : reqs) {
+            requireResource(REQ_PROTOCOL + req);
+        }
+        return resources;
+    }
+
+    public Map<Resource, List<Wire>> resolve(List<Resource> systemBundles,
+                                        boolean resolveOptionalImports) throws ResolutionException {
+        // Resolve
+        for (int i = 0; i < systemBundles.size(); i++) {
+            resources.put("system-bundle-" + i, systemBundles.get(i));
+        }
+
+        List<org.osgi.service.repository.Repository> repos = new ArrayList<org.osgi.service.repository.Repository>();
+        repos.add(new StaticRepository(resources.values()));
+        repos.addAll(resourceRepos);
+
+        ResolverImpl resolver = new ResolverImpl(new Slf4jResolverLog(LOGGER));
+        ResolveContext context = new ResolveContextImpl(
+                Collections.<Resource>singleton(requirements),
+                this.optionals,
+                new AggregateRepository(repos),
+                resolveOptionalImports);
+
+        return resolver.resolve(context);
+    }
+
+    public void requireFeature(String feature) throws IOException {
+        // Find name and version range
+        String[] split = feature.split("/");
+        String name = split[0].trim();
+        String version = (split.length > 1) ? split[1].trim() : null;
+        if (version != null && !version.equals("0.0.0") && !version.startsWith("[") && !version.startsWith("(")) {
+            version = Macro.transform(featureRange, version);
+        }
+        VersionRange range = version != null ? new VersionRange(version) : VersionRange.ANY_VERSION;
+        // Add requirement
+        Map<String, Object> attrs = new HashMap<String, Object>();
+        attrs.put(IdentityNamespace.IDENTITY_NAMESPACE, name);
+        attrs.put(IdentityNamespace.CAPABILITY_TYPE_ATTRIBUTE, FeatureNamespace.TYPE_FEATURE);
+        attrs.put(IdentityNamespace.CAPABILITY_VERSION_ATTRIBUTE, range);
+        requirements.addRequirement(
+                new RequirementImpl(requirements, IdentityNamespace.IDENTITY_NAMESPACE,
+                        Collections.<String, String>emptyMap(), attrs)
+        );
+    }
+
+    public void requireResource(String location) {
+        Resource res = resources.get(location);
+        if (res == null) {
+            throw new IllegalStateException("Could not find resource for " + location);
+        }
+        List<Capability> caps = res.getCapabilities(IdentityNamespace.IDENTITY_NAMESPACE);
+        if (caps.size() != 1) {
+            throw new IllegalStateException("Resource does not have a single " + IdentityNamespace.IDENTITY_NAMESPACE + " capability");
+        }
+        Capability cap = caps.get(0);
+        // Add requirement
+        Map<String, Object> attrs = new HashMap<String, Object>();
+        attrs.put(IdentityNamespace.IDENTITY_NAMESPACE, cap.getAttributes().get(IdentityNamespace.IDENTITY_NAMESPACE));
+        attrs.put(IdentityNamespace.CAPABILITY_TYPE_ATTRIBUTE, cap.getAttributes().get(IdentityNamespace.CAPABILITY_TYPE_ATTRIBUTE));
+        attrs.put(IdentityNamespace.CAPABILITY_VERSION_ATTRIBUTE, new VersionRange((Version) cap.getAttributes().get(IdentityNamespace.CAPABILITY_VERSION_ATTRIBUTE), true));
+        requirements.addRequirement(
+                new RequirementImpl(requirements, IdentityNamespace.IDENTITY_NAMESPACE,
+                        Collections.<String, String>emptyMap(), attrs));
+
+    }
+
+    public void registerMatchingFeatures(String feature) throws IOException {
+        // Find name and version range
+        String[] split = feature.split("/");
+        String name = split[0].trim();
+        String version = (split.length > 1)
+                ? split[1].trim() : Version.emptyVersion.toString();
+        // Register matching features
+        registerMatchingFeatures(name, new VersionRange(version));
+    }
+
+    public void registerMatchingFeatures(String name, String version) throws IOException {
+        if (version != null && !version.equals("0.0.0") && !version.startsWith("[") && !version.startsWith("(")) {
+            version = Macro.transform(featureRange, version);
+        }
+        registerMatchingFeatures(name, version != null ? new VersionRange(version) : VersionRange.ANY_VERSION);
+    }
+
+    public void registerMatchingFeatures(String name, VersionRange range) throws IOException {
+        for (Repository repo : repositories) {
+            Feature[] features;
+            try {
+                features = repo.getFeatures();
+            } catch (Exception e) {
+                // This should not happen as the repository has been loaded already
+                throw new IllegalStateException(e);
+            }
+            for (Feature f : features) {
+                if (name.equals(f.getName())) {
+                    Version v = VersionTable.getVersion(f.getVersion());
+                    if (range.contains(v)) {
+                        featuresToRegister.add(f);
+                        for (Dependency dep : f.getDependencies()) {
+                            registerMatchingFeatures(dep.getName(), dep.getVersion());
+                        }
+                        for (BundleInfo bundle : f.getBundles()) {
+                            downloadAndBuildResource(bundle.getLocation());
+                        }
+                        for (Conditional cond : f.getConditional()) {
+                            Feature c = cond.asFeature(f.getName(), f.getVersion());
+                            featuresToRegister.add(c);
+                            for (BundleInfo bundle : c.getBundles()) {
+                                downloadAndBuildResource(bundle.getLocation());
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    public void buildRequirement(String requirement) {
+        try {
+            String location = REQ_PROTOCOL + requirement;
+            ResourceImpl resource = new ResourceImpl(location, "dummy", Version.emptyVersion);
+            for (Requirement req : ResourceBuilder.parseRequirement(resource, requirement)) {
+                resource.addRequirement(req);
+            }
+            resources.put(location, resource);
+        } catch (BundleException e) {
+            throw new IllegalArgumentException("Error parsing requirement: " + requirement, e);
+        }
+    }
+
+    public void downloadAndBuildResource(final String location) throws IOException {
+        if (!resources.containsKey(location)) {
+            downloader.download(location, new Downloader.DownloadCallback() {
+                @Override
+                public void downloaded(StreamProvider provider) throws Exception {
+                    manageResource(location, provider);
+                }
+            });
+        }
+    }
+
+    private void manageResource(String location, StreamProvider provider) throws Exception {
+        if (!resources.containsKey(location)) {
+            Attributes attributes = getAttributes(location, provider);
+            Resource resource = createResource(location, attributes);
+            resources.put(location, resource);
+            providers.put(location, provider);
+        }
+    }
+
+    private Resource createResource(String uri, Attributes attributes) throws Exception {
+        Map<String, String> headers = new HashMap<String, String>();
+        for (Map.Entry attr : attributes.entrySet()) {
+            headers.put(attr.getKey().toString(), attr.getValue().toString());
+        }
+        try {
+            return ResourceBuilder.build(uri, headers);
+        } catch (BundleException e) {
+            throw new Exception("Unable to create resource for bundle " + uri, e);
+        }
+    }
+
+    protected Attributes getAttributes(String uri, StreamProvider provider) throws Exception {
+        InputStream is = provider.open();
+        try {
+            ZipInputStream zis = new ZipInputStream(is);
+            ZipEntry entry;
+            while ( (entry = zis.getNextEntry()) != null ) {
+                if ("META-INF/MANIFEST.MF".equals(entry.getName())) {
+                    return new Manifest(zis).getMainAttributes();
+                }
+            }
+        } finally {
+            is.close();
+        }
+        throw new IllegalArgumentException("Resource " + uri + " does not contain a manifest");
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/src/main/java/org/apache/karaf/features/internal/deployment/Downloader.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/deployment/Downloader.java b/features/src/main/java/org/apache/karaf/features/internal/deployment/Downloader.java
new file mode 100644
index 0000000..2d5dd98
--- /dev/null
+++ b/features/src/main/java/org/apache/karaf/features/internal/deployment/Downloader.java
@@ -0,0 +1,35 @@
+/*
+ * 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.karaf.features.internal.deployment;
+
+import java.net.MalformedURLException;
+
+import org.apache.karaf.features.internal.util.MultiException;
+
+public interface Downloader {
+
+    void await() throws InterruptedException, MultiException;
+
+    void download(String location, DownloadCallback downloadCallback) throws MalformedURLException;
+
+    interface DownloadCallback {
+
+        void downloaded(StreamProvider provider) throws Exception;
+
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/src/main/java/org/apache/karaf/features/internal/deployment/StreamProvider.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/deployment/StreamProvider.java b/features/src/main/java/org/apache/karaf/features/internal/deployment/StreamProvider.java
new file mode 100644
index 0000000..60a3dfc
--- /dev/null
+++ b/features/src/main/java/org/apache/karaf/features/internal/deployment/StreamProvider.java
@@ -0,0 +1,26 @@
+/*
+ * 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.karaf.features.internal.deployment;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+public interface StreamProvider {
+
+    InputStream open() throws IOException;
+
+}


[21/59] [abbrv] git commit: [KARAF-2852] Merge bundle/command into bundle/core

Posted by gn...@apache.org.
[KARAF-2852] Merge bundle/command into bundle/core


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

Branch: refs/heads/master
Commit: d01809398ab4943c9d1944da3bd6e68a37268ba1
Parents: 999f497
Author: Guillaume Nodet <gn...@gmail.com>
Authored: Wed Apr 9 21:59:03 2014 +0200
Committer: Guillaume Nodet <gn...@gmail.com>
Committed: Thu Apr 10 15:59:24 2014 +0200

----------------------------------------------------------------------
 .../standard/src/main/feature/feature.xml       |   1 -
 bundle/command/NOTICE                           |  71 ----
 bundle/command/pom.xml                          | 113 -------
 .../karaf/bundle/command/BundleCommand.java     |  69 ----
 .../command/BundleCommandWithConfirmation.java  |  37 ---
 .../karaf/bundle/command/BundlesCommand.java    |  79 -----
 .../command/BundlesCommandWithConfirmation.java |  62 ----
 .../karaf/bundle/command/Capabilities.java      | 239 -------------
 .../apache/karaf/bundle/command/Classes.java    |  63 ----
 .../org/apache/karaf/bundle/command/Diag.java   |  51 ---
 .../karaf/bundle/command/DynamicImport.java     |  46 ---
 .../apache/karaf/bundle/command/FindClass.java  |  68 ----
 .../apache/karaf/bundle/command/Headers.java    | 333 -------------------
 .../org/apache/karaf/bundle/command/Info.java   |  79 -----
 .../apache/karaf/bundle/command/Install.java    |  81 -----
 .../bundle/command/ListBundleServices.java      | 116 -------
 .../karaf/bundle/command/ListBundles.java       | 176 ----------
 .../apache/karaf/bundle/command/LoadTest.java   | 192 -----------
 .../apache/karaf/bundle/command/Refresh.java    |  43 ---
 .../karaf/bundle/command/Requirements.java      | 177 ----------
 .../apache/karaf/bundle/command/Resolve.java    |  39 ---
 .../apache/karaf/bundle/command/Restart.java    |  62 ----
 .../karaf/bundle/command/ShowBundleTree.java    | 245 --------------
 .../org/apache/karaf/bundle/command/Start.java  |  32 --
 .../apache/karaf/bundle/command/StartLevel.java |  64 ----
 .../org/apache/karaf/bundle/command/Stop.java   |  44 ---
 .../apache/karaf/bundle/command/Uninstall.java  |  36 --
 .../org/apache/karaf/bundle/command/Update.java |  48 ---
 .../org/apache/karaf/bundle/command/Watch.java  | 128 -------
 .../karaf/bundle/command/bundletree/Node.java   | 159 ---------
 .../karaf/bundle/command/bundletree/Tree.java   | 100 ------
 .../wikidoc/AnsiPrintingWikiVisitor.java        |  58 ----
 .../bundle/command/wikidoc/WikiParser.java      |  86 -----
 .../bundle/command/wikidoc/WikiVisitor.java     |  29 --
 .../src/main/resources/OSGI-INF/bundle.info     |  32 --
 .../karaf/bundle/command/ListServicesTest.java  |  61 ----
 .../karaf/bundle/command/TestBundleFactory.java | 104 ------
 .../bundle/command/bundletree/TreeTest.java     | 135 --------
 .../bundle/command/wikidoc/WikiParserTest.java  |  94 ------
 bundle/core/pom.xml                             |   8 +
 .../karaf/bundle/command/BundleCommand.java     |  69 ++++
 .../command/BundleCommandWithConfirmation.java  |  37 +++
 .../karaf/bundle/command/BundlesCommand.java    |  79 +++++
 .../command/BundlesCommandWithConfirmation.java |  62 ++++
 .../karaf/bundle/command/Capabilities.java      | 239 +++++++++++++
 .../apache/karaf/bundle/command/Classes.java    |  63 ++++
 .../org/apache/karaf/bundle/command/Diag.java   |  51 +++
 .../karaf/bundle/command/DynamicImport.java     |  46 +++
 .../apache/karaf/bundle/command/FindClass.java  |  68 ++++
 .../apache/karaf/bundle/command/Headers.java    | 333 +++++++++++++++++++
 .../org/apache/karaf/bundle/command/Info.java   |  79 +++++
 .../apache/karaf/bundle/command/Install.java    |  81 +++++
 .../bundle/command/ListBundleServices.java      | 116 +++++++
 .../karaf/bundle/command/ListBundles.java       | 176 ++++++++++
 .../apache/karaf/bundle/command/LoadTest.java   | 192 +++++++++++
 .../apache/karaf/bundle/command/Refresh.java    |  43 +++
 .../karaf/bundle/command/Requirements.java      | 177 ++++++++++
 .../apache/karaf/bundle/command/Resolve.java    |  39 +++
 .../apache/karaf/bundle/command/Restart.java    |  62 ++++
 .../karaf/bundle/command/ShowBundleTree.java    | 245 ++++++++++++++
 .../org/apache/karaf/bundle/command/Start.java  |  32 ++
 .../apache/karaf/bundle/command/StartLevel.java |  64 ++++
 .../org/apache/karaf/bundle/command/Stop.java   |  44 +++
 .../apache/karaf/bundle/command/Uninstall.java  |  36 ++
 .../org/apache/karaf/bundle/command/Update.java |  48 +++
 .../org/apache/karaf/bundle/command/Watch.java  | 128 +++++++
 .../karaf/bundle/command/bundletree/Node.java   | 159 +++++++++
 .../karaf/bundle/command/bundletree/Tree.java   | 100 ++++++
 .../wikidoc/AnsiPrintingWikiVisitor.java        |  58 ++++
 .../bundle/command/wikidoc/WikiParser.java      |  86 +++++
 .../bundle/command/wikidoc/WikiVisitor.java     |  29 ++
 .../karaf/bundle/command/ListServicesTest.java  |  61 ++++
 .../karaf/bundle/command/TestBundleFactory.java | 104 ++++++
 .../bundle/command/bundletree/TreeTest.java     | 135 ++++++++
 .../bundle/command/wikidoc/WikiParserTest.java  |  94 ++++++
 bundle/pom.xml                                  |   1 -
 76 files changed, 3443 insertions(+), 3653 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/karaf/blob/d0180939/assemblies/features/standard/src/main/feature/feature.xml
----------------------------------------------------------------------
diff --git a/assemblies/features/standard/src/main/feature/feature.xml b/assemblies/features/standard/src/main/feature/feature.xml
index fde555c..2bc3ec4 100644
--- a/assemblies/features/standard/src/main/feature/feature.xml
+++ b/assemblies/features/standard/src/main/feature/feature.xml
@@ -121,7 +121,6 @@
 
     <feature name="bundle" description="Provide Bundle support" version="${project.version}">
         <bundle start-level="30" start="true">mvn:org.apache.karaf.bundle/org.apache.karaf.bundle.core/${project.version}</bundle>
-        <bundle start-level="30" start="true">mvn:org.apache.karaf.bundle/org.apache.karaf.bundle.command/${project.version}</bundle>
     </feature>
 
     <feature name="config" description="Provide OSGi ConfigAdmin support" version="${project.version}">

http://git-wip-us.apache.org/repos/asf/karaf/blob/d0180939/bundle/command/NOTICE
----------------------------------------------------------------------
diff --git a/bundle/command/NOTICE b/bundle/command/NOTICE
deleted file mode 100644
index b70f1f9..0000000
--- a/bundle/command/NOTICE
+++ /dev/null
@@ -1,71 +0,0 @@
-Apache Karaf
-Copyright 2010-2014 The Apache Software Foundation
-
-
-I. Included Software
-
-This product includes software developed at
-The Apache Software Foundation (http://www.apache.org/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-The OSGi Alliance (http://www.osgi.org/).
-Copyright (c) OSGi Alliance (2000, 2010).
-Licensed under the Apache License 2.0.
-
-This product includes software developed at
-OW2 (http://www.ow2.org/).
-Licensed under the BSD License.
-
-This product includes software developed at
-OPS4J (http://www.ops4j.org/).
-Licensed under the Apache License 2.0.
-
-This product includes software developed at
-Eclipse Foundation (http://www.eclipse.org/).
-Licensed under the EPL.
-
-This product includes software written by
-Antony Lesuisse.
-Licensed under Public Domain.
-
-
-II. Used Software
-
-This product uses software developed at
-FUSE Source (http://www.fusesource.org/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-AOP Alliance (http://aopalliance.sourceforge.net/).
-Licensed under the Public Domain.
-
-This product uses software developed at
-Tanuki Software (http://www.tanukisoftware.com/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-Jasypt (http://jasypt.sourceforge.net/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-JLine (http://jline.sourceforge.net).
-Licensed under the BSD License.
-
-This product uses software developed at
-SLF4J (http://www.slf4j.org/).
-Licensed under the MIT License.
-
-This product uses software developed at
-SpringSource (http://www.springsource.org/).
-Licensed under the Apache License 2.0.
-
-This product includes software from http://www.json.org.
-Copyright (c) 2002 JSON.org
-
-
-III. License Summary
-- Apache License 2.0
-- BSD License
-- EPL License
-- MIT License

http://git-wip-us.apache.org/repos/asf/karaf/blob/d0180939/bundle/command/pom.xml
----------------------------------------------------------------------
diff --git a/bundle/command/pom.xml b/bundle/command/pom.xml
deleted file mode 100644
index d856d04..0000000
--- a/bundle/command/pom.xml
+++ /dev/null
@@ -1,113 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-
-    <!--
-
-        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.
-    -->
-
-    <modelVersion>4.0.0</modelVersion>
-
-    <parent>
-        <groupId>org.apache.karaf.bundle</groupId>
-        <artifactId>bundle</artifactId>
-        <version>4.0.0-SNAPSHOT</version>
-        <relativePath>../pom.xml</relativePath>
-    </parent>
-
-    <artifactId>org.apache.karaf.bundle.command</artifactId>
-    <packaging>bundle</packaging>
-    <name>Apache Karaf :: Bundle :: Commands</name>
-    <description>Provides shell commands to manipulate OSGi bundles.</description>
-
-    <properties>
-        <appendedResourcesDirectory>${basedir}/../../etc/appended-resources</appendedResourcesDirectory>
-    </properties>
-
-    <dependencies>
-        <dependency>
-            <groupId>org.apache.karaf.shell</groupId>
-            <artifactId>org.apache.karaf.shell.core</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.karaf.bundle</groupId>
-            <artifactId>org.apache.karaf.bundle.core</artifactId>
-        </dependency>
-
-        <dependency>
-            <groupId>org.apache.felix</groupId>
-            <artifactId>org.apache.felix.gogo.runtime</artifactId>
-            <scope>provided</scope>
-        </dependency>
-
-		<dependency>
-            <groupId>org.osgi</groupId>
-            <artifactId>org.osgi.core</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.slf4j</groupId>
-            <artifactId>slf4j-api</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.slf4j</groupId>
-            <artifactId>slf4j-jdk14</artifactId>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.felix</groupId>
-            <artifactId>org.apache.felix.utils</artifactId>
-            <scope>provided</scope>
-        </dependency>
-    </dependencies>
-
-    <build>
-        <resources>
-            <resource>
-                <directory>${project.basedir}/src/main/resources</directory>
-                <includes>
-                    <include>**/*</include>
-                </includes>
-            </resource>
-            <resource>
-                <directory>${project.basedir}/src/main/resources</directory>
-                <filtering>true</filtering>
-                <includes>
-                    <include>**/*.info</include>
-                </includes>
-            </resource>
-        </resources>
-        <plugins>
-            <plugin>
-                <groupId>org.apache.felix</groupId>
-                <artifactId>maven-bundle-plugin</artifactId>
-                <configuration>
-                    <instructions>
-                        <Export-Package>!*</Export-Package>
-                        <Private-Package>
-                            org.apache.karaf.bundle.command*,
-                            org.apache.felix.utils.version;-split-package:=merge-first,
-                            org.apache.felix.utils.manifest;-split-package:=merge-first
-                        </Private-Package>
-                        <Karaf-Commands>org.apache.karaf.bundle.command.*</Karaf-Commands>
-                    </instructions>
-                </configuration>
-            </plugin>
-        </plugins>
-    </build>
-
-</project>

http://git-wip-us.apache.org/repos/asf/karaf/blob/d0180939/bundle/command/src/main/java/org/apache/karaf/bundle/command/BundleCommand.java
----------------------------------------------------------------------
diff --git a/bundle/command/src/main/java/org/apache/karaf/bundle/command/BundleCommand.java b/bundle/command/src/main/java/org/apache/karaf/bundle/command/BundleCommand.java
deleted file mode 100644
index dce0ca8..0000000
--- a/bundle/command/src/main/java/org/apache/karaf/bundle/command/BundleCommand.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * 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.karaf.bundle.command;
-
-import org.apache.karaf.bundle.core.BundleService;
-import org.apache.karaf.shell.api.action.Action;
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.lifecycle.Reference;
-import org.apache.karaf.shell.support.ShellUtil;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.BundleContext;
-
-/**
- * Unique bundle command.
- */
-public abstract class BundleCommand implements Action {
-
-    @Argument(index = 0, name = "id", description = "The bundle ID or name or name/version", required = true, multiValued = false)
-    String id;
-
-    boolean defaultAllBundles = true;
-
-    @Reference
-    BundleService bundleService;
-
-    @Reference
-    BundleContext bundleContext;
-
-    public BundleCommand(boolean defaultAllBundles) {
-        this.defaultAllBundles = defaultAllBundles;
-    }
-
-    public Object execute() throws Exception {
-        return doExecute(true);
-    }
-
-    protected Object doExecute(boolean force) throws Exception {
-        Bundle bundle = bundleService.getBundle(id, defaultAllBundles);
-        if (bundle != null) {
-            if (force || !ShellUtil.isASystemBundle(bundleContext, bundle)) {
-                doExecute(bundle);
-            } else {
-                System.err.println("Access to system bundle " + id + " is discouraged. You may override with -f");
-            }
-        }
-        return null;
-    }
-
-    protected abstract void doExecute(Bundle bundle) throws Exception;
-
-    public void setBundleService(BundleService bundleService) {
-        this.bundleService = bundleService;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d0180939/bundle/command/src/main/java/org/apache/karaf/bundle/command/BundleCommandWithConfirmation.java
----------------------------------------------------------------------
diff --git a/bundle/command/src/main/java/org/apache/karaf/bundle/command/BundleCommandWithConfirmation.java b/bundle/command/src/main/java/org/apache/karaf/bundle/command/BundleCommandWithConfirmation.java
deleted file mode 100644
index c07a357..0000000
--- a/bundle/command/src/main/java/org/apache/karaf/bundle/command/BundleCommandWithConfirmation.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * 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.karaf.bundle.command;
-
-import org.apache.karaf.shell.api.action.Option;
-
-/**
- * Unique bundle command with confirmation while accessing system bundle.
- */
-public abstract class BundleCommandWithConfirmation extends BundleCommand {
-
-    @Option(name = "--force", aliases = {"-f"}, description = "Forces the command to execute", required = false, multiValued = false)
-    boolean force;
-
-    public BundleCommandWithConfirmation() {
-        super(true);
-    }
-
-    public Object execute() throws Exception {
-        return doExecute(force);
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d0180939/bundle/command/src/main/java/org/apache/karaf/bundle/command/BundlesCommand.java
----------------------------------------------------------------------
diff --git a/bundle/command/src/main/java/org/apache/karaf/bundle/command/BundlesCommand.java b/bundle/command/src/main/java/org/apache/karaf/bundle/command/BundlesCommand.java
deleted file mode 100644
index ff4dd53..0000000
--- a/bundle/command/src/main/java/org/apache/karaf/bundle/command/BundlesCommand.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * 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.karaf.bundle.command;
-
-import java.util.List;
-
-import org.apache.karaf.bundle.core.BundleService;
-import org.apache.karaf.shell.api.action.Action;
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.lifecycle.Reference;
-import org.apache.karaf.shell.support.ShellUtil;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.BundleContext;
-
-public abstract class BundlesCommand implements Action {
-
-    @Argument(index = 0, name = "ids", description = "The list of bundle (identified by IDs or name or name/version) separated by whitespaces", required = false, multiValued = true)
-    List<String> ids;
-    
-    boolean defaultAllBundles = true;
-
-    @Reference
-    BundleContext bundleContext;
-
-    @Reference
-    BundleService bundleService;
-    
-    public BundlesCommand(boolean defaultAllBundles) {
-        this.defaultAllBundles = defaultAllBundles;
-    }
-
-    public void setBundleContext(BundleContext bundleContext) {
-        this.bundleContext = bundleContext;
-    }
-
-    @Override
-    public Object execute() throws Exception {
-        doExecute(true);
-        return null;
-    }
-
-    protected Object doExecute(boolean force) throws Exception {
-        List<Bundle> bundles = bundleService.selectBundles(ids, defaultAllBundles);
-        if (!force) {
-            assertNoSystemBundles(bundles);
-        }
-        doExecute(bundles);
-        return null;
-    }
-    
-    private void assertNoSystemBundles(List<Bundle> bundles) {
-        for (Bundle bundle : bundles) {
-            if (ShellUtil.isASystemBundle(bundleContext, bundle)) {
-                throw new RuntimeException("Access to system bundle " + bundle.getBundleId() + " denied. You can override with -f");
-            }
-        }
-    }
-      
-    protected abstract void doExecute(List<Bundle> bundles) throws Exception;
-
-    public void setBundleService(BundleService bundleService) {
-        this.bundleService = bundleService;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d0180939/bundle/command/src/main/java/org/apache/karaf/bundle/command/BundlesCommandWithConfirmation.java
----------------------------------------------------------------------
diff --git a/bundle/command/src/main/java/org/apache/karaf/bundle/command/BundlesCommandWithConfirmation.java b/bundle/command/src/main/java/org/apache/karaf/bundle/command/BundlesCommandWithConfirmation.java
deleted file mode 100644
index 271fc42..0000000
--- a/bundle/command/src/main/java/org/apache/karaf/bundle/command/BundlesCommandWithConfirmation.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * 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.karaf.bundle.command;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import org.apache.karaf.shell.api.action.Option;
-import org.apache.karaf.shell.support.MultiException;
-import org.osgi.framework.Bundle;
-
-/**
- * Command related to bundles requiring read-write access to the bundle (including system bundle).
- */
-public abstract class BundlesCommandWithConfirmation extends BundlesCommand {
-
-    @Option(name = "--force", aliases = {"-f"}, description = "Forces the command to execute", required = false, multiValued = false)
-    boolean force;
-    
-    protected String errorMessage = "Unable to execute command on bundle ";
-    
-    public BundlesCommandWithConfirmation() {
-        super(false);
-    }
-
-    protected Object doExecute() throws Exception {
-        doExecute(force);
-        return null;
-    }
-
-    protected void doExecute(List<Bundle> bundles) throws Exception {
-        if (bundles.isEmpty()) {
-            System.err.println("No bundles specified.");
-            return;
-        }
-        List<Exception> exceptions = new ArrayList<Exception>();
-        for (Bundle bundle : bundles) {
-            try {
-                executeOnBundle(bundle);
-            } catch (Exception e) {
-                exceptions.add(new Exception(errorMessage + bundle.getBundleId() + ": " + e.getMessage(), e));
-            }
-        }
-        MultiException.throwIf("Error executing command on bundles", exceptions);
-    }
-    
-    protected abstract void executeOnBundle(Bundle bundle) throws Exception;
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d0180939/bundle/command/src/main/java/org/apache/karaf/bundle/command/Capabilities.java
----------------------------------------------------------------------
diff --git a/bundle/command/src/main/java/org/apache/karaf/bundle/command/Capabilities.java b/bundle/command/src/main/java/org/apache/karaf/bundle/command/Capabilities.java
deleted file mode 100644
index de83a1d..0000000
--- a/bundle/command/src/main/java/org/apache/karaf/bundle/command/Capabilities.java
+++ /dev/null
@@ -1,239 +0,0 @@
-/*
- * 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.karaf.bundle.command;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.regex.Pattern;
-
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Option;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.apache.karaf.shell.support.ShellUtil;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.Constants;
-import org.osgi.framework.ServiceReference;
-import org.osgi.framework.wiring.BundleCapability;
-import org.osgi.framework.wiring.BundleWire;
-import org.osgi.framework.wiring.BundleWiring;
-
-@Command(scope = "bundle", name = "capabilities", description = "Displays OSGi capabilities of a given bundles.")
-@Service
-public class Capabilities extends BundlesCommand {
-    public static final String NONSTANDARD_SERVICE_NAMESPACE = "service";
-
-    private static final String EMPTY_MESSAGE = "[EMPTY]";
-    private static final String UNUSED_MESSAGE = "[UNUSED]";
-
-    @Option(name = "--namespace")
-    String namespace = "*";
-
-    public Capabilities() {
-        super(true);
-    }
-    
-    @Override
-    protected void doExecute(List<Bundle> bundles) throws Exception {
-        boolean separatorNeeded = false;
-        Pattern ns = Pattern.compile(namespace.replaceAll("\\.", "\\\\.").replaceAll("\\*", ".*"));
-        for (Bundle b : bundles)
-        {
-            if (separatorNeeded)
-            {
-                System.out.println("");
-            }
-
-            // Print out any matching generic capabilities.
-            BundleWiring wiring = b.adapt(BundleWiring.class);
-            if (wiring != null)
-            {
-                String title = b + " provides:";
-                System.out.println(title);
-                System.out.println(ShellUtil.getUnderlineString(title));
-
-                // Print generic capabilities for matching namespaces.
-                boolean matches = printMatchingCapabilities(wiring, ns);
-
-                // Handle service capabilities separately, since they aren't part
-                // of the generic model in OSGi.
-                if (matchNamespace(ns, NONSTANDARD_SERVICE_NAMESPACE))
-                {
-                    matches |= printServiceCapabilities(b);
-                }
-
-                // If there were no capabilities for the specified namespace,
-                // then say so.
-                if (!matches)
-                {
-                    System.out.println(namespace + " " + EMPTY_MESSAGE);
-                }
-            }
-            else
-            {
-                System.out.println("Bundle " + b.getBundleId() + " is not resolved.");
-            }
-            separatorNeeded = true;
-        }
-    }
-
-    private static boolean printMatchingCapabilities(BundleWiring wiring, Pattern namespace)
-    {
-        List<BundleWire> wires = wiring.getProvidedWires(null);
-        Map<BundleCapability, List<BundleWire>> aggregateCaps =
-            aggregateCapabilities(namespace, wires);
-        List<BundleCapability> allCaps = wiring.getCapabilities(null);
-        boolean matches = false;
-        for (BundleCapability cap : allCaps)
-        {
-            if (matchNamespace(namespace, cap.getNamespace()))
-            {
-                matches = true;
-                List<BundleWire> dependents = aggregateCaps.get(cap);
-                Object keyAttr =
-                    cap.getAttributes().get(cap.getNamespace());
-                if (dependents != null)
-                {
-                    String msg;
-                    if (keyAttr != null)
-                    {
-                        msg = cap.getNamespace()
-                            + "; "
-                            + keyAttr
-                            + " "
-                            + getVersionFromCapability(cap);
-                    }
-                    else
-                    {
-                        msg = cap.toString();
-                    }
-                    msg = msg + " required by:";
-                    System.out.println(msg);
-                    for (BundleWire wire : dependents)
-                    {
-                        System.out.println("   " + wire.getRequirerWiring().getBundle());
-                    }
-                }
-                else if (keyAttr != null)
-                {
-                    System.out.println(cap.getNamespace()
-                        + "; "
-                        + cap.getAttributes().get(cap.getNamespace())
-                        + " "
-                        + getVersionFromCapability(cap)
-                        + " "
-                        + UNUSED_MESSAGE);
-                }
-                else
-                {
-                    System.out.println(cap + " " + UNUSED_MESSAGE);
-                }
-            }
-        }
-        return matches;
-    }
-
-    private static Map<BundleCapability, List<BundleWire>> aggregateCapabilities(
-        Pattern namespace, List<BundleWire> wires)
-    {
-        // Aggregate matching capabilities.
-        Map<BundleCapability, List<BundleWire>> map =
-            new HashMap<BundleCapability, List<BundleWire>>();
-        for (BundleWire wire : wires)
-        {
-            if (matchNamespace(namespace, wire.getCapability().getNamespace()))
-            {
-                List<BundleWire> dependents = map.get(wire.getCapability());
-                if (dependents == null)
-                {
-                    dependents = new ArrayList<BundleWire>();
-                    map.put(wire.getCapability(), dependents);
-                }
-                dependents.add(wire);
-            }
-        }
-        return map;
-    }
-
-    static boolean printServiceCapabilities(Bundle b)
-    {
-        boolean matches = false;
-
-        try
-        {
-            ServiceReference<?>[] refs = b.getRegisteredServices();
-
-            if ((refs != null) && (refs.length > 0))
-            {
-                matches = true;
-                // Print properties for each service.
-                for (ServiceReference<?> ref : refs)
-                {
-                    // Print object class with "namespace".
-                    System.out.println(
-                        NONSTANDARD_SERVICE_NAMESPACE
-                        + "; "
-                        + ShellUtil.getValueString(ref.getProperty("objectClass"))
-                        + " with properties:");
-                    // Print service properties.
-                    String[] keys = ref.getPropertyKeys();
-                    for (String key : keys)
-                    {
-                        if (!key.equalsIgnoreCase(Constants.OBJECTCLASS))
-                        {
-                            Object v = ref.getProperty(key);
-                            System.out.println("   "
-                                + key + " = " + ShellUtil.getValueString(v));
-                        }
-                    }
-                    Bundle[] users = ref.getUsingBundles();
-                    if ((users != null) && (users.length > 0))
-                    {
-                        System.out.println("   Used by:");
-                        for (Bundle user : users)
-                        {
-                            System.out.println("      " + user);
-                        }
-                    }
-                }
-            }
-        }
-        catch (Exception ex)
-        {
-            System.err.println(ex.toString());
-        }
-
-        return matches;
-    }
-
-    private static String getVersionFromCapability(BundleCapability c)
-    {
-        Object o = c.getAttributes().get(Constants.VERSION_ATTRIBUTE);
-        if (o == null)
-        {
-            o = c.getAttributes().get(Constants.BUNDLE_VERSION_ATTRIBUTE);
-        }
-        return (o == null) ? "" : o.toString();
-    }
-
-    private static boolean matchNamespace(Pattern namespace, String actual)
-    {
-        return namespace.matcher(actual).matches();
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d0180939/bundle/command/src/main/java/org/apache/karaf/bundle/command/Classes.java
----------------------------------------------------------------------
diff --git a/bundle/command/src/main/java/org/apache/karaf/bundle/command/Classes.java b/bundle/command/src/main/java/org/apache/karaf/bundle/command/Classes.java
deleted file mode 100644
index b0f80ff..0000000
--- a/bundle/command/src/main/java/org/apache/karaf/bundle/command/Classes.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * 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.karaf.bundle.command;
-
-import java.util.Collection;
-import java.util.List;
-
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Option;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.wiring.BundleWiring;
-
-@Command(scope = "bundle", name = "classes", description = "Displays a list of classes contained in the bundle")
-@Service
-public class Classes extends BundlesCommand {
-
-    @Option(name = "-a", aliases={"--display-all-files"}, description="List all classes and files in the bundle", required = false, multiValued = false)
-    boolean displayAllFiles;
-
-    public Classes() {
-        super(true);
-    }
-
-    protected void doExecute(List<Bundle> bundles) throws Exception {
-        for (Bundle bundle : bundles) {
-            printResources(bundle);
-        }
-    }
-
-    protected void printResources(Bundle bundle) {
-        BundleWiring wiring = bundle.adapt(BundleWiring.class);
-        if (wiring != null){
-            Collection<String> resources;
-            if (displayAllFiles){
-                resources = wiring.listResources("/", null, BundleWiring.LISTRESOURCES_RECURSE);
-            }else{
-                resources = wiring.listResources("/", "*class", BundleWiring.LISTRESOURCES_RECURSE);
-            }
-            for (String resource:resources){
-                System.out.println(resource);
-            }
-        } else {
-            System.out.println("Bundle " + bundle.getBundleId() + " is not resolved.");
-        }
-    }
-
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d0180939/bundle/command/src/main/java/org/apache/karaf/bundle/command/Diag.java
----------------------------------------------------------------------
diff --git a/bundle/command/src/main/java/org/apache/karaf/bundle/command/Diag.java b/bundle/command/src/main/java/org/apache/karaf/bundle/command/Diag.java
deleted file mode 100644
index 1e8e11b..0000000
--- a/bundle/command/src/main/java/org/apache/karaf/bundle/command/Diag.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * 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.karaf.bundle.command;
-
-import java.util.List;
-
-import org.apache.karaf.bundle.core.BundleInfo;
-import org.apache.karaf.bundle.core.BundleState;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.apache.karaf.shell.support.ShellUtil;
-import org.osgi.framework.Bundle;
-
-@Command(scope = "bundle", name = "diag", description = "Displays diagnostic information why a bundle is not Active")
-@Service
-public class Diag extends BundlesCommand {
-
-    public Diag() {
-        super(true);
-    }
-
-    protected void doExecute(List<Bundle> bundles) throws Exception {
-        for (Bundle bundle : bundles) {
-            BundleInfo info = bundleService.getInfo(bundle);
-            if (info.getState() == BundleState.Failure || info.getState() == BundleState.Waiting
-                || info.getState() == BundleState.GracePeriod || info.getState() == BundleState.Installed) {
-                String title = ShellUtil.getBundleName(bundle);
-                System.out.println(title);
-                System.out.println(ShellUtil.getUnderlineString(title));
-                System.out.println("Status: " + info.getState().toString());
-                System.out.println(this.bundleService.getDiag(bundle));
-                System.out.println();
-            }
-        }
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d0180939/bundle/command/src/main/java/org/apache/karaf/bundle/command/DynamicImport.java
----------------------------------------------------------------------
diff --git a/bundle/command/src/main/java/org/apache/karaf/bundle/command/DynamicImport.java b/bundle/command/src/main/java/org/apache/karaf/bundle/command/DynamicImport.java
deleted file mode 100644
index 74fc20a..0000000
--- a/bundle/command/src/main/java/org/apache/karaf/bundle/command/DynamicImport.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * 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.karaf.bundle.command;
-
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.osgi.framework.Bundle;
-
-/**
- * Command for enabling/disabling debug logging on a bundle and calculating the difference in
- * wired imports.
- */
-@Command(scope = "bundle", name = "dynamic-import", description = "Enables/disables dynamic-import for a given bundle.")
-@Service
-public class DynamicImport extends BundleCommand {
-
-    public DynamicImport() {
-        super(true);
-    }
-
-    @Override
-    protected void doExecute(Bundle bundle) throws Exception {
-        if (bundleService.isDynamicImport(bundle)) {
-            System.out.printf("Disabling dynamic imports on bundle %s%n", bundle);
-            bundleService.disableDynamicImports(bundle);
-        } else {
-            System.out.printf("Enabling dynamic imports on bundle %s%n", bundle);
-            bundleService.enableDynamicImports(bundle);
-        }
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d0180939/bundle/command/src/main/java/org/apache/karaf/bundle/command/FindClass.java
----------------------------------------------------------------------
diff --git a/bundle/command/src/main/java/org/apache/karaf/bundle/command/FindClass.java b/bundle/command/src/main/java/org/apache/karaf/bundle/command/FindClass.java
deleted file mode 100644
index 4a9fc75..0000000
--- a/bundle/command/src/main/java/org/apache/karaf/bundle/command/FindClass.java
+++ /dev/null
@@ -1,68 +0,0 @@
-package org.apache.karaf.bundle.command;
-
-/*
- * 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.
- */
-
-import java.util.Collection;
-
-import org.apache.karaf.shell.api.action.Action;
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.lifecycle.Reference;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.apache.karaf.shell.support.ShellUtil;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.wiring.BundleWiring;
-
-@Command(scope = "bundle", name = "find-class", description = "Locates a specified class in any deployed bundle")
-@Service
-public class FindClass implements Action {
-
-    @Argument(index = 0, name = "className", description = "Class name or partial class name to be found", required = true, multiValued = false)
-    String className;
-
-    @Reference
-    BundleContext bundleContext;
-
-    @Override
-    public Object execute() throws Exception {
-        findResource();
-        return null;
-    }
-
-    protected void findResource() {
-        Bundle[] bundles = bundleContext.getBundles();
-        String filter = "*" + className + "*";
-        for (Bundle bundle:bundles){
-            BundleWiring wiring = bundle.adapt(BundleWiring.class);
-            if (wiring != null){
-                Collection<String> resources = wiring.listResources("/", filter, BundleWiring.LISTRESOURCES_RECURSE);
-                if (resources.size() > 0){
-                    String title = ShellUtil.getBundleName(bundle);
-                    System.out.println("\n" + title);
-                }
-                for (String resource:resources){
-                    System.out.println(resource);
-                }
-            } else {
-                System.out.println("Bundle " + bundle.getBundleId() + " is not resolved.");
-            }
-        }
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d0180939/bundle/command/src/main/java/org/apache/karaf/bundle/command/Headers.java
----------------------------------------------------------------------
diff --git a/bundle/command/src/main/java/org/apache/karaf/bundle/command/Headers.java b/bundle/command/src/main/java/org/apache/karaf/bundle/command/Headers.java
deleted file mode 100644
index 16083ff..0000000
--- a/bundle/command/src/main/java/org/apache/karaf/bundle/command/Headers.java
+++ /dev/null
@@ -1,333 +0,0 @@
-/*
- * 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.karaf.bundle.command;
-
-import java.util.Arrays;
-import java.util.Comparator;
-import java.util.Dictionary;
-import java.util.Enumeration;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-
-import org.apache.felix.utils.manifest.Attribute;
-import org.apache.felix.utils.manifest.Clause;
-import org.apache.felix.utils.manifest.Directive;
-import org.apache.felix.utils.manifest.Parser;
-import org.apache.felix.utils.version.VersionRange;
-import org.apache.felix.utils.version.VersionTable;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Option;
-import org.apache.karaf.shell.api.action.lifecycle.Reference;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.apache.karaf.shell.api.console.Terminal;
-import org.apache.karaf.shell.support.ShellUtil;
-import org.fusesource.jansi.Ansi;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.Constants;
-import org.osgi.framework.wiring.BundleCapability;
-import org.osgi.framework.wiring.BundleRevision;
-import org.osgi.framework.wiring.BundleWiring;
-
-@Command(scope = "bundle", name = "headers", description = "Displays OSGi headers of a given bundles.")
-@Service
-public class Headers extends BundlesCommand {
-
-    protected final static String BUNDLE_PREFIX = "Bundle-";
-    protected final static String PACKAGE_SUFFFIX = "-Package";
-    protected final static String SERVICE_SUFFIX = "-Service";
-    protected final static String CAPABILITY_SUFFIX = "-Capability";
-    protected final static String IMPORT_PACKAGES_ATTRIB = "Import-Package";
-    protected final static String REQUIRE_BUNDLE_ATTRIB = "Require-Bundle";
-
-    @Option(name = "--indent", description = "Indentation method")
-    int indent = -1;
-
-    @Reference
-    Terminal terminal;
-    
-    public Headers() {
-        super(true);
-    }
-
-    protected void doExecute(List<Bundle> bundles) throws Exception {
-        for (Bundle bundle : bundles) {
-            printHeaders(bundle);
-        }
-    }
-
-    protected void printHeaders(Bundle bundle) throws Exception {
-        String title = ShellUtil.getBundleName(bundle);
-        System.out.println("\n" + title);
-        System.out.println(ShellUtil.getUnderlineString(title));
-        if (indent == 0) {
-            Dictionary<String, String> dict = bundle.getHeaders();
-            Enumeration<String> keys = dict.keys();
-            while (keys.hasMoreElements()) {
-                Object k = keys.nextElement();
-                Object v = dict.get(k);
-                System.out.println(k + " = " + ShellUtil.getValueString(v));
-            }
-        } else {
-            System.out.println(generateFormattedOutput(bundle));
-        }
-    }
-
-    protected String generateFormattedOutput(Bundle bundle) {
-        StringBuilder output = new StringBuilder();
-        Map<String, Object> otherAttribs = new HashMap<String, Object>();
-        Map<String, Object> bundleAttribs = new HashMap<String, Object>();
-        Map<String, Object> serviceAttribs = new HashMap<String, Object>();
-        Map<String, Object> packagesAttribs = new HashMap<String, Object>();
-        Dictionary<String, String> dict = bundle.getHeaders();
-        Enumeration<String> keys = dict.keys();
-
-        // do an initial loop and separate the attributes in different groups
-        while (keys.hasMoreElements()) {
-            String k = (String) keys.nextElement();
-            Object v = dict.get(k);
-            if (k.startsWith(BUNDLE_PREFIX)) {
-                // starts with Bundle-xxx
-                bundleAttribs.put(k, v);
-            } else if (k.endsWith(SERVICE_SUFFIX) || k.endsWith(CAPABILITY_SUFFIX)) {
-                // ends with xxx-Service
-                serviceAttribs.put(k, v);
-            } else if (k.endsWith(PACKAGE_SUFFFIX)) {
-                // ends with xxx-Package
-                packagesAttribs.put(k, v);
-            } else if (k.endsWith(REQUIRE_BUNDLE_ATTRIB)) {
-                // require bundle statement
-                packagesAttribs.put(k, v);
-            } else {
-                // the remaining attribs
-                otherAttribs.put(k, v);
-            }
-        }
-
-        // we will display the formatted result like this:
-        // Bundle-Name (ID)
-        // -----------------------
-        // all other attributes
-        //
-        // all Bundle attributes
-        //
-        // all Service attributes
-        //
-        // all Package attributes
-        Iterator<Map.Entry<String, Object>> it = otherAttribs.entrySet().iterator();
-        while (it.hasNext()) {
-            Map.Entry<String, Object> e = it.next();
-            output.append(String.format("%s = %s\n", e.getKey(), ShellUtil.getValueString(e.getValue())));
-        }
-        if (otherAttribs.size() > 0) {
-            output.append('\n');
-        }
-
-        it = bundleAttribs.entrySet().iterator();
-        while (it.hasNext()) {
-            Map.Entry<String, Object> e = it.next();
-            output.append(String.format("%s = %s\n", e.getKey(), ShellUtil.getValueString(e.getValue())));
-        }
-        if (bundleAttribs.size() > 0) {
-            output.append('\n');
-        }
-
-        it = serviceAttribs.entrySet().iterator();
-        while (it.hasNext()) {
-            Map.Entry<String, Object> e = it.next();
-            output.append(e.getKey());
-            output.append(" = \n");
-            formatHeader(ShellUtil.getValueString(e.getValue()), null, output, indent);
-            output.append("\n");
-        }
-        if (serviceAttribs.size() > 0) {
-            output.append('\n');
-        }
-
-        Map<String, ClauseFormatter> formatters = new HashMap<String, ClauseFormatter>();
-        formatters.put(REQUIRE_BUNDLE_ATTRIB, new ClauseFormatter() {
-            public void pre(Clause clause, StringBuilder output) {
-                boolean isSatisfied = checkBundle(clause.getName(), clause.getAttribute("bundle-version"));
-                Ansi.ansi(output).fg(isSatisfied ? Ansi.Color.DEFAULT : Ansi.Color.RED).a("");
-            }
-            public void post(Clause clause, StringBuilder output) {
-                Ansi.ansi(output).reset().a("");
-            }
-        });
-        formatters.put(IMPORT_PACKAGES_ATTRIB, new ClauseFormatter() {
-            public void pre(Clause clause, StringBuilder output) {
-                boolean isSatisfied = checkPackage(clause.getName(), clause.getAttribute("version"));
-                boolean isOptional = "optional".equals(clause.getDirective("resolution"));
-                Ansi.ansi(output).fg(isSatisfied ? Ansi.Color.DEFAULT : Ansi.Color.RED)
-                                 .a(isSatisfied || isOptional ? Ansi.Attribute.INTENSITY_BOLD_OFF : Ansi.Attribute.INTENSITY_BOLD)
-                                 .a("");
-            }
-            public void post(Clause clause, StringBuilder output) {
-                Ansi.ansi(output).reset().a("");
-            }
-        });
-
-        it = packagesAttribs.entrySet().iterator();
-        while (it.hasNext()) {
-            Map.Entry<String, Object> e = it.next();
-            output.append(e.getKey());
-            output.append(" = \n");
-            formatHeader(ShellUtil.getValueString(e.getValue()), formatters.get(e.getKey()), output, indent);
-            output.append("\n");
-        }
-        if (packagesAttribs.size() > 0) {
-            output.append('\n');
-        }
-
-        return output.toString();
-    }
-
-    protected interface ClauseFormatter {
-        void pre(Clause clause, StringBuilder output);
-        void post(Clause clause, StringBuilder output);
-    }
-
-    protected void formatHeader(String header, ClauseFormatter formatter, StringBuilder builder, int indent) {
-        Clause[] clauses = Parser.parseHeader(header);
-        formatClauses(clauses, formatter, builder, indent);
-    }
-
-    protected void formatClauses(Clause[] clauses, ClauseFormatter formatter, StringBuilder builder, int indent) {
-        boolean first = true;
-        for (Clause clause : clauses) {
-            if (first) {
-                first = false;
-            } else {
-                builder.append(",\n");
-            }
-            formatClause(clause, formatter, builder, indent);
-        }
-    }
-
-    protected void formatClause(Clause clause, ClauseFormatter formatter, StringBuilder builder, int indent) {
-        builder.append("\t");
-        if (formatter != null) {
-            formatter.pre(clause, builder);
-        }
-        formatClause(clause, builder, indent);
-        if (formatter != null) {
-            formatter.post(clause, builder);
-        }
-    }
-
-    protected int getTermWidth() {
-        return terminal.getWidth();
-
-    }
-
-    protected void formatClause(Clause clause, StringBuilder builder, int indent) {
-        if (indent < 0) {
-            if (clause.toString().length() < getTermWidth() - 8) { // -8 for tabs
-                indent = 1;
-            } else {
-                indent = 3;
-            }
-        }
-        String name = clause.getName();
-        Directive[] directives = clause.getDirectives();
-        Attribute[] attributes = clause.getAttributes();
-        Arrays.sort(directives, new Comparator<Directive>() {
-            public int compare(Directive o1, Directive o2) {
-                return o1.getName().compareTo(o2.getName());
-            }
-        });
-        Arrays.sort(attributes, new Comparator<Attribute>() {
-            public int compare(Attribute o1, Attribute o2) {
-                return o1.getName().compareTo(o2.getName());
-            }
-        });
-        builder.append(name);
-        for (int i = 0; directives != null && i < directives.length; i++) {
-            builder.append(";");
-            if (indent > 1) {
-                builder.append("\n\t\t");
-            }
-            builder.append(directives[i].getName()).append(":=");
-            String v = directives[i].getValue();
-            if (v.contains(",")) {
-                if (indent > 2 && v.length() > 20) {
-                    v = v.replace(",", ",\n\t\t\t");
-                }
-                builder.append("\"").append(v).append("\"");
-            } else {
-                builder.append(v);
-            }
-        }
-        for (int i = 0; attributes != null && i < attributes.length; i++) {
-            builder.append(";");
-            if (indent > 1) {
-                builder.append("\n\t\t");
-            }
-            builder.append(attributes[i].getName()).append("=");
-            String v = attributes[i].getValue();
-            if (v.contains(",")) {
-                if (indent > 2 && v.length() > 20) {
-                    v = v.replace(",", ",\n\t\t\t");
-                }
-                builder.append("\"").append(v).append("\"");
-            } else {
-                builder.append(v);
-            }
-        }
-    }
-
-
-    private boolean checkBundle(String bundleName, String version) {
-        VersionRange vr = VersionRange.parseVersionRange(version);
-        Bundle[] bundles = bundleContext.getBundles();
-        for (int i = 0; (bundles != null) && (i < bundles.length); i++) {
-            String sym = bundles[i].getSymbolicName();
-            if ((sym != null) && sym.equals(bundleName)) {
-                if (vr.contains(bundles[i].getVersion())) {
-                    return true;
-                }
-            }
-        }
-        return false;
-    }
-
-    private boolean checkPackage(String packageName, String version) {
-        VersionRange range = VersionRange.parseVersionRange(version);
-        Bundle[] bundles = bundleContext.getBundles();
-        for (int i = 0; (bundles != null) && (i < bundles.length); i++) {
-            BundleWiring wiring = bundles[i].adapt(BundleWiring.class);
-            List<BundleCapability> caps = wiring != null ? wiring.getCapabilities(BundleRevision.PACKAGE_NAMESPACE) : null;
-            if (caps != null) {
-                for (BundleCapability cap : caps) {
-                    String n = getAttribute(cap, BundleRevision.PACKAGE_NAMESPACE);
-                    String v = getAttribute(cap, Constants.VERSION_ATTRIBUTE);
-                    if (packageName.equals(n) && range.contains(VersionTable.getVersion(v))) {
-                        return true;
-                    }
-                }
-            }
-        }
-        return false;
-    }
-    
-    private String getAttribute(BundleCapability cap, String name)  {
-        Object obj = cap.getAttributes().get(name);
-        return obj != null ? obj.toString() : null;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d0180939/bundle/command/src/main/java/org/apache/karaf/bundle/command/Info.java
----------------------------------------------------------------------
diff --git a/bundle/command/src/main/java/org/apache/karaf/bundle/command/Info.java b/bundle/command/src/main/java/org/apache/karaf/bundle/command/Info.java
deleted file mode 100644
index 451ec87..0000000
--- a/bundle/command/src/main/java/org/apache/karaf/bundle/command/Info.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * 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.karaf.bundle.command;
-
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.net.URL;
-import java.util.List;
-
-import org.apache.karaf.bundle.command.wikidoc.AnsiPrintingWikiVisitor;
-import org.apache.karaf.bundle.command.wikidoc.WikiParser;
-import org.apache.karaf.bundle.command.wikidoc.WikiVisitor;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.apache.karaf.shell.support.ShellUtil;
-import org.osgi.framework.Bundle;
-
-@Command(scope = "bundle", name = "info", description = "Displays detailed information of a given bundles.")
-@Service
-public class Info extends BundlesCommand {
-
-    public Info() {
-        super(true);
-    }
-
-    protected void doExecute(List<Bundle> bundles) throws Exception {
-        for (Bundle bundle : bundles) {
-          printInfo(bundle);
-        }
-    }
-
-    /**
-     * <p>
-     * Get the OSGI-INF/bundle.info entry from the bundle and display it.
-     * </p>
-     *
-     * @param bundle the bundle.
-     */
-    protected void printInfo(Bundle bundle) {
-        String title = ShellUtil.getBundleName(bundle);
-        System.out.println("\n" + title);
-        System.out.println(ShellUtil.getUnderlineString(title));
-        URL bundleInfo = bundle.getEntry("OSGI-INF/bundle.info");
-        if (bundleInfo != null) {
-        	BufferedReader reader = null;
-            try {
-                reader = new BufferedReader(new InputStreamReader(bundleInfo.openStream()));
-                WikiVisitor visitor = new AnsiPrintingWikiVisitor(System.out);
-                WikiParser parser = new WikiParser(visitor);
-                parser.parse(reader);
-            } catch (Exception e) {
-                // ignore
-            } finally {
-            	if (reader != null) {
-            		try {
-						reader.close();
-					} catch (IOException e) {
-					}
-            	}
-            }
-        }
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d0180939/bundle/command/src/main/java/org/apache/karaf/bundle/command/Install.java
----------------------------------------------------------------------
diff --git a/bundle/command/src/main/java/org/apache/karaf/bundle/command/Install.java b/bundle/command/src/main/java/org/apache/karaf/bundle/command/Install.java
deleted file mode 100644
index 11fba89..0000000
--- a/bundle/command/src/main/java/org/apache/karaf/bundle/command/Install.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * 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.karaf.bundle.command;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import org.apache.karaf.shell.api.action.Action;
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Option;
-import org.apache.karaf.shell.api.action.lifecycle.Reference;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.apache.karaf.shell.support.MultiException;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.BundleContext;
-
-@Command(scope = "bundle", name = "install", description = "Installs one or more bundles.")
-@Service
-public class Install implements Action {
-
-    @Argument(index = 0, name = "urls", description = "Bundle URLs separated by whitespaces", required = true, multiValued = true)
-    List<String> urls;
-
-    @Option(name = "-s", aliases={"--start"}, description="Starts the bundles after installation", required = false, multiValued = false)
-    boolean start;
-
-    @Reference
-    BundleContext bundleContext;
-
-    @Override
-    public Object execute() throws Exception {
-        List<Exception> exceptions = new ArrayList<Exception>();
-        List<Bundle> bundles = new ArrayList<Bundle>();
-        for (String url : urls) {
-            try {
-                bundles.add(bundleContext.installBundle(url, null));
-            } catch (Exception e) {
-                exceptions.add(new Exception("Unable to install bundle " + url, e));
-            }
-        }
-        if (start) {
-            for (Bundle bundle : bundles) {
-                try {
-                    bundle.start();
-                } catch (Exception e) {
-                    exceptions.add(new Exception("Unable to start bundle " + bundle.getLocation(), e));
-                }
-            }
-        }
-        if (bundles.size() == 1) {
-            System.out.println("Bundle ID: " + bundles.get(0).getBundleId());
-        } else {
-            StringBuffer sb = new StringBuffer("Bundle IDs: ");
-            for (Bundle bundle : bundles) {
-                if (sb.length() > 0) {
-                    sb.append(", ");
-                }
-                sb.append(bundle.getBundleId());
-            }
-            System.out.println(sb);
-        }
-        MultiException.throwIf("Error installing bundles", exceptions);
-        return null;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d0180939/bundle/command/src/main/java/org/apache/karaf/bundle/command/ListBundleServices.java
----------------------------------------------------------------------
diff --git a/bundle/command/src/main/java/org/apache/karaf/bundle/command/ListBundleServices.java b/bundle/command/src/main/java/org/apache/karaf/bundle/command/ListBundleServices.java
deleted file mode 100644
index 28f8264..0000000
--- a/bundle/command/src/main/java/org/apache/karaf/bundle/command/ListBundleServices.java
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * 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.karaf.bundle.command;
-
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Option;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.apache.karaf.shell.support.ShellUtil;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.Constants;
-import org.osgi.framework.ServiceReference;
-
-@Command(scope = "bundle", name = "services", description = "Lists OSGi services per Bundle")
-@Service
-public class ListBundleServices extends BundlesCommand {
-
-    @Option(name = "-a", aliases = {}, description = "Shows all services. (By default Karaf commands are hidden)", required = false, multiValued = false)
-    boolean showAll;
-
-    @Option(name = "-u", aliases = {}, description = "Shows the services each bundle uses. (By default the provided services are shown)", required = false, multiValued = false)
-    boolean inUse;
-    
-    @Option(name = "-p", aliases = {}, description = "Shows the properties of the services", required = false, multiValued = false)
-    boolean showProperties = false;
-
-    Set<String> hidden = new HashSet<String>(Arrays.asList(new String[] {
-        "org.apache.felix.service.command.Function",
-        "org.apache.karaf.shell.console.Completer"
-    }));
-    
-    public ListBundleServices() {
-        super(true);
-    }
-    
-    @Override
-    protected void doExecute(List<Bundle> bundles) throws Exception {
-        for (Bundle bundle : bundles) {
-            ServiceReference<?>[] refs = (inUse) ? bundle.getServicesInUse() : bundle.getRegisteredServices();
-            printServices(bundle, refs, showProperties);
-        }
-    }
-    
-    private void printServices(Bundle bundle, ServiceReference<?>[] refs, boolean showProperties) {
-        boolean headerPrinted = false;
-        boolean needSeparator = false;
-        
-        if (refs == null) {
-            return;
-        }
-
-        for (ServiceReference<?> serviceRef : refs) {
-            String[] objectClass = (String[]) serviceRef.getProperty(Constants.OBJECTCLASS);
-
-            boolean print = showAll || !isCommandOrCompleter(objectClass);
-
-            // Print header if we have not already done so.
-            if (!headerPrinted) {
-                headerPrinted = true;
-                System.out.println("");
-                String title = ShellUtil.getBundleName(bundle) + ((inUse) ? " uses:" : " provides:");
-                System.out.println(title);
-                System.out.println(ShellUtil.getUnderlineString(title));
-            }
-
-            if (print) {
-                // Print service separator if necessary.
-                if (needSeparator && showProperties) {
-                    System.out.println("----");
-                }
-
-                if (showProperties) {
-                    printProperties(serviceRef);
-                } else {
-                    System.out.println(ShellUtil.getValueString(objectClass));
-                }
-
-                needSeparator = true;
-            }
-        }
-    }
-
-    private boolean isCommandOrCompleter(String[] objectClasses) {
-        for (String objectClass : objectClasses) {
-            if (hidden.contains(objectClass)) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    private void printProperties(ServiceReference<?> serviceRef) {
-        for (String key : serviceRef.getPropertyKeys()) {
-            System.out.println(key + " = " + ShellUtil.getValueString(serviceRef.getProperty(key)));
-        }
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d0180939/bundle/command/src/main/java/org/apache/karaf/bundle/command/ListBundles.java
----------------------------------------------------------------------
diff --git a/bundle/command/src/main/java/org/apache/karaf/bundle/command/ListBundles.java b/bundle/command/src/main/java/org/apache/karaf/bundle/command/ListBundles.java
deleted file mode 100644
index 107e578..0000000
--- a/bundle/command/src/main/java/org/apache/karaf/bundle/command/ListBundles.java
+++ /dev/null
@@ -1,176 +0,0 @@
-/*
- * 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.karaf.bundle.command;
-
-import org.apache.karaf.bundle.core.BundleInfo;
-import org.apache.karaf.bundle.core.BundleService;
-import org.apache.karaf.bundle.core.BundleState;
-import org.apache.karaf.shell.api.action.Action;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Option;
-import org.apache.karaf.shell.api.action.lifecycle.Reference;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.apache.karaf.shell.support.table.ShellTable;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.startlevel.FrameworkStartLevel;
-
-@Command(scope = "bundle", name = "list", description = "Lists all installed bundles.")
-@Service
-public class ListBundles implements Action {
-
-    @Option(name = "-l", aliases = {}, description = "Show the locations", required = false, multiValued = false)
-    boolean showLoc;
-
-    @Option(name = "-s", description = "Shows the symbolic name", required = false, multiValued = false)
-    boolean showSymbolic;
-
-    @Option(name = "-u", description = "Shows the update locations", required = false, multiValued = false)
-    boolean showUpdate;
-
-    @Option(name = "-t", valueToShowInHelp = "", description = "Specifies the bundle threshold; bundles with a start-level less than this value will not get printed out.", required = false, multiValued = false)
-    int bundleLevelThreshold = -1;
-
-    @Option(name = "--no-format", description = "Disable table rendered output", required = false, multiValued = false)
-    boolean noFormat;
-
-    @Reference
-    BundleContext bundleContext;
-
-    @Reference
-    private BundleService bundleService;
-
-    public void setBundleService(BundleService bundleService) {
-        this.bundleService = bundleService;
-    }
-
-    @Override
-    public Object execute() throws Exception {
-        Bundle[] bundles = bundleContext.getBundles();
-        if (bundles == null) {
-            System.out.println("There are no installed bundles.");
-            return null;
-        }
-
-        determineBundleLevelThreshold();
-        
-        // Display active start level.
-        FrameworkStartLevel fsl = bundleContext.getBundle(0).adapt(FrameworkStartLevel.class);
-        if (fsl != null) {
-            System.out.println("START LEVEL " + fsl.getStartLevel() + " , List Threshold: " + bundleLevelThreshold);
-        }
-
-        ShellTable table = new ShellTable();
-        table.column("ID").alignRight();
-        table.column("State");
-        table.column("Lvl").alignRight();
-        table.column("Version");
-        table.column(getNameHeader());
-        
-        for (int i = 0; i < bundles.length; i++) {
-            Bundle bundle = bundles[i];
-            BundleInfo info = this.bundleService.getInfo(bundle);
-            if (info.getStartLevel() >= bundleLevelThreshold) {
-                String name = getNameToShow(info) + printFragments(info) + printHosts(info);
-                String version = info.getVersion();
-                table.addRow().addContent(info.getBundleId(), getStateString(info.getState()), 
-                        info.getStartLevel(), version, name);
-            }
-        }
-        table.print(System.out, !noFormat);
-
-        return null;
-    }
-
-    private String getNameHeader() {
-        String msg = "Name";
-        if (showLoc) {
-            msg = "Location";
-        } else if (showSymbolic) {
-            msg = "Symbolic name";
-        } else if (showUpdate) {
-            msg = "Update location";
-        }
-        return msg;
-    }
-
-    private void determineBundleLevelThreshold() {
-        final String sbslProp = bundleContext.getProperty("karaf.systemBundlesStartLevel");
-        if (sbslProp != null) {
-            try {
-                if (bundleLevelThreshold < 0) {
-                    bundleLevelThreshold = Integer.valueOf(sbslProp);
-                }
-            } catch (Exception ignore) {
-                // ignore
-            }
-        }
-    }
-
-    private String printHosts(BundleInfo info) {
-        if (info.getFragmentHosts().size() <= 0) {
-            return "";
-        }
-        StringBuilder builder = new StringBuilder();
-        builder.append(", Hosts: ");
-        boolean first = true;
-        for (Bundle host : info.getFragmentHosts()) {
-            builder.append((first ? "" : ", ") + host.getBundleId());
-            first = false;
-        }
-        return builder.toString();
-    }
-
-    private String printFragments(BundleInfo info) {
-        if (info.getFragments().size() <= 0) {
-            return "";
-        }
-        StringBuilder builder = new StringBuilder();
-        builder.append(", Fragments: ");
-        boolean first = true;
-        for (Bundle host : info.getFragments()) {
-            builder.append((first ? "" : ", ") + host.getBundleId());
-            first = false;
-        }
-        return builder.toString();
-    }
-
-    private String getStateString(BundleState state) {
-        return (state == null) ? "" : state.toString();
-    }
-
-    /**
-     * Overwrite the default value is the user specifically requested to display
-     * one or the other.
-     * 
-     * @param info
-     * @return
-     */
-    private String getNameToShow(BundleInfo info) {
-        if (showLoc) {
-            return info.getUpdateLocation();
-        } else if (showSymbolic) {
-            return info.getSymbolicName() == null ? "<no symbolic name>" : info.getSymbolicName();
-        } else if (showUpdate) {
-            return info.getUpdateLocation();
-        } else {
-            String name = (info.getName() == null) ? info.getSymbolicName() : info.getName();
-            return (name == null) ? info.getUpdateLocation() : name;
-        }
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d0180939/bundle/command/src/main/java/org/apache/karaf/bundle/command/LoadTest.java
----------------------------------------------------------------------
diff --git a/bundle/command/src/main/java/org/apache/karaf/bundle/command/LoadTest.java b/bundle/command/src/main/java/org/apache/karaf/bundle/command/LoadTest.java
deleted file mode 100644
index 8ed318f..0000000
--- a/bundle/command/src/main/java/org/apache/karaf/bundle/command/LoadTest.java
+++ /dev/null
@@ -1,192 +0,0 @@
-/*
- * 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.karaf.bundle.command;
-
-import java.io.IOException;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-import java.util.Random;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.atomic.AtomicBoolean;
-
-import org.apache.karaf.shell.api.action.Action;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Option;
-import org.apache.karaf.shell.api.console.Session;
-import org.apache.karaf.shell.api.action.lifecycle.Reference;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.BundleException;
-import org.osgi.framework.FrameworkEvent;
-import org.osgi.framework.FrameworkListener;
-import org.osgi.framework.wiring.FrameworkWiring;
-
-@Command(scope = "bundle", name = "load-test", description = "Load test bundle lifecycle")
-@Service
-public class LoadTest implements Action {
-
-    @Option(name = "--threads", description = "number of concurrent threads")
-    int threads = 2;
-
-    @Option(name = "--delay", description = "maximum delay between actions")
-    int delay = 1;
-
-    @Option(name = "--iterations", description = "number of iterations per thread")
-    int iterations = 100;
-
-    @Option(name = "--refresh", description = "percentage of bundle refresh vs restart")
-    int refresh = 20;
-
-    @Option(name = "--excludes", description = "List of bundles (ids or symbolic names) to exclude")
-    List<String> excludes = Arrays.asList("0", "org.ops4j.pax.url.mvn", "org.ops4j.pax.logging.pax-logging-api", "org.ops4j.pax.logging.pax-logging-service");
-
-    @Reference
-    Session session;
-
-    @Reference
-    BundleContext bundleContext;
-
-    @Override
-    public Object execute() throws Exception {
-        if (!confirm(session)) {
-            return null;
-        }
-        final BundleContext bundleContext = this.bundleContext.getBundle(0).getBundleContext();
-        final FrameworkWiring wiring = bundleContext.getBundle().adapt(FrameworkWiring.class);
-        final CountDownLatch latch = new CountDownLatch(threads);
-        final Bundle[] bundles = bundleContext.getBundles();
-        final AtomicBoolean[] locks = new AtomicBoolean[bundles.length];
-        for (int b = 0; b < locks.length; b++) {
-            locks[b] = new AtomicBoolean(true);
-            // Avoid touching excluded bundles
-            if (excludes.contains(Long.toString(bundles[b].getBundleId()))
-                    || excludes.contains(bundles[b].getSymbolicName())) {
-                continue;
-            }
-            // Only touch active bundles
-            if (bundles[b].getState() != Bundle.ACTIVE) {
-                continue;
-            }
-            // Now set the lock to available
-            locks[b].set(false);
-        }
-        for (int i = 0; i < threads; i++) {
-            new Thread() {
-                public void run() {
-                    try {
-                        Random rand = new Random();
-                        for (int j = 0; j < iterations; j++) {
-                            for (;;) {
-                                int b = rand.nextInt(bundles.length);
-                                if (locks[b].compareAndSet(false, true)) {
-                                    try {
-                                        // Only touch active bundles
-                                        if (bundles[b].getState() != Bundle.ACTIVE) {
-                                            continue;
-                                        }
-                                        if (rand.nextInt(100) < refresh) {
-                                            try {
-                                                bundles[b].update();
-                                                final CountDownLatch latch = new CountDownLatch(1);
-                                                wiring.refreshBundles(Collections.singletonList(bundles[b]), new FrameworkListener() {
-                                                    public void frameworkEvent(FrameworkEvent event) {
-                                                        latch.countDown();
-                                                    }
-                                                });
-                                                latch.await();
-                                            } finally {
-                                                while (true) {
-                                                    try {
-                                                        bundles[b].start(Bundle.START_TRANSIENT);
-                                                        break;
-                                                    } catch (Exception e) {
-                                                        Thread.sleep(1);
-                                                    }
-                                                }
-                                            }
-                                        } else {
-                                            try {
-                                                bundles[b].stop(Bundle.STOP_TRANSIENT);
-                                            } finally {
-                                                while (true) {
-                                                    try {
-                                                        bundles[b].start(Bundle.START_TRANSIENT);
-                                                        break;
-                                                    } catch (Exception e) {
-                                                        Thread.sleep(1);
-                                                    }
-                                                }
-                                            }
-                                        }
-                                        Thread.sleep(rand.nextInt(delay));
-                                    } catch (Exception e) {
-                                        boolean ignore = false;
-                                        if (e instanceof BundleException && e.getMessage() != null) {
-                                            String msg = e.getMessage();
-                                            if ("Cannot acquire global lock to update the bundle.".equals(msg) ||
-                                                    "Unable to acquire global lock for resolve.".equals(msg) ||
-                                                    msg.matches("Bundle .* cannot be update, since it is either starting or stopping.")) {
-                                                ignore = true;
-                                            }
-                                        }
-                                        if (!ignore) {
-                                            e.printStackTrace();
-                                        }
-                                    } finally {
-                                        locks[b].set(false);
-                                    }
-                                }
-                                break;
-                            }
-                        }
-                    } catch (Throwable t) {
-                        t.printStackTrace();
-                    } finally {
-                        latch.countDown();
-                    }
-                }
-            }.start();
-        }
-        new Thread() {
-            @Override
-            public void run() {
-                try {
-                    latch.await();
-                } catch (InterruptedException e) {
-                    e.printStackTrace();
-                }
-                System.err.println("Load test finished");
-            }
-        }.start();
-        return null;
-    }
-
-    private boolean confirm(Session session) throws IOException {
-        for (;;) {
-            String msg = "You are about to perform a start/stop/refresh load test on bundles.\nDo you wish to continue (yes/no): ";
-            String str = session.readLine(msg, null);
-            if ("yes".equalsIgnoreCase(str)) {
-                return true;
-            }
-            if ("no".equalsIgnoreCase(str)) {
-                return false;
-            }
-        }
-    }
-}


[06/59] [abbrv] [KARAF-2852] Merge features/core and features/command

Posted by gn...@apache.org.
http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/src/main/java/org/apache/karaf/features/internal/repository/AggregateRepository.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/repository/AggregateRepository.java b/features/src/main/java/org/apache/karaf/features/internal/repository/AggregateRepository.java
new file mode 100644
index 0000000..0d5e83d
--- /dev/null
+++ b/features/src/main/java/org/apache/karaf/features/internal/repository/AggregateRepository.java
@@ -0,0 +1,55 @@
+/*
+ * 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.karaf.features.internal.repository;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.osgi.resource.Capability;
+import org.osgi.resource.Requirement;
+import org.osgi.service.repository.Repository;
+
+public class AggregateRepository implements Repository {
+
+    private final Collection<Repository> repositories;
+
+    public AggregateRepository(Collection<Repository> repositories) {
+        this.repositories = repositories;
+    }
+
+    @Override
+    public Map<Requirement, Collection<Capability>> findProviders(Collection<? extends Requirement> requirements) {
+        Map<Requirement, Collection<Capability>> result = new HashMap<Requirement, Collection<Capability>>();
+        for (Requirement requirement : requirements) {
+            List<Capability> caps = new ArrayList<Capability>();
+            for (Repository repository : repositories) {
+                Map<Requirement, Collection<Capability>> resMap =
+                        repository.findProviders(Collections.singleton(requirement));
+                Collection<Capability> res = resMap != null ? resMap.get(requirement) : null;
+                if (res != null) {
+                    caps.addAll(res);
+                }
+            }
+            result.put(requirement, caps);
+        }
+        return result;
+    }
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/src/main/java/org/apache/karaf/features/internal/repository/BaseRepository.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/repository/BaseRepository.java b/features/src/main/java/org/apache/karaf/features/internal/repository/BaseRepository.java
new file mode 100644
index 0000000..c4c0d16
--- /dev/null
+++ b/features/src/main/java/org/apache/karaf/features/internal/repository/BaseRepository.java
@@ -0,0 +1,86 @@
+/*
+ * 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.karaf.features.internal.repository;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.karaf.features.internal.resolver.CapabilitySet;
+import org.apache.karaf.features.internal.resolver.RequirementImpl;
+import org.apache.karaf.features.internal.resolver.SimpleFilter;
+import org.osgi.framework.Constants;
+import org.osgi.resource.Capability;
+import org.osgi.resource.Requirement;
+import org.osgi.resource.Resource;
+import org.osgi.service.repository.Repository;
+
+/**
+ */
+public class BaseRepository implements Repository {
+
+    protected final List<Resource> resources;
+    protected final Map<String, CapabilitySet> capSets;
+
+    public BaseRepository() {
+        this.resources = new ArrayList<Resource>();
+        this.capSets = new HashMap<String, CapabilitySet>();
+    }
+
+    protected void addResource(Resource resource) {
+        for (Capability cap : resource.getCapabilities(null)) {
+            String ns = cap.getNamespace();
+            CapabilitySet set = capSets.get(ns);
+            if (set == null) {
+                set = new CapabilitySet(Collections.singletonList(ns));
+                capSets.put(ns, set);
+            }
+            set.addCapability(cap);
+        }
+        resources.add(resource);
+    }
+
+    public List<Resource> getResources() {
+        return resources;
+    }
+
+    @Override
+    public Map<Requirement, Collection<Capability>> findProviders(Collection<? extends Requirement> requirements) {
+        Map<Requirement, Collection<Capability>> result = new HashMap<Requirement, Collection<Capability>>();
+        for (Requirement requirement : requirements) {
+            CapabilitySet set = capSets.get(requirement.getNamespace());
+            if (set != null) {
+                SimpleFilter sf;
+                if (requirement instanceof RequirementImpl) {
+                    sf = ((RequirementImpl) requirement).getFilter();
+                } else {
+                    String filter = requirement.getDirectives().get(Constants.FILTER_DIRECTIVE);
+                    sf = (filter != null)
+                            ? SimpleFilter.parse(filter)
+                            : new SimpleFilter(null, null, SimpleFilter.MATCH_ALL);
+                }
+                result.put(requirement, set.match(sf, true));
+            } else {
+                result.put(requirement, Collections.<Capability>emptyList());
+            }
+        }
+        return result;
+    }
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/src/main/java/org/apache/karaf/features/internal/repository/CacheRepository.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/repository/CacheRepository.java b/features/src/main/java/org/apache/karaf/features/internal/repository/CacheRepository.java
new file mode 100644
index 0000000..7916821
--- /dev/null
+++ b/features/src/main/java/org/apache/karaf/features/internal/repository/CacheRepository.java
@@ -0,0 +1,59 @@
+/*
+ * 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.karaf.features.internal.repository;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.osgi.resource.Capability;
+import org.osgi.resource.Requirement;
+import org.osgi.service.repository.Repository;
+
+public class CacheRepository implements Repository {
+
+    private final Repository repository;
+    private final Map<Requirement, Collection<Capability>> cache =
+            new ConcurrentHashMap<Requirement, Collection<Capability>>();
+
+    public CacheRepository(Repository repository) {
+        this.repository = repository;
+    }
+
+    @Override
+    public Map<Requirement, Collection<Capability>> findProviders(Collection<? extends Requirement> requirements) {
+        List<Requirement> missing = new ArrayList<Requirement>();
+        Map<Requirement, Collection<Capability>> result = new HashMap<Requirement, Collection<Capability>>();
+        for (Requirement requirement : requirements) {
+            Collection<Capability> caps = cache.get(requirement);
+            if (caps == null) {
+                missing.add(requirement);
+            } else {
+                result.put(requirement, caps);
+            }
+        }
+        Map<Requirement, Collection<Capability>> newCache = repository.findProviders(missing);
+        for (Requirement requirement : newCache.keySet()) {
+            cache.put(requirement, newCache.get(requirement));
+            result.put(requirement, newCache.get(requirement));
+        }
+        return result;
+    }
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/src/main/java/org/apache/karaf/features/internal/repository/HttpMetadataProvider.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/repository/HttpMetadataProvider.java b/features/src/main/java/org/apache/karaf/features/internal/repository/HttpMetadataProvider.java
new file mode 100644
index 0000000..1aecef1
--- /dev/null
+++ b/features/src/main/java/org/apache/karaf/features/internal/repository/HttpMetadataProvider.java
@@ -0,0 +1,88 @@
+/*
+ * 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.karaf.features.internal.repository;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.util.Map;
+import java.util.zip.GZIPInputStream;
+
+import org.apache.karaf.features.internal.util.JsonReader;
+
+/**
+ */
+public class HttpMetadataProvider implements MetadataProvider {
+
+    public static final String HEADER_ACCEPT_ENCODING = "Accept-Encoding";
+    public static final String HEADER_CONTENT_ENCODING = "Content-Encoding";
+    public static final String GZIP = "gzip";
+
+    private final String url;
+    private long lastModified;
+    private Map<String, Map<String, String>> metadatas;
+
+    public HttpMetadataProvider(String url) {
+        this.url = url;
+    }
+
+    @Override
+    public long getLastModified() {
+        return lastModified;
+    }
+
+    @Override
+    public Map<String, Map<String, String>> getMetadatas() {
+        try {
+            HttpURLConnection.setFollowRedirects(false);
+            HttpURLConnection con = (HttpURLConnection) new URL(url).openConnection();
+            if (lastModified > 0) {
+                con.setIfModifiedSince(lastModified);
+            }
+            con.setRequestProperty(HEADER_ACCEPT_ENCODING, GZIP);
+            if (con.getResponseCode() == HttpURLConnection.HTTP_OK) {
+                lastModified = con.getLastModified();
+                InputStream is = con.getInputStream();
+                if (GZIP.equals(con.getHeaderField(HEADER_CONTENT_ENCODING))) {
+                    is = new GZIPInputStream(is);
+                }
+                metadatas = verify(JsonReader.read(is));
+            } else if (con.getResponseCode() != HttpURLConnection.HTTP_NOT_MODIFIED) {
+                throw new IOException("Unexpected http response: "
+                        + con.getResponseCode() + " " + con.getResponseMessage());
+            }
+            return metadatas;
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    private Map<String, Map<String, String>> verify(Object value) {
+        Map<?,?> obj = Map.class.cast(value);
+        for (Map.Entry<?,?> entry : obj.entrySet()) {
+            String.class.cast(entry.getKey());
+            Map<?,?> child = Map.class.cast(entry.getValue());
+            for (Map.Entry<?,?> ce : child.entrySet()) {
+                String.class.cast(ce.getKey());
+                String.class.cast(ce.getValue());
+            }
+        }
+        return (Map<String, Map<String, String>>) obj;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/src/main/java/org/apache/karaf/features/internal/repository/MetadataProvider.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/repository/MetadataProvider.java b/features/src/main/java/org/apache/karaf/features/internal/repository/MetadataProvider.java
new file mode 100644
index 0000000..9ac54a1
--- /dev/null
+++ b/features/src/main/java/org/apache/karaf/features/internal/repository/MetadataProvider.java
@@ -0,0 +1,29 @@
+/*
+ * 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.karaf.features.internal.repository;
+
+import java.util.Map;
+
+/**
+ */
+public interface MetadataProvider {
+
+    long getLastModified();
+
+    Map<String, Map<String, String>> getMetadatas();
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/src/main/java/org/apache/karaf/features/internal/repository/MetadataRepository.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/repository/MetadataRepository.java b/features/src/main/java/org/apache/karaf/features/internal/repository/MetadataRepository.java
new file mode 100644
index 0000000..2d4fbba
--- /dev/null
+++ b/features/src/main/java/org/apache/karaf/features/internal/repository/MetadataRepository.java
@@ -0,0 +1,43 @@
+/*
+ * 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.karaf.features.internal.repository;
+
+import java.util.Map;
+
+import org.apache.karaf.features.internal.resolver.ResourceBuilder;
+import org.osgi.resource.Resource;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ */
+public class MetadataRepository extends BaseRepository {
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(MetadataRepository.class);
+
+    public MetadataRepository(MetadataProvider provider) {
+        Map<String, Map<String, String>> metadatas = provider.getMetadatas();
+        for (Map.Entry<String, Map<String, String>> metadata : metadatas.entrySet()) {
+            try {
+                Resource resource = ResourceBuilder.build(metadata.getKey(), metadata.getValue());
+                addResource(resource);
+            } catch (Exception e) {
+                LOGGER.info("Unable to build resource for " + metadata.getKey(), e);
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/src/main/java/org/apache/karaf/features/internal/repository/StaticRepository.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/repository/StaticRepository.java b/features/src/main/java/org/apache/karaf/features/internal/repository/StaticRepository.java
new file mode 100644
index 0000000..f289c8d
--- /dev/null
+++ b/features/src/main/java/org/apache/karaf/features/internal/repository/StaticRepository.java
@@ -0,0 +1,33 @@
+/*
+ * 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.karaf.features.internal.repository;
+
+import java.util.Collection;
+
+import org.osgi.resource.Resource;
+
+/**
+ */
+public class StaticRepository extends BaseRepository {
+
+    public StaticRepository(Collection<Resource> resources) {
+        for (Resource resource : resources) {
+            addResource(resource);
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/src/main/java/org/apache/karaf/features/internal/resolver/BaseClause.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/resolver/BaseClause.java b/features/src/main/java/org/apache/karaf/features/internal/resolver/BaseClause.java
new file mode 100644
index 0000000..0653398
--- /dev/null
+++ b/features/src/main/java/org/apache/karaf/features/internal/resolver/BaseClause.java
@@ -0,0 +1,114 @@
+/*
+ * 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.karaf.features.internal.resolver;
+
+import java.util.Map;
+
+import org.osgi.framework.Version;
+import org.osgi.resource.Resource;
+
+/**
+ */
+public abstract class BaseClause {
+
+    public abstract Resource getResource();
+
+    public abstract String getNamespace();
+
+    public abstract Map<String, String> getDirectives();
+
+    public abstract Map<String, Object> getAttributes();
+
+    @Override
+    public String toString() {
+        return toString(getResource(), getNamespace(), getAttributes(), getDirectives());
+    }
+
+    public static String toString(Resource res, String namespace, Map<String, Object> attrs, Map<String, String> dirs) {
+        StringBuilder sb = new StringBuilder();
+        if (res != null) {
+            sb.append("[").append(res).append("] ");
+        }
+        sb.append(namespace);
+        for (String key : attrs.keySet()) {
+            sb.append("; ");
+            append(sb, key, attrs.get(key), true);
+        }
+        for (String key : dirs.keySet()) {
+            sb.append("; ");
+            append(sb, key, dirs.get(key), false);
+        }
+        return sb.toString();
+    }
+
+    private static void append(StringBuilder sb, String key, Object val, boolean attribute) {
+        sb.append(key);
+        if (val instanceof Version) {
+            sb.append(":Version=");
+            sb.append(val);
+        } else if (val instanceof Long) {
+            sb.append(":Long=");
+            sb.append(val);
+        } else if (val instanceof Double) {
+            sb.append(":Double=");
+            sb.append(val);
+        } else if (val instanceof Iterable) {
+            Iterable it = (Iterable) val;
+            String scalar = null;
+            for (Object o : it) {
+                String ts;
+                if (o instanceof String) {
+                    ts = "String";
+                } else if (o instanceof Long) {
+                    ts = "Long";
+                } else if (o instanceof Double) {
+                    ts = "Double";
+                } else if (o instanceof Version) {
+                    ts = "Version";
+                } else {
+                    throw new IllegalArgumentException("Unsupported scalar type: " + o);
+                }
+                if (scalar == null) {
+                    scalar = ts;
+                } else if (!scalar.equals(ts)) {
+                    throw new IllegalArgumentException("Unconsistent list type for attribute " + key);
+                }
+            }
+            sb.append(":List<").append(scalar).append(">=");
+            sb.append("\"");
+            boolean first = true;
+            for (Object o : it) {
+                if (first) {
+                    first = false;
+                } else {
+                    sb.append(",");
+                }
+                sb.append(o.toString().replace("\"", "\\\"").replace(",", "\\,"));
+            }
+            sb.append("\"");
+        } else {
+            sb.append(attribute ? "=" : ":=");
+            String s = val.toString();
+            if (s.matches("[0-9a-zA-Z_\\-.]*")) {
+                sb.append(s);
+            } else {
+                sb.append("\"").append(s.replace("\"", "\\\\")).append("\"");
+            }
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/src/main/java/org/apache/karaf/features/internal/resolver/CandidateComparator.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/resolver/CandidateComparator.java b/features/src/main/java/org/apache/karaf/features/internal/resolver/CandidateComparator.java
new file mode 100644
index 0000000..ad4cc85
--- /dev/null
+++ b/features/src/main/java/org/apache/karaf/features/internal/resolver/CandidateComparator.java
@@ -0,0 +1,129 @@
+/*
+ * 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.karaf.features.internal.resolver;
+
+import java.util.Comparator;
+
+import org.osgi.framework.Version;
+import org.osgi.framework.namespace.BundleNamespace;
+import org.osgi.framework.namespace.PackageNamespace;
+import org.osgi.framework.wiring.BundleCapability;
+import org.osgi.resource.Capability;
+
+public class CandidateComparator implements Comparator<Capability>
+{
+    public int compare(Capability cap1, Capability cap2)
+    {
+        int c = 0;
+        // Always prefer system bundle
+        if (cap1 instanceof BundleCapability && !(cap2 instanceof BundleCapability)) {
+            c = -1;
+        } else if (!(cap1 instanceof BundleCapability) && cap2 instanceof BundleCapability) {
+            c = 1;
+        }
+        // Compare revision capabilities.
+        if ((c == 0) && cap1.getNamespace().equals(BundleNamespace.BUNDLE_NAMESPACE))
+        {
+            c = ((Comparable) cap1.getAttributes().get(BundleNamespace.BUNDLE_NAMESPACE))
+                    .compareTo(cap2.getAttributes().get(BundleNamespace.BUNDLE_NAMESPACE));
+            if (c == 0)
+            {
+                Version v1 = (!cap1.getAttributes().containsKey(BundleNamespace.CAPABILITY_BUNDLE_VERSION_ATTRIBUTE))
+                        ? Version.emptyVersion
+                        : (Version) cap1.getAttributes().get(BundleNamespace.CAPABILITY_BUNDLE_VERSION_ATTRIBUTE);
+                Version v2 = (!cap2.getAttributes().containsKey(BundleNamespace.CAPABILITY_BUNDLE_VERSION_ATTRIBUTE))
+                        ? Version.emptyVersion
+                        : (Version) cap2.getAttributes().get(BundleNamespace.CAPABILITY_BUNDLE_VERSION_ATTRIBUTE);
+                // Compare these in reverse order, since we want
+                // highest version to have priority.
+                c = compareVersions(v2, v1);
+            }
+        }
+        // Compare package capabilities.
+        else if ((c == 0) && cap1.getNamespace().equals(PackageNamespace.PACKAGE_NAMESPACE))
+        {
+            c = ((Comparable) cap1.getAttributes().get(PackageNamespace.PACKAGE_NAMESPACE))
+                    .compareTo(cap2.getAttributes().get(PackageNamespace.PACKAGE_NAMESPACE));
+            if (c == 0)
+            {
+                Version v1 = (!cap1.getAttributes().containsKey(PackageNamespace.CAPABILITY_VERSION_ATTRIBUTE))
+                        ? Version.emptyVersion
+                        : (Version) cap1.getAttributes().get(PackageNamespace.CAPABILITY_VERSION_ATTRIBUTE);
+                Version v2 = (!cap2.getAttributes().containsKey(PackageNamespace.CAPABILITY_VERSION_ATTRIBUTE))
+                        ? Version.emptyVersion
+                        : (Version) cap2.getAttributes().get(PackageNamespace.CAPABILITY_VERSION_ATTRIBUTE);
+                // Compare these in reverse order, since we want
+                // highest version to have priority.
+                c = compareVersions(v2, v1);
+                // if same version, rather compare on the bundle version
+                if (c == 0)
+                {
+                    v1 = (!cap1.getAttributes().containsKey(BundleNamespace.CAPABILITY_BUNDLE_VERSION_ATTRIBUTE))
+                            ? Version.emptyVersion
+                            : (Version) cap1.getAttributes().get(BundleNamespace.CAPABILITY_BUNDLE_VERSION_ATTRIBUTE);
+                    v2 = (!cap2.getAttributes().containsKey(BundleNamespace.CAPABILITY_BUNDLE_VERSION_ATTRIBUTE))
+                            ? Version.emptyVersion
+                            : (Version) cap2.getAttributes().get(BundleNamespace.CAPABILITY_BUNDLE_VERSION_ATTRIBUTE);
+                    // Compare these in reverse order, since we want
+                    // highest version to have priority.
+                    c = compareVersions(v2, v1);
+                }
+            }
+        }
+        // Compare feature capabilities
+        else if ((c == 0) && cap1.getNamespace().equals(FeatureNamespace.FEATURE_NAMESPACE))
+        {
+            c = ((Comparable) cap1.getAttributes().get(FeatureNamespace.FEATURE_NAMESPACE))
+                    .compareTo(cap2.getAttributes().get(FeatureNamespace.FEATURE_NAMESPACE));
+            if (c == 0)
+            {
+                Version v1 = (!cap1.getAttributes().containsKey(FeatureNamespace.CAPABILITY_VERSION_ATTRIBUTE))
+                        ? Version.emptyVersion
+                        : (Version) cap1.getAttributes().get(FeatureNamespace.CAPABILITY_VERSION_ATTRIBUTE);
+                Version v2 = (!cap2.getAttributes().containsKey(FeatureNamespace.CAPABILITY_VERSION_ATTRIBUTE))
+                        ? Version.emptyVersion
+                        : (Version) cap2.getAttributes().get(FeatureNamespace.CAPABILITY_VERSION_ATTRIBUTE);
+                // Compare these in reverse order, since we want
+                // highest version to have priority.
+                c = compareVersions(v2, v1);
+            }
+        }
+        return c;
+    }
+
+    private int compareVersions(Version v1, Version v2) {
+        int c = v1.getMajor() - v2.getMajor();
+        if (c != 0) {
+            return c;
+        }
+        c = v1.getMinor() - v2.getMinor();
+        if (c != 0) {
+            return c;
+        }
+        c = v1.getMicro() - v2.getMicro();
+        if (c != 0) {
+            return c;
+        }
+        String q1 = cleanQualifierForComparison(v1.getQualifier());
+        String q2 = cleanQualifierForComparison(v2.getQualifier());
+        return q1.compareTo(q2);
+    }
+
+    private String cleanQualifierForComparison(String qualifier) {
+        return qualifier.replaceAll("(redhat-[0-9]{3})([0-9]{3})", "$1-$2");
+    }
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/src/main/java/org/apache/karaf/features/internal/resolver/CapabilityImpl.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/resolver/CapabilityImpl.java b/features/src/main/java/org/apache/karaf/features/internal/resolver/CapabilityImpl.java
new file mode 100644
index 0000000..bfe9b40
--- /dev/null
+++ b/features/src/main/java/org/apache/karaf/features/internal/resolver/CapabilityImpl.java
@@ -0,0 +1,165 @@
+/*
+ * 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.karaf.features.internal.resolver;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.StringTokenizer;
+
+import org.osgi.framework.Constants;
+import org.osgi.resource.Capability;
+import org.osgi.resource.Resource;
+
+public class CapabilityImpl extends BaseClause implements Capability {
+
+    private final Resource m_resource;
+    private final String m_namespace;
+    private final Map<String, String> m_dirs;
+    private final Map<String, Object> m_attrs;
+    private final List<String> m_uses;
+    private final List<List<String>> m_includeFilter;
+    private final List<List<String>> m_excludeFilter;
+    private final Set<String> m_mandatory;
+
+    public CapabilityImpl(Capability capability) {
+        this(null, capability.getNamespace(), capability.getDirectives(), capability.getAttributes());
+    }
+
+    public CapabilityImpl(Resource resource, String namespace,
+                          Map<String, String> dirs, Map<String, Object> attrs) {
+        m_namespace = namespace;
+        m_resource = resource;
+        m_dirs = dirs;
+        m_attrs = attrs;
+
+        // Find all export directives: uses, mandatory, include, and exclude.
+
+        List<String> uses = Collections.emptyList();
+        String value = m_dirs.get(Constants.USES_DIRECTIVE);
+        if (value != null) {
+            // Parse these uses directive.
+            StringTokenizer tok = new StringTokenizer(value, ",");
+            uses = new ArrayList<String>(tok.countTokens());
+            while (tok.hasMoreTokens()) {
+                uses.add(tok.nextToken().trim());
+            }
+        }
+        m_uses = uses;
+
+        value = m_dirs.get(Constants.INCLUDE_DIRECTIVE);
+        if (value != null) {
+            List<String> filters = ResourceBuilder.parseDelimitedString(value, ",");
+            m_includeFilter = new ArrayList<List<String>>(filters.size());
+            for (String filter : filters) {
+                List<String> substrings = SimpleFilter.parseSubstring(filter);
+                m_includeFilter.add(substrings);
+            }
+        } else {
+            m_includeFilter = null;
+        }
+
+        value = m_dirs.get(Constants.EXCLUDE_DIRECTIVE);
+        if (value != null) {
+            List<String> filters = ResourceBuilder.parseDelimitedString(value, ",");
+            m_excludeFilter = new ArrayList<List<String>>(filters.size());
+            for (String filter : filters) {
+                List<String> substrings = SimpleFilter.parseSubstring(filter);
+                m_excludeFilter.add(substrings);
+            }
+        } else {
+            m_excludeFilter = null;
+        }
+
+        Set<String> mandatory = Collections.emptySet();
+        value = m_dirs.get(Constants.MANDATORY_DIRECTIVE);
+        if (value != null) {
+            List<String> names = ResourceBuilder.parseDelimitedString(value, ",");
+            mandatory = new HashSet<String>(names.size());
+            for (String name : names) {
+                // If attribute exists, then record it as mandatory.
+                if (m_attrs.containsKey(name)) {
+                    mandatory.add(name);
+                }
+                // Otherwise, report an error.
+                else {
+                    throw new IllegalArgumentException("Mandatory attribute '" + name + "' does not exist.");
+                }
+            }
+        }
+        m_mandatory = mandatory;
+    }
+
+    public Resource getResource() {
+        return m_resource;
+    }
+
+    public String getNamespace() {
+        return m_namespace;
+    }
+
+    public Map<String, String> getDirectives() {
+        return m_dirs;
+    }
+
+    public Map<String, Object> getAttributes() {
+        return m_attrs;
+    }
+
+    public boolean isAttributeMandatory(String name) {
+        return !m_mandatory.isEmpty() && m_mandatory.contains(name);
+    }
+
+    public List<String> getUses() {
+        return m_uses;
+    }
+
+    public boolean isIncluded(String name) {
+        if ((m_includeFilter == null) && (m_excludeFilter == null)) {
+            return true;
+        }
+
+        // Get the class name portion of the target class.
+        String className = getClassName(name);
+
+        // If there are no include filters then all classes are included
+        // by default, otherwise try to find one match.
+        boolean included = (m_includeFilter == null);
+        for (int i = 0; !included && m_includeFilter != null && i < m_includeFilter.size(); i++) {
+            included = SimpleFilter.compareSubstring(m_includeFilter.get(i), className);
+        }
+
+        // If there are no exclude filters then no classes are excluded
+        // by default, otherwise try to find one match.
+        boolean excluded = false;
+        for (int i = 0; (!excluded) && (m_excludeFilter != null) && (i < m_excludeFilter.size()); i++) {
+            excluded = SimpleFilter.compareSubstring(m_excludeFilter.get(i), className);
+        }
+        return included && !excluded;
+    }
+
+    private static String getClassName(String className) {
+        if (className == null) {
+            className = "";
+        }
+        return (className.lastIndexOf('.') < 0) ? "" : className.substring(className.lastIndexOf('.') + 1);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/src/main/java/org/apache/karaf/features/internal/resolver/CapabilitySet.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/resolver/CapabilitySet.java b/features/src/main/java/org/apache/karaf/features/internal/resolver/CapabilitySet.java
new file mode 100644
index 0000000..4c5656d
--- /dev/null
+++ b/features/src/main/java/org/apache/karaf/features/internal/resolver/CapabilitySet.java
@@ -0,0 +1,612 @@
+/*
+ * 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.karaf.features.internal.resolver;
+
+import java.lang.reflect.Array;
+import java.lang.reflect.Constructor;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.TreeMap;
+
+import org.osgi.framework.Constants;
+import org.osgi.resource.Capability;
+
+public class CapabilitySet
+{
+    private final Map<String, Map<Object, Set<Capability>>> m_indices;
+    private final Set<Capability> m_capSet = new HashSet<Capability>();
+
+public void dump()
+{
+    for (Entry<String, Map<Object, Set<Capability>>> entry : m_indices.entrySet())
+    {
+        boolean header1 = false;
+        for (Entry<Object, Set<Capability>> entry2 : entry.getValue().entrySet())
+        {
+            boolean header2 = false;
+            for (Capability cap : entry2.getValue())
+            {
+                if (!header1)
+                {
+                    System.out.println(entry.getKey() + ":");
+                    header1 = true;
+                }
+                if (!header2)
+                {
+                    System.out.println("   " + entry2.getKey());
+                    header2 = true;
+                }
+                System.out.println("      " + cap);
+            }
+        }
+    }
+}
+
+    public CapabilitySet(List<String> indexProps)
+    {
+        m_indices = new TreeMap<String, Map<Object, Set<Capability>>>();
+        for (int i = 0; (indexProps != null) && (i < indexProps.size()); i++)
+        {
+            m_indices.put(
+                indexProps.get(i), new HashMap<Object, Set<Capability>>());
+        }
+    }
+
+    public void addCapability(Capability cap)
+    {
+        m_capSet.add(cap);
+
+        // Index capability.
+        for (Entry<String, Map<Object, Set<Capability>>> entry : m_indices.entrySet())
+        {
+            Object value = cap.getAttributes().get(entry.getKey());
+            if (value != null)
+            {
+                if (value.getClass().isArray())
+                {
+                    value = convertArrayToList(value);
+                }
+
+                Map<Object, Set<Capability>> index = entry.getValue();
+
+                if (value instanceof Collection)
+                {
+                    Collection c = (Collection) value;
+                    for (Object o : c)
+                    {
+                        indexCapability(index, cap, o);
+                    }
+                }
+                else
+                {
+                    indexCapability(index, cap, value);
+                }
+            }
+        }
+    }
+
+    private void indexCapability(
+        Map<Object, Set<Capability>> index, Capability cap, Object capValue)
+    {
+        Set<Capability> caps = index.get(capValue);
+        if (caps == null)
+        {
+            caps = new HashSet<Capability>();
+            index.put(capValue, caps);
+        }
+        caps.add(cap);
+    }
+
+    public void removeCapability(Capability cap)
+    {
+        if (m_capSet.remove(cap))
+        {
+            for (Entry<String, Map<Object, Set<Capability>>> entry : m_indices.entrySet())
+            {
+                Object value = cap.getAttributes().get(entry.getKey());
+                if (value != null)
+                {
+                    if (value.getClass().isArray())
+                    {
+                        value = convertArrayToList(value);
+                    }
+
+                    Map<Object, Set<Capability>> index = entry.getValue();
+
+                    if (value instanceof Collection)
+                    {
+                        Collection c = (Collection) value;
+                        for (Object o : c)
+                        {
+                            deindexCapability(index, cap, o);
+                        }
+                    }
+                    else
+                    {
+                        deindexCapability(index, cap, value);
+                    }
+                }
+            }
+        }
+    }
+
+    private void deindexCapability(
+        Map<Object, Set<Capability>> index, Capability cap, Object value)
+    {
+        Set<Capability> caps = index.get(value);
+        if (caps != null)
+        {
+            caps.remove(cap);
+            if (caps.isEmpty())
+            {
+                index.remove(value);
+            }
+        }
+    }
+
+    public Set<Capability> match(SimpleFilter sf, boolean obeyMandatory)
+    {
+        Set<Capability> matches = match(m_capSet, sf);
+        return (obeyMandatory)
+            ? matchMandatory(matches, sf)
+            : matches;
+    }
+
+    private Set<Capability> match(Set<Capability> caps, SimpleFilter sf)
+    {
+        Set<Capability> matches = new HashSet<Capability>();
+
+        if (sf.getOperation() == SimpleFilter.MATCH_ALL)
+        {
+            matches.addAll(caps);
+        }
+        else if (sf.getOperation() == SimpleFilter.AND)
+        {
+            // Evaluate each subfilter against the remaining capabilities.
+            // For AND we calculate the intersection of each subfilter.
+            // We can short-circuit the AND operation if there are no
+            // remaining capabilities.
+            List<SimpleFilter> sfs = (List<SimpleFilter>) sf.getValue();
+            for (int i = 0; (caps.size() > 0) && (i < sfs.size()); i++)
+            {
+                matches = match(caps, sfs.get(i));
+                caps = matches;
+            }
+        }
+        else if (sf.getOperation() == SimpleFilter.OR)
+        {
+            // Evaluate each subfilter against the remaining capabilities.
+            // For OR we calculate the union of each subfilter.
+            List<SimpleFilter> sfs = (List<SimpleFilter>) sf.getValue();
+            for (int i = 0; i < sfs.size(); i++)
+            {
+                matches.addAll(match(caps, sfs.get(i)));
+            }
+        }
+        else if (sf.getOperation() == SimpleFilter.NOT)
+        {
+            // Evaluate each subfilter against the remaining capabilities.
+            // For OR we calculate the union of each subfilter.
+            matches.addAll(caps);
+            List<SimpleFilter> sfs = (List<SimpleFilter>) sf.getValue();
+            for (int i = 0; i < sfs.size(); i++)
+            {
+                matches.removeAll(match(caps, sfs.get(i)));
+            }
+        }
+        else
+        {
+            Map<Object, Set<Capability>> index = m_indices.get(sf.getName());
+            if ((sf.getOperation() == SimpleFilter.EQ) && (index != null))
+            {
+                Set<Capability> existingCaps = index.get(sf.getValue());
+                if (existingCaps != null)
+                {
+                    matches.addAll(existingCaps);
+                    matches.retainAll(caps);
+                }
+            }
+            else
+            {
+                for (Iterator<Capability> it = caps.iterator(); it.hasNext(); )
+                {
+                    Capability cap = it.next();
+                    Object lhs = cap.getAttributes().get(sf.getName());
+                    if (lhs != null)
+                    {
+                        if (compare(lhs, sf.getValue(), sf.getOperation()))
+                        {
+                            matches.add(cap);
+                        }
+                    }
+                }
+            }
+        }
+
+        return matches;
+    }
+
+    public static boolean matches(Capability cap, SimpleFilter sf)
+    {
+        return matchesInternal(cap, sf) && matchMandatory(cap, sf);
+    }
+
+    private static boolean matchesInternal(Capability cap, SimpleFilter sf)
+    {
+        boolean matched = true;
+
+        if (sf.getOperation() == SimpleFilter.MATCH_ALL)
+        {
+            matched = true;
+        }
+        else if (sf.getOperation() == SimpleFilter.AND)
+        {
+            // Evaluate each subfilter against the remaining capabilities.
+            // For AND we calculate the intersection of each subfilter.
+            // We can short-circuit the AND operation if there are no
+            // remaining capabilities.
+            List<SimpleFilter> sfs = (List<SimpleFilter>) sf.getValue();
+            for (int i = 0; matched && (i < sfs.size()); i++)
+            {
+                matched = matchesInternal(cap, sfs.get(i));
+            }
+        }
+        else if (sf.getOperation() == SimpleFilter.OR)
+        {
+            // Evaluate each subfilter against the remaining capabilities.
+            // For OR we calculate the union of each subfilter.
+            matched = false;
+            List<SimpleFilter> sfs = (List<SimpleFilter>) sf.getValue();
+            for (int i = 0; !matched && (i < sfs.size()); i++)
+            {
+                matched = matchesInternal(cap, sfs.get(i));
+            }
+        }
+        else if (sf.getOperation() == SimpleFilter.NOT)
+        {
+            // Evaluate each subfilter against the remaining capabilities.
+            // For OR we calculate the union of each subfilter.
+            List<SimpleFilter> sfs = (List<SimpleFilter>) sf.getValue();
+            for (int i = 0; i < sfs.size(); i++)
+            {
+                matched = !(matchesInternal(cap, sfs.get(i)));
+            }
+        }
+        else
+        {
+            matched = false;
+            Object lhs = cap.getAttributes().get(sf.getName());
+            if (lhs != null)
+            {
+                matched = compare(lhs, sf.getValue(), sf.getOperation());
+            }
+        }
+
+        return matched;
+    }
+
+    private static Set<Capability> matchMandatory(
+        Set<Capability> caps, SimpleFilter sf)
+    {
+        for (Iterator<Capability> it = caps.iterator(); it.hasNext(); )
+        {
+            Capability cap = it.next();
+            if (!matchMandatory(cap, sf))
+            {
+                it.remove();
+            }
+        }
+        return caps;
+    }
+
+    private static boolean matchMandatory(Capability cap, SimpleFilter sf)
+    {
+        if (cap instanceof CapabilityImpl) {
+            for (Entry<String, Object> entry : cap.getAttributes().entrySet())
+            {
+                if (((CapabilityImpl) cap).isAttributeMandatory(entry.getKey())
+                    && !matchMandatoryAttribute(entry.getKey(), sf))
+                {
+                    return false;
+                }
+            }
+        } else {
+            String value = cap.getDirectives().get(Constants.MANDATORY_DIRECTIVE);
+            if (value != null) {
+                List<String> names = ResourceBuilder.parseDelimitedString(value, ",");
+                for (Entry<String, Object> entry : cap.getAttributes().entrySet())
+                {
+                    if (names.contains(entry.getKey())
+                            && !matchMandatoryAttribute(entry.getKey(), sf))
+                    {
+                        return false;
+                    }
+                }
+            }
+
+        }
+        return true;
+    }
+
+    private static boolean matchMandatoryAttribute(String attrName, SimpleFilter sf)
+    {
+        if ((sf.getName() != null) && sf.getName().equals(attrName))
+        {
+            return true;
+        }
+        else if (sf.getOperation() == SimpleFilter.AND)
+        {
+            List list = (List) sf.getValue();
+            for (int i = 0; i < list.size(); i++)
+            {
+                SimpleFilter sf2 = (SimpleFilter) list.get(i);
+                if ((sf2.getName() != null)
+                    && sf2.getName().equals(attrName))
+                {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    private static final Class<?>[] STRING_CLASS = new Class[] { String.class };
+
+    private static boolean compare(Object lhs, Object rhsUnknown, int op)
+    {
+        if (lhs == null)
+        {
+            return false;
+        }
+
+        // If this is a PRESENT operation, then just return true immediately
+        // since we wouldn't be here if the attribute wasn't present.
+        if (op == SimpleFilter.PRESENT)
+        {
+            return true;
+        }
+
+        // If the type is comparable, then we can just return the
+        // result immediately.
+        if (lhs instanceof Comparable)
+        {
+            // Spec says SUBSTRING is false for all types other than string.
+            if ((op == SimpleFilter.SUBSTRING) && !(lhs instanceof String))
+            {
+                return false;
+            }
+
+            Object rhs;
+            if (op == SimpleFilter.SUBSTRING)
+            {
+                rhs = rhsUnknown;
+            }
+            else
+            {
+                try
+                {
+                    rhs = coerceType(lhs, (String) rhsUnknown);
+                }
+                catch (Exception ex)
+                {
+                    return false;
+                }
+            }
+
+            switch (op)
+            {
+                case SimpleFilter.EQ :
+                    try
+                    {
+                        return (((Comparable) lhs).compareTo(rhs) == 0);
+                    }
+                    catch (Exception ex)
+                    {
+                        return false;
+                    }
+                case SimpleFilter.GTE :
+                    try
+                    {
+                        return (((Comparable) lhs).compareTo(rhs) >= 0);
+                    }
+                    catch (Exception ex)
+                    {
+                        return false;
+                    }
+                case SimpleFilter.LTE :
+                    try
+                    {
+                        return (((Comparable) lhs).compareTo(rhs) <= 0);
+                    }
+                    catch (Exception ex)
+                    {
+                        return false;
+                    }
+                case SimpleFilter.APPROX :
+                    return compareApproximate(((Comparable) lhs), rhs);
+                case SimpleFilter.SUBSTRING :
+                    return SimpleFilter.compareSubstring((List<String>) rhs, (String) lhs);
+                default:
+                    throw new RuntimeException(
+                        "Unknown comparison operator: " + op);
+            }
+        }
+        // Booleans do not implement comparable, so special case them.
+        else if (lhs instanceof Boolean)
+        {
+            Object rhs;
+            try
+            {
+                rhs = coerceType(lhs, (String) rhsUnknown);
+            }
+            catch (Exception ex)
+            {
+                return false;
+            }
+
+            switch (op)
+            {
+                case SimpleFilter.EQ :
+                case SimpleFilter.GTE :
+                case SimpleFilter.LTE :
+                case SimpleFilter.APPROX :
+                    return (lhs.equals(rhs));
+                default:
+                    throw new RuntimeException(
+                        "Unknown comparison operator: " + op);
+            }
+        }
+
+        // If the LHS is not a comparable or boolean, check if it is an
+        // array. If so, convert it to a list so we can treat it as a
+        // collection.
+        if (lhs.getClass().isArray())
+        {
+            lhs = convertArrayToList(lhs);
+        }
+
+        // If LHS is a collection, then call compare() on each element
+        // of the collection until a match is found.
+        if (lhs instanceof Collection)
+        {
+            for (Iterator iter = ((Collection) lhs).iterator(); iter.hasNext(); )
+            {
+                if (compare(iter.next(), rhsUnknown, op))
+                {
+                    return true;
+                }
+            }
+
+            return false;
+        }
+
+        // Spec says SUBSTRING is false for all types other than string.
+        if ((op == SimpleFilter.SUBSTRING) && !(lhs instanceof String))
+        {
+            return false;
+        }
+
+        // Since we cannot identify the LHS type, then we can only perform
+        // equality comparison.
+        try
+        {
+            return lhs.equals(coerceType(lhs, (String) rhsUnknown));
+        }
+        catch (Exception ex)
+        {
+            return false;
+        }
+    }
+
+    private static boolean compareApproximate(Object lhs, Object rhs)
+    {
+        if (rhs instanceof String)
+        {
+            return removeWhitespace((String) lhs)
+                .equalsIgnoreCase(removeWhitespace((String) rhs));
+        }
+        else if (rhs instanceof Character)
+        {
+            return Character.toLowerCase(((Character) lhs))
+                == Character.toLowerCase(((Character) rhs));
+        }
+        return lhs.equals(rhs);
+    }
+
+    private static String removeWhitespace(String s)
+    {
+        StringBuffer sb = new StringBuffer(s.length());
+        for (int i = 0; i < s.length(); i++)
+        {
+            if (!Character.isWhitespace(s.charAt(i)))
+            {
+                sb.append(s.charAt(i));
+            }
+        }
+        return sb.toString();
+    }
+
+    private static Object coerceType(Object lhs, String rhsString) throws Exception
+    {
+        // If the LHS expects a string, then we can just return
+        // the RHS since it is a string.
+        if (lhs.getClass() == rhsString.getClass())
+        {
+            return rhsString;
+        }
+
+        // Try to convert the RHS type to the LHS type by using
+        // the string constructor of the LHS class, if it has one.
+        Object rhs = null;
+        try
+        {
+            // The Character class is a special case, since its constructor
+            // does not take a string, so handle it separately.
+            if (lhs instanceof Character)
+            {
+                rhs = new Character(rhsString.charAt(0));
+            }
+            else
+            {
+                // Spec says we should trim number types.
+                if ((lhs instanceof Number) || (lhs instanceof Boolean))
+                {
+                    rhsString = rhsString.trim();
+                }
+                Constructor ctor = lhs.getClass().getConstructor(STRING_CLASS);
+                ctor.setAccessible(true);
+                rhs = ctor.newInstance(new Object[] { rhsString });
+            }
+        }
+        catch (Exception ex)
+        {
+            throw new Exception(
+                "Could not instantiate class "
+                    + lhs.getClass().getName()
+                    + " from string constructor with argument '"
+                    + rhsString + "' because " + ex);
+        }
+
+        return rhs;
+    }
+
+    /**
+     * This is an ugly utility method to convert an array of primitives
+     * to an array of primitive wrapper objects. This method simplifies
+     * processing LDAP filters since the special case of primitive arrays
+     * can be ignored.
+     * @param array An array of primitive types.
+     * @return An corresponding array using pritive wrapper objects.
+    **/
+    private static List convertArrayToList(Object array)
+    {
+        int len = Array.getLength(array);
+        List list = new ArrayList(len);
+        for (int i = 0; i < len; i++)
+        {
+            list.add(Array.get(array, i));
+        }
+        return list;
+    }
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/src/main/java/org/apache/karaf/features/internal/resolver/FeatureNamespace.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/resolver/FeatureNamespace.java b/features/src/main/java/org/apache/karaf/features/internal/resolver/FeatureNamespace.java
new file mode 100644
index 0000000..e211618
--- /dev/null
+++ b/features/src/main/java/org/apache/karaf/features/internal/resolver/FeatureNamespace.java
@@ -0,0 +1,72 @@
+/*
+ * 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.karaf.features.internal.resolver;
+
+import java.util.List;
+
+import org.osgi.framework.Version;
+import org.osgi.resource.Capability;
+import org.osgi.resource.Namespace;
+import org.osgi.resource.Resource;
+
+/**
+ */
+public final class FeatureNamespace extends Namespace {
+
+    public static final String FEATURE_NAMESPACE = "karaf.feature";
+
+    public static final String	CAPABILITY_VERSION_ATTRIBUTE	= "version";
+
+    /**
+     * The attribute value identifying the resource
+     * {@link org.osgi.framework.namespace.IdentityNamespace#CAPABILITY_TYPE_ATTRIBUTE type} as an OSGi bundle.
+     *
+     * @see org.osgi.framework.namespace.IdentityNamespace#CAPABILITY_TYPE_ATTRIBUTE
+     */
+    public static final String	TYPE_FEATURE = "karaf.feature";
+
+    public static String getName(Resource resource)
+    {
+        List<Capability> caps = resource.getCapabilities(null);
+        for (Capability cap : caps)
+        {
+            if (cap.getNamespace().equals(FEATURE_NAMESPACE))
+            {
+                return cap.getAttributes().get(FEATURE_NAMESPACE).toString();
+            }
+        }
+        return null;
+    }
+
+    public static Version getVersion(Resource resource)
+    {
+        List<Capability> caps = resource.getCapabilities(null);
+        for (Capability cap : caps)
+        {
+            if (cap.getNamespace().equals(FEATURE_NAMESPACE))
+            {
+                return (Version)
+                        cap.getAttributes().get(CAPABILITY_VERSION_ATTRIBUTE);
+            }
+        }
+        return null;
+    }
+
+
+    private FeatureNamespace() {
+    }
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/src/main/java/org/apache/karaf/features/internal/resolver/FeatureResource.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/resolver/FeatureResource.java b/features/src/main/java/org/apache/karaf/features/internal/resolver/FeatureResource.java
new file mode 100644
index 0000000..88f08ae
--- /dev/null
+++ b/features/src/main/java/org/apache/karaf/features/internal/resolver/FeatureResource.java
@@ -0,0 +1,121 @@
+/*
+ * 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.karaf.features.internal.resolver;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.felix.utils.version.VersionRange;
+import org.apache.felix.utils.version.VersionTable;
+import org.apache.karaf.features.BundleInfo;
+import org.apache.karaf.features.Conditional;
+import org.apache.karaf.features.Dependency;
+import org.apache.karaf.features.Feature;
+import org.apache.karaf.features.internal.util.Macro;
+import org.osgi.framework.BundleException;
+import org.osgi.framework.Constants;
+import org.osgi.framework.Version;
+import org.osgi.framework.namespace.IdentityNamespace;
+import org.osgi.resource.Capability;
+import org.osgi.resource.Requirement;
+import org.osgi.resource.Resource;
+
+/**
+*/
+public class FeatureResource extends ResourceImpl {
+
+    private final Feature feature;
+
+    public static Resource build(Feature feature, Conditional conditional, String featureRange, Map<String, Resource> locToRes) throws BundleException {
+        Feature fcond = conditional.asFeature(feature.getName(), feature.getVersion());
+        FeatureResource resource = (FeatureResource) build(fcond, featureRange, locToRes);
+        for (Dependency dep : conditional.getCondition()) {
+            addDependency(resource, dep, featureRange);
+        }
+        org.apache.karaf.features.internal.model.Dependency dep = new org.apache.karaf.features.internal.model.Dependency();
+        dep.setName(feature.getName());
+        dep.setVersion(feature.getVersion());
+        addDependency(resource, dep, featureRange);
+        return resource;
+    }
+
+    public static Resource build(Feature feature, String featureRange, Map<String, Resource> locToRes) throws BundleException {
+        FeatureResource resource = new FeatureResource(feature);
+        Map<String, String> dirs = new HashMap<String, String>();
+        Map<String, Object> attrs = new HashMap<String, Object>();
+        attrs.put(FeatureNamespace.FEATURE_NAMESPACE, feature.getName());
+        attrs.put(FeatureNamespace.CAPABILITY_VERSION_ATTRIBUTE, VersionTable.getVersion(feature.getVersion()));
+        resource.addCapability(new CapabilityImpl(resource, FeatureNamespace.FEATURE_NAMESPACE, dirs, attrs));
+        for (BundleInfo info : feature.getBundles()) {
+            if (!info.isDependency()) {
+                Resource res = locToRes.get(info.getLocation());
+                if (res == null) {
+                    throw new IllegalStateException("Resource not found for url " + info.getLocation());
+                }
+                List<Capability> caps = res.getCapabilities(IdentityNamespace.IDENTITY_NAMESPACE);
+                if (caps.size() != 1) {
+                    throw new IllegalStateException("Resource does not have a single " + IdentityNamespace.IDENTITY_NAMESPACE + " capability");
+                }
+                dirs = new HashMap<String, String>();
+                attrs = new HashMap<String, Object>();
+                attrs.put(IdentityNamespace.IDENTITY_NAMESPACE, caps.get(0).getAttributes().get(IdentityNamespace.IDENTITY_NAMESPACE));
+                attrs.put(IdentityNamespace.CAPABILITY_TYPE_ATTRIBUTE, caps.get(0).getAttributes().get(IdentityNamespace.CAPABILITY_TYPE_ATTRIBUTE));
+                attrs.put(IdentityNamespace.CAPABILITY_VERSION_ATTRIBUTE, new VersionRange((Version) caps.get(0).getAttributes().get(IdentityNamespace.CAPABILITY_VERSION_ATTRIBUTE), true));
+                resource.addRequirement(new RequirementImpl(resource, IdentityNamespace.IDENTITY_NAMESPACE, dirs, attrs));
+            }
+        }
+        for (Dependency dep : feature.getDependencies()) {
+            addDependency(resource, dep, featureRange);
+        }
+        for (org.apache.karaf.features.Capability cap : feature.getCapabilities()) {
+            resource.addCapabilities(ResourceBuilder.parseCapability(resource, cap.getValue()));
+        }
+        for (org.apache.karaf.features.Requirement req : feature.getRequirements()) {
+            resource.addRequirements(ResourceBuilder.parseRequirement(resource, req.getValue()));
+        }
+        return resource;
+    }
+
+    protected static void addDependency(FeatureResource resource, Dependency dep, String featureRange) {
+        Map<String, String> dirs;
+        Map<String, Object> attrs;
+        String name = dep.getName();
+        String version = dep.getVersion();
+        if (version.equals("0.0.0")) {
+            version = null;
+        } else if (!version.startsWith("[") && !version.startsWith("(")) {
+            version = Macro.transform(featureRange, version);
+        }
+        dirs = new HashMap<String, String>();
+        attrs = new HashMap<String, Object>();
+        attrs.put(FeatureNamespace.FEATURE_NAMESPACE, name);
+        if (version != null) {
+            attrs.put(FeatureNamespace.CAPABILITY_VERSION_ATTRIBUTE, new VersionRange(version));
+        }
+        resource.addRequirement(new RequirementImpl(resource, FeatureNamespace.FEATURE_NAMESPACE, dirs, attrs));
+    }
+
+    public FeatureResource(Feature feature) {
+        super(feature.getName(), FeatureNamespace.TYPE_FEATURE, VersionTable.getVersion(feature.getVersion()));
+        this.feature = feature;
+    }
+
+    public Feature getFeature() {
+        return feature;
+    }
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/src/main/java/org/apache/karaf/features/internal/resolver/IdentityCapability.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/resolver/IdentityCapability.java b/features/src/main/java/org/apache/karaf/features/internal/resolver/IdentityCapability.java
new file mode 100644
index 0000000..cdc00d1
--- /dev/null
+++ b/features/src/main/java/org/apache/karaf/features/internal/resolver/IdentityCapability.java
@@ -0,0 +1,63 @@
+/*
+ * 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.karaf.features.internal.resolver;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.osgi.framework.Version;
+import org.osgi.framework.namespace.IdentityNamespace;
+import org.osgi.resource.Capability;
+import org.osgi.resource.Resource;
+
+class IdentityCapability extends BaseClause implements Capability
+{
+    private final Resource m_resource;
+    private final Map<String, String> m_dirs;
+    private final Map<String, Object> m_attrs;
+
+    public IdentityCapability(Resource resource, String name, String type, Version version)
+    {
+        m_resource = resource;
+        m_dirs = new HashMap<String, String>();
+        m_attrs = new HashMap<String, Object>();
+        m_attrs.put(IdentityNamespace.IDENTITY_NAMESPACE, name);
+        m_attrs.put(IdentityNamespace.CAPABILITY_TYPE_ATTRIBUTE, type);
+        m_attrs.put(IdentityNamespace.CAPABILITY_VERSION_ATTRIBUTE, version);
+    }
+
+    public String getNamespace()
+    {
+        return IdentityNamespace.IDENTITY_NAMESPACE;
+    }
+
+    public Map<String, String> getDirectives()
+    {
+        return m_dirs;
+    }
+
+    public Map<String, Object> getAttributes()
+    {
+        return m_attrs;
+    }
+
+    public Resource getResource()
+    {
+        return m_resource;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/src/main/java/org/apache/karaf/features/internal/resolver/RequirementImpl.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/resolver/RequirementImpl.java b/features/src/main/java/org/apache/karaf/features/internal/resolver/RequirementImpl.java
new file mode 100644
index 0000000..a4ef775
--- /dev/null
+++ b/features/src/main/java/org/apache/karaf/features/internal/resolver/RequirementImpl.java
@@ -0,0 +1,80 @@
+/*
+ * 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.karaf.features.internal.resolver;
+
+import java.util.Map;
+
+import org.osgi.framework.Constants;
+import org.osgi.resource.Capability;
+import org.osgi.resource.Requirement;
+import org.osgi.resource.Resource;
+
+public class RequirementImpl extends BaseClause implements Requirement {
+    private final Resource m_resource;
+    private final String m_namespace;
+    private final SimpleFilter m_filter;
+    private final boolean m_optional;
+    private final Map<String, String> m_dirs;
+    private final Map<String, Object> m_attrs;
+
+    public RequirementImpl(
+            Resource resource, String namespace,
+            Map<String, String> dirs, Map<String, Object> attrs, SimpleFilter filter) {
+        m_resource = resource;
+        m_namespace = namespace;
+        m_dirs = dirs;
+        m_attrs = attrs;
+        m_filter = filter;
+        // Find resolution import directives.
+        m_optional = Constants.RESOLUTION_OPTIONAL.equals(m_dirs.get(Constants.RESOLUTION_DIRECTIVE));
+    }
+
+    public RequirementImpl(
+            Resource resource, String namespace,
+            Map<String, String> dirs, Map<String, Object> attrs) {
+        this(resource, namespace, dirs, attrs, SimpleFilter.convert(attrs));
+    }
+
+    public String getNamespace() {
+        return m_namespace;
+    }
+
+    public Map<String, String> getDirectives() {
+        return m_dirs;
+    }
+
+    public Map<String, Object> getAttributes() {
+        return m_attrs;
+    }
+
+    public Resource getResource() {
+        return m_resource;
+    }
+
+    public boolean matches(Capability cap) {
+        return CapabilitySet.matches(cap, getFilter());
+    }
+
+    public boolean isOptional() {
+        return m_optional;
+    }
+
+    public SimpleFilter getFilter() {
+        return m_filter;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/src/main/java/org/apache/karaf/features/internal/resolver/ResolveContextImpl.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/resolver/ResolveContextImpl.java b/features/src/main/java/org/apache/karaf/features/internal/resolver/ResolveContextImpl.java
new file mode 100644
index 0000000..e2ff793
--- /dev/null
+++ b/features/src/main/java/org/apache/karaf/features/internal/resolver/ResolveContextImpl.java
@@ -0,0 +1,102 @@
+/*
+ * 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.karaf.features.internal.resolver;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.osgi.framework.Constants;
+import org.osgi.resource.Capability;
+import org.osgi.resource.Requirement;
+import org.osgi.resource.Resource;
+import org.osgi.resource.Wiring;
+import org.osgi.service.repository.Repository;
+import org.osgi.service.resolver.HostedCapability;
+import org.osgi.service.resolver.ResolveContext;
+
+/**
+*/
+public class ResolveContextImpl extends ResolveContext {
+
+    private final Set<Resource> mandatory;
+    private final Set<Resource> optional;
+    private final Repository repository;
+    private final Map<Resource, Wiring> wirings;
+    private final boolean resolveOptional;
+
+    private final CandidateComparator candidateComparator = new CandidateComparator();
+
+    public ResolveContextImpl(Set<Resource> mandatory,
+                              Set<Resource> optional,
+                              Repository repository,
+                              boolean resolveOptional) {
+        this.mandatory = mandatory;
+        this.optional = optional;
+        this.repository = repository;
+        this.wirings = new HashMap<Resource, Wiring>();
+        this.resolveOptional = resolveOptional;
+    }
+
+    @Override
+    public Collection<Resource> getMandatoryResources() {
+        return mandatory;
+    }
+
+    @Override
+    public Collection<Resource> getOptionalResources() {
+        return optional;
+    }
+
+    @Override
+    public List<Capability> findProviders(Requirement requirement) {
+        List<Capability> caps = new ArrayList<Capability>();
+        Map<Requirement, Collection<Capability>> resMap =
+                repository.findProviders(Collections.singleton(requirement));
+        Collection<Capability> res = resMap != null ? resMap.get(requirement) : null;
+        if (res != null) {
+            caps.addAll(res);
+        }
+        Collections.sort(caps, candidateComparator);
+        return caps;
+    }
+    @Override
+    public int insertHostedCapability(List capabilities, HostedCapability hostedCapability) {
+        for (int i=0; i < capabilities.size(); i++) {
+            Capability cap = (Capability) capabilities.get(i);
+            if (candidateComparator.compare(hostedCapability, cap) <= 0) {
+                capabilities.add(i, hostedCapability);
+                return i;
+            }
+        }
+        capabilities.add(hostedCapability);
+        return capabilities.size() - 1;
+    }
+    @Override
+    public boolean isEffective(Requirement requirement) {
+        return resolveOptional ||
+                !Constants.RESOLUTION_OPTIONAL.equals(requirement.getDirectives().get(Constants.RESOLUTION_DIRECTIVE));
+    }
+    @Override
+    public Map<Resource, Wiring> getWirings() {
+        return wirings;
+    }
+}


[42/59] [abbrv] git commit: [KARAF-2852] Merge system/core and system/command

Posted by gn...@apache.org.
[KARAF-2852] Merge system/core and system/command


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

Branch: refs/heads/master
Commit: 0a100d76c881f6bd7e63c983f624d145180f609d
Parents: 149822e
Author: Guillaume Nodet <gn...@gmail.com>
Authored: Thu Apr 10 08:57:14 2014 +0200
Committer: Guillaume Nodet <gn...@gmail.com>
Committed: Thu Apr 10 16:02:30 2014 +0200

----------------------------------------------------------------------
 .../standard/src/main/feature/feature.xml       |   1 -
 system/NOTICE                                   |  71 +++++
 system/command/NOTICE                           |  71 -----
 system/command/pom.xml                          |  87 -------
 .../karaf/system/commands/FrameworkOptions.java |  73 ------
 .../org/apache/karaf/system/commands/Name.java  |  51 ----
 .../apache/karaf/system/commands/Shutdown.java  | 104 --------
 .../karaf/system/commands/StartLevel.java       |  49 ----
 .../karaf/system/commands/SystemProperty.java   | 157 -----------
 .../apache/karaf/system/commands/Version.java   |  38 ---
 .../src/main/resources/OSGI-INF/bundle.info     |  20 --
 system/core/NOTICE                              |  71 -----
 system/core/pom.xml                             | 106 --------
 .../org/apache/karaf/system/FrameworkType.java  |  19 --
 .../org/apache/karaf/system/SystemService.java  | 130 ----------
 .../system/internal/SystemServiceImpl.java      | 238 -----------------
 .../karaf/system/internal/osgi/Activator.java   |  38 ---
 .../karaf/system/management/SystemMBean.java    | 157 -----------
 .../management/internal/SystemMBeanImpl.java    | 259 -------------------
 .../src/main/resources/OSGI-INF/bundle.info     |  16 --
 .../system/internal/SystemServiceImplTest.java  |  53 ----
 .../src/test/resources/etc/system.properties    |  22 --
 system/pom.xml                                  |  89 ++++++-
 .../org/apache/karaf/system/FrameworkType.java  |  19 ++
 .../org/apache/karaf/system/SystemService.java  | 130 ++++++++++
 .../karaf/system/commands/FrameworkOptions.java |  73 ++++++
 .../org/apache/karaf/system/commands/Name.java  |  51 ++++
 .../apache/karaf/system/commands/Shutdown.java  | 104 ++++++++
 .../karaf/system/commands/StartLevel.java       |  49 ++++
 .../karaf/system/commands/SystemProperty.java   | 157 +++++++++++
 .../apache/karaf/system/commands/Version.java   |  38 +++
 .../system/internal/SystemServiceImpl.java      | 238 +++++++++++++++++
 .../karaf/system/internal/osgi/Activator.java   |  38 +++
 .../karaf/system/management/SystemMBean.java    | 157 +++++++++++
 .../management/internal/SystemMBeanImpl.java    | 259 +++++++++++++++++++
 system/src/main/resources/OSGI-INF/bundle.info  |  16 ++
 .../system/internal/SystemServiceImplTest.java  |  53 ++++
 system/src/test/resources/etc/system.properties |  22 ++
 38 files changed, 1556 insertions(+), 1768 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/karaf/blob/0a100d76/assemblies/features/standard/src/main/feature/feature.xml
----------------------------------------------------------------------
diff --git a/assemblies/features/standard/src/main/feature/feature.xml b/assemblies/features/standard/src/main/feature/feature.xml
index 90c38db..fae3b4f 100644
--- a/assemblies/features/standard/src/main/feature/feature.xml
+++ b/assemblies/features/standard/src/main/feature/feature.xml
@@ -165,7 +165,6 @@
 
     <feature name="system" description="Provide System support" version="${project.version}">
         <bundle start-level="30" start="true">mvn:org.apache.karaf.system/org.apache.karaf.system.core/${project.version}</bundle>
-        <bundle start-level="30" start="true">mvn:org.apache.karaf.system/org.apache.karaf.system.command/${project.version}</bundle>
     </feature>
 
     <feature name="http" version="${project.version}" resolver="(obr)" description="Implementation of the OSGI HTTP Service">

http://git-wip-us.apache.org/repos/asf/karaf/blob/0a100d76/system/NOTICE
----------------------------------------------------------------------
diff --git a/system/NOTICE b/system/NOTICE
new file mode 100644
index 0000000..b70f1f9
--- /dev/null
+++ b/system/NOTICE
@@ -0,0 +1,71 @@
+Apache Karaf
+Copyright 2010-2014 The Apache Software Foundation
+
+
+I. Included Software
+
+This product includes software developed at
+The Apache Software Foundation (http://www.apache.org/).
+Licensed under the Apache License 2.0.
+
+This product uses software developed at
+The OSGi Alliance (http://www.osgi.org/).
+Copyright (c) OSGi Alliance (2000, 2010).
+Licensed under the Apache License 2.0.
+
+This product includes software developed at
+OW2 (http://www.ow2.org/).
+Licensed under the BSD License.
+
+This product includes software developed at
+OPS4J (http://www.ops4j.org/).
+Licensed under the Apache License 2.0.
+
+This product includes software developed at
+Eclipse Foundation (http://www.eclipse.org/).
+Licensed under the EPL.
+
+This product includes software written by
+Antony Lesuisse.
+Licensed under Public Domain.
+
+
+II. Used Software
+
+This product uses software developed at
+FUSE Source (http://www.fusesource.org/).
+Licensed under the Apache License 2.0.
+
+This product uses software developed at
+AOP Alliance (http://aopalliance.sourceforge.net/).
+Licensed under the Public Domain.
+
+This product uses software developed at
+Tanuki Software (http://www.tanukisoftware.com/).
+Licensed under the Apache License 2.0.
+
+This product uses software developed at
+Jasypt (http://jasypt.sourceforge.net/).
+Licensed under the Apache License 2.0.
+
+This product uses software developed at
+JLine (http://jline.sourceforge.net).
+Licensed under the BSD License.
+
+This product uses software developed at
+SLF4J (http://www.slf4j.org/).
+Licensed under the MIT License.
+
+This product uses software developed at
+SpringSource (http://www.springsource.org/).
+Licensed under the Apache License 2.0.
+
+This product includes software from http://www.json.org.
+Copyright (c) 2002 JSON.org
+
+
+III. License Summary
+- Apache License 2.0
+- BSD License
+- EPL License
+- MIT License

http://git-wip-us.apache.org/repos/asf/karaf/blob/0a100d76/system/command/NOTICE
----------------------------------------------------------------------
diff --git a/system/command/NOTICE b/system/command/NOTICE
deleted file mode 100644
index b70f1f9..0000000
--- a/system/command/NOTICE
+++ /dev/null
@@ -1,71 +0,0 @@
-Apache Karaf
-Copyright 2010-2014 The Apache Software Foundation
-
-
-I. Included Software
-
-This product includes software developed at
-The Apache Software Foundation (http://www.apache.org/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-The OSGi Alliance (http://www.osgi.org/).
-Copyright (c) OSGi Alliance (2000, 2010).
-Licensed under the Apache License 2.0.
-
-This product includes software developed at
-OW2 (http://www.ow2.org/).
-Licensed under the BSD License.
-
-This product includes software developed at
-OPS4J (http://www.ops4j.org/).
-Licensed under the Apache License 2.0.
-
-This product includes software developed at
-Eclipse Foundation (http://www.eclipse.org/).
-Licensed under the EPL.
-
-This product includes software written by
-Antony Lesuisse.
-Licensed under Public Domain.
-
-
-II. Used Software
-
-This product uses software developed at
-FUSE Source (http://www.fusesource.org/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-AOP Alliance (http://aopalliance.sourceforge.net/).
-Licensed under the Public Domain.
-
-This product uses software developed at
-Tanuki Software (http://www.tanukisoftware.com/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-Jasypt (http://jasypt.sourceforge.net/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-JLine (http://jline.sourceforge.net).
-Licensed under the BSD License.
-
-This product uses software developed at
-SLF4J (http://www.slf4j.org/).
-Licensed under the MIT License.
-
-This product uses software developed at
-SpringSource (http://www.springsource.org/).
-Licensed under the Apache License 2.0.
-
-This product includes software from http://www.json.org.
-Copyright (c) 2002 JSON.org
-
-
-III. License Summary
-- Apache License 2.0
-- BSD License
-- EPL License
-- MIT License

http://git-wip-us.apache.org/repos/asf/karaf/blob/0a100d76/system/command/pom.xml
----------------------------------------------------------------------
diff --git a/system/command/pom.xml b/system/command/pom.xml
deleted file mode 100644
index 3eeaa19..0000000
--- a/system/command/pom.xml
+++ /dev/null
@@ -1,87 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-
-    <!--
-
-        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.
-    -->
-
-    <modelVersion>4.0.0</modelVersion>
-
-    <parent>
-        <groupId>org.apache.karaf.system</groupId>
-        <artifactId>system</artifactId>
-        <version>4.0.0-SNAPSHOT</version>
-        <relativePath>../pom.xml</relativePath>
-    </parent>
-
-    <artifactId>org.apache.karaf.system.command</artifactId>
-    <packaging>bundle</packaging>
-    <name>Apache Karaf :: System :: Shell Commands</name>
-    <description>
-        This bundle provides Karaf shell commands to manipulate system service (shutdown container, etc).
-    </description>
-
-    <properties>
-        <appendedResourcesDirectory>${basedir}/../../etc/appended-resources</appendedResourcesDirectory>
-    </properties>
-
-    <dependencies>
-        <dependency>
-            <groupId>org.apache.karaf.system</groupId>
-            <artifactId>org.apache.karaf.system.core</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.karaf.shell</groupId>
-            <artifactId>org.apache.karaf.shell.core</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.osgi</groupId>
-            <artifactId>org.osgi.core</artifactId>
-            <scope>provided</scope>
-        </dependency>
-    </dependencies>
-
-    <build>
-        <resources>
-            <resource>
-                <directory>${project.basedir}/src/main/resources</directory>
-                <includes>
-                    <include>**/*</include>
-                </includes>
-            </resource>
-            <resource>
-                <directory>${project.basedir}/src/main/resources</directory>
-                <filtering>true</filtering>
-                <includes>
-                    <include>**/*.info</include>
-                </includes>
-            </resource>
-        </resources>
-        <plugins>
-            <plugin>
-                <groupId>org.apache.felix</groupId>
-                <artifactId>maven-bundle-plugin</artifactId>
-                <configuration>
-                    <instructions>
-                        <Karaf-Commands>*</Karaf-Commands>
-                    </instructions>
-                </configuration>
-            </plugin>
-        </plugins>
-    </build>
-
-</project>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/karaf/blob/0a100d76/system/command/src/main/java/org/apache/karaf/system/commands/FrameworkOptions.java
----------------------------------------------------------------------
diff --git a/system/command/src/main/java/org/apache/karaf/system/commands/FrameworkOptions.java b/system/command/src/main/java/org/apache/karaf/system/commands/FrameworkOptions.java
deleted file mode 100644
index 9e16a7d..0000000
--- a/system/command/src/main/java/org/apache/karaf/system/commands/FrameworkOptions.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * 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.karaf.system.commands;
-
-import org.apache.karaf.shell.api.action.Action;
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Option;
-import org.apache.karaf.shell.api.action.lifecycle.Reference;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.apache.karaf.system.FrameworkType;
-import org.apache.karaf.system.SystemService;
-
-/**
- * Command for enabling/disabling debug logging on the OSGi framework
- */
-@Command(scope = "system", name = "framework", description = "OSGi Framework options.")
-@Service
-public class FrameworkOptions implements Action {
-
-    @Option(name = "-debug", aliases={"--enable-debug"}, description="Enable debug for the OSGi framework", required = false, multiValued = false)
-    boolean debug;
-
-    @Option(name = "-nodebug", aliases={"--disable-debug"}, description="Disable debug for the OSGi framework", required = false, multiValued = false)
-    boolean nodebug;
-
-    @Argument(name = "framework", required = false, description = "Name of the OSGi framework to use")
-    String framework;
-
-    @Reference
-    SystemService systemService;
-
-    @Override
-    public Object execute() throws Exception {
-
-        if (!debug^nodebug && framework == null) {
-            System.out.printf("Current OSGi framework is %s%n", systemService.getFramework().name());
-            return null;
-        }
-        if (framework != null) {
-            FrameworkType frameworkType = FrameworkType.valueOf(framework);
-            systemService.setFramework(frameworkType);
-            System.out.println("Changed OSGi framework to " + frameworkType.toString().toLowerCase() + ". Karaf needs to be restarted to make the change effective");
-        }
-        if (debug) {
-            FrameworkType frameworkType = systemService.getFramework();
-            System.out.printf("Enabling debug for OSGi framework (%s)%n", frameworkType.name());
-            systemService.setFrameworkDebug(true);
-        }
-        if (nodebug) {
-            FrameworkType frameworkType = systemService.getFramework();
-            System.out.printf("Disabling debug for OSGi framework (%s)%n", frameworkType.name());
-            systemService.setFrameworkDebug(false);
-        }
-
-        return null;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/0a100d76/system/command/src/main/java/org/apache/karaf/system/commands/Name.java
----------------------------------------------------------------------
diff --git a/system/command/src/main/java/org/apache/karaf/system/commands/Name.java b/system/command/src/main/java/org/apache/karaf/system/commands/Name.java
deleted file mode 100644
index a716d82..0000000
--- a/system/command/src/main/java/org/apache/karaf/system/commands/Name.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * 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.karaf.system.commands;
-
-
-import org.apache.karaf.shell.api.action.Action;
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.lifecycle.Reference;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.apache.karaf.system.SystemService;
-
-/**
- * Command to shut down Karaf container.
- */
-@Command(scope = "system", name = "name", description = "Show or change Karaf instance name.")
-@Service
-public class Name implements Action {
-
-    @Argument(name = "name", index = 0, description = "New name for the instance", required = false, multiValued = false)
-    String name;
-
-    @Reference
-    SystemService systemService;
-
-    @Override
-    public Object execute() throws Exception {
-        if (name == null) {
-            System.out.println(systemService.getName());
-        } else {
-            systemService.setName(name);
-            System.out.println("Instance name changed to " + name + ". Restart needed for this to take effect.");
-        }
-        return null;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/0a100d76/system/command/src/main/java/org/apache/karaf/system/commands/Shutdown.java
----------------------------------------------------------------------
diff --git a/system/command/src/main/java/org/apache/karaf/system/commands/Shutdown.java b/system/command/src/main/java/org/apache/karaf/system/commands/Shutdown.java
deleted file mode 100644
index b8b4b41..0000000
--- a/system/command/src/main/java/org/apache/karaf/system/commands/Shutdown.java
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * 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.karaf.system.commands;
-
-import org.apache.karaf.shell.api.action.Action;
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Option;
-import org.apache.karaf.shell.api.action.lifecycle.Reference;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.apache.karaf.shell.api.console.Session;
-import org.apache.karaf.system.SystemService;
-
-/**
- * Command to shut down Karaf container.
- */
-@Command(scope = "system", name = "shutdown", description = "Shutdown Karaf.")
-@Service
-public class Shutdown implements Action {
-
-    @Option(name = "-f", aliases = "--force", description = "Force the shutdown without confirmation message.", required = false, multiValued = false)
-    boolean force = false;
-
-    @Option(name = "-r", aliases = "--reboot", description = "Reboot the Karaf container.", required = false, multiValued = false)
-    boolean reboot = false;
-
-    @Option(name = "-h", aliases = "--halt", description = "Halt the Karaf container.", required = false, multiValued = false)
-    boolean halt = false;
-
-    @Option(name = "-c", aliases = {"--clean", "--clean-all", "-ca"}, description = "Force a clean restart by deleting the data directory")
-    private boolean cleanAll;
-
-    @Option(name = "-cc", aliases = {"--clean-cache", "-cc"}, description = "Force a clean restart by deleting the cache directory")
-    private boolean cleanCache;
-
-
-    @Argument(name = "time", index = 0, description = "Shutdown after a specified delay. The time argument can have different" +
-            " formats. First, it can be an absolute time in the format hh:mm, in which hh is the hour (1 or 2 digits) and mm" +
-            " is the minute of the hour (in two digits). Second, it can be in the format +m, in which m is the number of minutes" +
-            " to wait. The word now is an alias for +0.", required = false, multiValued = false)
-    String time;
-
-    @Reference
-    SystemService systemService;
-
-    @Reference
-    Session session;
-
-    @Override
-    public Object execute() throws Exception {
-
-        if (force) {
-            if (reboot) {
-                systemService.reboot(time, determineSwipeType());
-            } else {
-                systemService.halt(time);
-            }
-            return null;
-        }
-
-        for (; ; ) {
-            String karafName = System.getProperty("karaf.name");
-            String msg;
-            if (reboot) {
-                msg = String.format("Confirm: reboot instance %s (yes/no): ", karafName);
-            } else {
-                msg = String.format("Confirm: halt instance %s (yes/no): ", karafName);
-            }
-            String str = session.readLine(msg, null);
-            if (str.equalsIgnoreCase("yes")) {
-                if (reboot) {
-                    systemService.reboot(time, determineSwipeType());
-                } else {
-                    systemService.halt(time);
-                }
-            }
-            return null;
-        }
-    }
-
-    private SystemService.Swipe determineSwipeType() {
-        if (cleanAll) {
-            return SystemService.Swipe.ALL;
-        } else if (cleanCache) {
-            return SystemService.Swipe.CACHE;
-        }
-        return SystemService.Swipe.NONE;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/0a100d76/system/command/src/main/java/org/apache/karaf/system/commands/StartLevel.java
----------------------------------------------------------------------
diff --git a/system/command/src/main/java/org/apache/karaf/system/commands/StartLevel.java b/system/command/src/main/java/org/apache/karaf/system/commands/StartLevel.java
deleted file mode 100644
index e91c15a..0000000
--- a/system/command/src/main/java/org/apache/karaf/system/commands/StartLevel.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * 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.karaf.system.commands;
-
-import org.apache.karaf.shell.api.action.Action;
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.lifecycle.Reference;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.apache.karaf.system.SystemService;
-
-/**
- * Get/set the system start level.
- */
-@Command(scope = "system", name = "start-level", description = "Gets or sets the system start level.")
-@Service
-public class StartLevel implements Action {
-
-    @Argument(index = 0, name = "level", description = "The new system start level to set", required = false, multiValued = false)
-    Integer level;
-
-    @Reference
-    SystemService systemService;
-
-    @Override
-    public Object execute() throws Exception {
-        if (level == null) {
-            System.out.println("Level " + systemService.getStartLevel());
-        } else {
-            systemService.setStartLevel(level);
-        }
-        return null;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/0a100d76/system/command/src/main/java/org/apache/karaf/system/commands/SystemProperty.java
----------------------------------------------------------------------
diff --git a/system/command/src/main/java/org/apache/karaf/system/commands/SystemProperty.java b/system/command/src/main/java/org/apache/karaf/system/commands/SystemProperty.java
deleted file mode 100644
index 37c2a1e..0000000
--- a/system/command/src/main/java/org/apache/karaf/system/commands/SystemProperty.java
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- * 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.karaf.system.commands;
-
-import java.io.File;
-import java.io.PrintStream;
-import java.text.SimpleDateFormat;
-import java.util.Collections;
-import java.util.Date;
-import java.util.Iterator;
-import java.util.Properties;
-import java.util.Set;
-import java.util.Vector;
-
-import org.apache.karaf.shell.api.action.Action;
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Option;
-import org.apache.karaf.shell.api.action.lifecycle.Reference;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.apache.karaf.system.SystemService;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.Constants;
-
-/**
- * Command that allow access to system properties easily.
- */
-@Command(scope = "system", name = "property", description = "Get or set a system property.")
-@Service
-public class SystemProperty implements Action {
-
-    @Option(name = "-p", aliases = {"--persistent"}, description = "Persist the new value to the etc/system.properties file")
-    boolean persistent;
-
-    @Option(name = "-f", aliases = {"--file-dump"}, description = "Dump all system properties in a file (in data folder)")
-    boolean dumpToFile;
-
-    @Option(name = "-u", aliases = {"--unset"}, description = "Show unset know properties with value unset")
-    boolean unset;
-
-    @Argument(index = 0, name = "key", required = false, description = "The system property name")
-    String key;
-
-    @Argument(index = 1, name = "value", required = false, description = "New value for the system property")
-    String value;
-
-    @Reference
-    BundleContext bundleContext;
-
-    @Reference
-    SystemService systemService;
-
-    @Override
-    public Object execute() throws Exception {
-        if (key == null && value == null) {
-            Properties props = (Properties) System.getProperties().clone();
-
-            String def = null;
-            if (unset) {
-                def = "unset";
-            }
-
-            setProperty(props, Constants.FRAMEWORK_BEGINNING_STARTLEVEL, def);
-            setProperty(props, Constants.FRAMEWORK_BOOTDELEGATION, def);
-            setProperty(props, Constants.FRAMEWORK_BUNDLE_PARENT, def);
-            setProperty(props, Constants.FRAMEWORK_BUNDLE_PARENT_APP, def);
-            setProperty(props, Constants.FRAMEWORK_BUNDLE_PARENT_BOOT, def);
-            setProperty(props, Constants.FRAMEWORK_BUNDLE_PARENT_EXT, def);
-            setProperty(props, Constants.FRAMEWORK_BUNDLE_PARENT_FRAMEWORK, def);
-            setProperty(props, Constants.FRAMEWORK_EXECPERMISSION, def);
-            setProperty(props, Constants.FRAMEWORK_EXECUTIONENVIRONMENT, def);
-            setProperty(props, Constants.FRAMEWORK_LANGUAGE, def);
-            setProperty(props, Constants.FRAMEWORK_LIBRARY_EXTENSIONS, def);
-            setProperty(props, Constants.FRAMEWORK_OS_NAME, def);
-            setProperty(props, Constants.FRAMEWORK_OS_VERSION, def);
-            setProperty(props, Constants.FRAMEWORK_PROCESSOR, def);
-            setProperty(props, Constants.FRAMEWORK_SECURITY, def);
-            setProperty(props, Constants.FRAMEWORK_SECURITY_OSGI, def);
-            setProperty(props, Constants.FRAMEWORK_STORAGE, def);
-            setProperty(props, Constants.FRAMEWORK_STORAGE_CLEAN_ONFIRSTINIT, def);
-            setProperty(props, Constants.FRAMEWORK_SYSTEMPACKAGES, def);
-            setProperty(props, Constants.FRAMEWORK_SYSTEMPACKAGES_EXTRA, def);
-            setProperty(props, Constants.FRAMEWORK_VENDOR, def);
-            setProperty(props, Constants.FRAMEWORK_VERSION, def);
-            setProperty(props, Constants.FRAMEWORK_WINDOWSYSTEM, def);
-
-            setProperty(props, Constants.SUPPORTS_BOOTCLASSPATH_EXTENSION, def);
-            setProperty(props, Constants.SUPPORTS_FRAMEWORK_EXTENSION, def);
-            setProperty(props, Constants.SUPPORTS_FRAMEWORK_FRAGMENT, def);
-            setProperty(props, Constants.SUPPORTS_FRAMEWORK_REQUIREBUNDLE, def);
-
-            if (dumpToFile) {
-                PrintStream ps = new PrintStream(
-                        new File(
-                                bundleContext.getProperty("karaf.data"),
-                                "dump-properties-" + System.currentTimeMillis() + ".properties"
-                        )
-                );
-                ps.println("#Dump of the System and OSGi properties with the command system:property");
-                ps.println("#Dump executed at " + new SimpleDateFormat().format(new Date()));
-                printOrderedProperties(props, ps);
-                ps.flush();
-                ps.close();
-            } else {
-                printOrderedProperties(props, System.out);
-            }
-
-            return null;
-        }
-
-        if (value != null) {
-            systemService.setSystemProperty(key, value, persistent);
-        } else {
-            System.out.println(System.getProperty(key));
-        }
-
-        return null;
-    }
-
-    private void printOrderedProperties(Properties props, PrintStream out) {
-        Set<Object> keys = props.keySet();
-        Vector<String> order = new Vector<String>(keys.size());
-        for (Iterator<Object> i = keys.iterator(); i.hasNext(); ) {
-            Object str = (Object) i.next();
-            order.add((String) str);
-        }
-        Collections.sort(order);
-        for (Iterator<String> i = order.iterator(); i.hasNext(); ) {
-            String key = (String) i.next();
-            out.println(key + "=" + props.getProperty(key));
-        }
-    }
-
-    private void setProperty(Properties props, String key, String def) {
-        String val = bundleContext.getProperty(key);
-        if (val == null && def != null) {
-            props.setProperty(key, def);
-        } else if (val != null) {
-            props.setProperty(key, val);
-        }
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/0a100d76/system/command/src/main/java/org/apache/karaf/system/commands/Version.java
----------------------------------------------------------------------
diff --git a/system/command/src/main/java/org/apache/karaf/system/commands/Version.java b/system/command/src/main/java/org/apache/karaf/system/commands/Version.java
deleted file mode 100644
index 9837aaa..0000000
--- a/system/command/src/main/java/org/apache/karaf/system/commands/Version.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * 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.karaf.system.commands;
-
-import org.apache.karaf.shell.api.action.Action;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.lifecycle.Reference;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.apache.karaf.system.SystemService;
-
-@Command(scope = "system", name = "version", description = "Display the instance version")
-@Service
-public class Version implements Action {
-
-    @Reference
-    SystemService systemService;
-
-    @Override
-    public Object execute() throws Exception {
-        System.out.println(systemService.getVersion());
-        return null;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/0a100d76/system/command/src/main/resources/OSGI-INF/bundle.info
----------------------------------------------------------------------
diff --git a/system/command/src/main/resources/OSGI-INF/bundle.info b/system/command/src/main/resources/OSGI-INF/bundle.info
deleted file mode 100644
index c115593..0000000
--- a/system/command/src/main/resources/OSGI-INF/bundle.info
+++ /dev/null
@@ -1,20 +0,0 @@
-h1. Synopsis
-
-${project.name}
-
-${project.description}
-
-Maven URL:
-[mvn:${project.groupId}/${project.artifactId}/${project.version}]
-
-h1. Description
-
-This bundle contains all Karaf system shell commands.
-
-The following commands are available:
-* system:shutdown - Shutdown the Karaf container.
-* syste:start-level - Gets or sets the Karaf system start level.
-
-h1. See also
-
-Shutdown Karaf - section of the Karaf User Guide.
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/karaf/blob/0a100d76/system/core/NOTICE
----------------------------------------------------------------------
diff --git a/system/core/NOTICE b/system/core/NOTICE
deleted file mode 100644
index b70f1f9..0000000
--- a/system/core/NOTICE
+++ /dev/null
@@ -1,71 +0,0 @@
-Apache Karaf
-Copyright 2010-2014 The Apache Software Foundation
-
-
-I. Included Software
-
-This product includes software developed at
-The Apache Software Foundation (http://www.apache.org/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-The OSGi Alliance (http://www.osgi.org/).
-Copyright (c) OSGi Alliance (2000, 2010).
-Licensed under the Apache License 2.0.
-
-This product includes software developed at
-OW2 (http://www.ow2.org/).
-Licensed under the BSD License.
-
-This product includes software developed at
-OPS4J (http://www.ops4j.org/).
-Licensed under the Apache License 2.0.
-
-This product includes software developed at
-Eclipse Foundation (http://www.eclipse.org/).
-Licensed under the EPL.
-
-This product includes software written by
-Antony Lesuisse.
-Licensed under Public Domain.
-
-
-II. Used Software
-
-This product uses software developed at
-FUSE Source (http://www.fusesource.org/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-AOP Alliance (http://aopalliance.sourceforge.net/).
-Licensed under the Public Domain.
-
-This product uses software developed at
-Tanuki Software (http://www.tanukisoftware.com/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-Jasypt (http://jasypt.sourceforge.net/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-JLine (http://jline.sourceforge.net).
-Licensed under the BSD License.
-
-This product uses software developed at
-SLF4J (http://www.slf4j.org/).
-Licensed under the MIT License.
-
-This product uses software developed at
-SpringSource (http://www.springsource.org/).
-Licensed under the Apache License 2.0.
-
-This product includes software from http://www.json.org.
-Copyright (c) 2002 JSON.org
-
-
-III. License Summary
-- Apache License 2.0
-- BSD License
-- EPL License
-- MIT License

http://git-wip-us.apache.org/repos/asf/karaf/blob/0a100d76/system/core/pom.xml
----------------------------------------------------------------------
diff --git a/system/core/pom.xml b/system/core/pom.xml
deleted file mode 100644
index 61c68e0..0000000
--- a/system/core/pom.xml
+++ /dev/null
@@ -1,106 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-
-    <!--
-
-        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.
-    -->
-
-    <modelVersion>4.0.0</modelVersion>
-
-    <parent>
-        <groupId>org.apache.karaf.system</groupId>
-        <artifactId>system</artifactId>
-        <version>4.0.0-SNAPSHOT</version>
-        <relativePath>../pom.xml</relativePath>
-    </parent>
-
-    <artifactId>org.apache.karaf.system.core</artifactId>
-    <packaging>bundle</packaging>
-    <name>Apache Karaf :: System :: Core</name>
-    <description>
-        This bundle provides services to manipulate the Karaf container itself (system).
-    </description>
-
-    <properties>
-        <appendedResourcesDirectory>${basedir}/../../etc/appended-resources</appendedResourcesDirectory>
-    </properties>
-
-    <dependencies>
-        <dependency>
-            <groupId>org.osgi</groupId>
-            <artifactId>org.osgi.core</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.slf4j</groupId>
-            <artifactId>slf4j-api</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.karaf</groupId>
-            <artifactId>org.apache.karaf.util</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.felix</groupId>
-            <artifactId>org.apache.felix.utils</artifactId>
-            <scope>provided</scope>
-        </dependency>
-    </dependencies>
-
-    <build>
-        <resources>
-            <resource>
-                <directory>${project.basedir}/src/main/resources</directory>
-                <includes>
-                    <include>**/*</include>
-                </includes>
-            </resource>
-            <resource>
-                <directory>${project.basedir}/src/main/resources</directory>
-                <filtering>true</filtering>
-                <includes>
-                    <include>**/*.info</include>
-                </includes>
-            </resource>
-        </resources>
-        <plugins>
-            <plugin>
-                <groupId>org.apache.felix</groupId>
-                <artifactId>maven-bundle-plugin</artifactId>
-                <configuration>
-                    <instructions>
-                        <Export-Package>
-                            org.apache.karaf.system,
-                            org.apache.karaf.system.management
-                        </Export-Package>
-                        <Private-Package>
-                            org.apache.karaf.system.internal,
-                            org.apache.karaf.system.internal.osgi,
-                            org.apache.karaf.system.management.internal,
-                            org.apache.karaf.util.tracker,
-                            org.apache.felix.utils.properties
-                        </Private-Package>
-                        <Bundle-Activator>
-                            org.apache.karaf.system.internal.osgi.Activator
-                        </Bundle-Activator>
-                    </instructions>
-                </configuration>
-            </plugin>
-        </plugins>
-    </build>
-
-</project>

http://git-wip-us.apache.org/repos/asf/karaf/blob/0a100d76/system/core/src/main/java/org/apache/karaf/system/FrameworkType.java
----------------------------------------------------------------------
diff --git a/system/core/src/main/java/org/apache/karaf/system/FrameworkType.java b/system/core/src/main/java/org/apache/karaf/system/FrameworkType.java
deleted file mode 100644
index 67720a7..0000000
--- a/system/core/src/main/java/org/apache/karaf/system/FrameworkType.java
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * 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.system;
-
-public enum FrameworkType {
-    felix,
-    equinox
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/0a100d76/system/core/src/main/java/org/apache/karaf/system/SystemService.java
----------------------------------------------------------------------
diff --git a/system/core/src/main/java/org/apache/karaf/system/SystemService.java b/system/core/src/main/java/org/apache/karaf/system/SystemService.java
deleted file mode 100644
index 2f53946..0000000
--- a/system/core/src/main/java/org/apache/karaf/system/SystemService.java
+++ /dev/null
@@ -1,130 +0,0 @@
- /*
- * 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.karaf.system;
-
-/**
- * Describe a system service
- */
-public interface SystemService {
-
-    /**
-     * Types defining what to remove on a restart of Karaf
-     */
-    public enum Swipe {
-        /** Delete nothing; simple restart */
-        NONE,
-        /** Delete only the cache; everything else remains */
-        CACHE,
-        /** Forces a clean restart by removing the working directory; this option is compatible to the former clean method. */
-        ALL
-    }
-
-    /**
-     * Halt the Karaf container.
-     */
-    void halt() throws Exception;
-
-    /**
-     * Halt the Karaf container.
-     *
-     * @param time shutdown delay. The time argument can have different formats.
-     *  First, it can be an absolute time in the format hh:mm, in which hh is the hour (1 or 2 digits) and mm
-     *  is the minute of the hour (in two digits). Second, it can be in the format +m, in which m is the number of minutes
-     *  to wait. The word now is an alias for +0.
-     */
-    void halt(String time) throws Exception;
-
-    /**
-     * Reboot the Karaf container.
-     *
-     * @throws Exception
-     */
-    void reboot() throws Exception;
-
-    /**
-     * Reboot the Karaf container.
-     *
-     * @param time reboot delay. The time argument can have different formats.
-     *  First, it can be an absolute time in the format hh:mm, in which hh is the hour (1 or 2 digits) and mm
-     *  is the minute of the hour (in two digits). Second, it can be in the format +m, in which m is the number of minutes
-     *  to wait. The word now is an alias for +0.
-     *  @param clean Force a clean restart by deleting the working directory.
-     */
-    void reboot(String time, Swipe clean) throws Exception;
-
-    /**
-     * Set the system start level.
-     *
-     * @param startLevel the new system start level.
-     */
-    void setStartLevel(int startLevel) throws Exception;
-
-    /**
-     * Get the system start level.
-     *
-     * @return the current system start level.
-     */
-    int getStartLevel() throws Exception;
-
-    /**
-     * Get the version of the current Karaf instance
-     *
-     * @return instance version
-     */
-    String getVersion();
-
-    /**
-     * Get the name of the current Karaf instance
-     *
-     * @return instance name
-     */
-    String getName();
-    
-    /**
-     * Set the name of the Karaf instance
-     *
-     * @param name new instance name
-     */
-    void setName(String name);
-    
-    /**
-     * Get the current OSGi framework in use.
-     *
-     * @return the name of the OSGi framework in use.
-     * @throws Exception
-     */
-    FrameworkType getFramework();
-    
-    /**
-     * change OSGi framework
-     *
-     * @param framework to use.
-     */
-    void setFramework(FrameworkType framework);
-    
-    /**
-     * Enable or diable debgging
-     * @param debug enable if true
-     */
-    void setFrameworkDebug(boolean debug);
-
-    /**
-     * Set a system property and persist to etc/system.properties
-     * @param key
-     */
-    String setSystemProperty(String key, String value, boolean persist);
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/0a100d76/system/core/src/main/java/org/apache/karaf/system/internal/SystemServiceImpl.java
----------------------------------------------------------------------
diff --git a/system/core/src/main/java/org/apache/karaf/system/internal/SystemServiceImpl.java b/system/core/src/main/java/org/apache/karaf/system/internal/SystemServiceImpl.java
deleted file mode 100644
index 8fa5a38..0000000
--- a/system/core/src/main/java/org/apache/karaf/system/internal/SystemServiceImpl.java
+++ /dev/null
@@ -1,238 +0,0 @@
-/*
-* 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.karaf.system.internal;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.util.Calendar;
-import java.util.GregorianCalendar;
-
-import org.apache.felix.utils.properties.Properties;
-import org.apache.karaf.system.FrameworkType;
-import org.apache.karaf.system.SystemService;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.startlevel.FrameworkStartLevel;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Implementation of the system service.
- */
-public class SystemServiceImpl implements SystemService {
-
-    private static final Logger LOGGER = LoggerFactory.getLogger(SystemServiceImpl.class);
-
-    private BundleContext bundleContext;
-
-    public void setBundleContext(BundleContext bundleContext) {
-        this.bundleContext = bundleContext;
-    }
-
-    public BundleContext getBundleContext() {
-        return this.bundleContext;
-    }
-
-    public void halt() throws Exception {
-        halt(null);
-    }
-
-    public void halt(String time) throws Exception {
-        shutdown(timeToSleep(time));
-    }
-
-    public void reboot() throws Exception {
-        reboot(null, Swipe.NONE);
-    }
-
-    public void reboot(String time, Swipe cleanup) throws Exception {
-        reboot(timeToSleep(time), cleanup);
-    }
-
-    private void shutdown(final long sleep) {
-        new Thread() {
-            public void run() {
-                try {
-                    sleepWithMsg(sleep, "Shutdown in " + sleep / 1000 / 60 + " minute(s)");
-                    getBundleContext().getBundle(0).stop();
-                } catch (Exception e) {
-                    LOGGER.error("Halt error", e);
-                }
-            }
-        }.start();
-    }
-
-    private void reboot(final long sleep, final Swipe clean) {
-        new Thread() {
-            public void run() {
-                try {
-                    sleepWithMsg(sleep, "Reboot in " + sleep / 1000 / 60 + " minute(s)");
-                    System.setProperty("karaf.restart", "true");
-                    if (clean.equals(Swipe.ALL)) {
-                        System.setProperty("karaf.clean.all", "true");
-                    } else if (clean.equals(Swipe.CACHE)) {
-                        System.setProperty("karaf.clean.cache", "true");
-                    }
-                    bundleContext.getBundle(0).stop();
-                } catch (Exception e) {
-                    LOGGER.error("Reboot error", e);
-                }
-            }
-        }.start();
-    }
-    
-    private void sleepWithMsg(final long sleep, String msg)
-            throws InterruptedException {
-        if (sleep > 0) {
-            LOGGER.info(msg);
-            System.err.println(msg);
-        }
-        Thread.sleep(sleep);
-    }
-
-    public void setStartLevel(int startLevel) throws Exception {
-        getBundleContext().getBundle(0).adapt(FrameworkStartLevel.class).setStartLevel(startLevel);
-    }
-
-    public int getStartLevel() throws Exception {
-        return getBundleContext().getBundle(0).adapt(FrameworkStartLevel.class).getStartLevel();
-    }
-
-    /**
-     * Convert a time string to sleep period (in millisecond).
-     *
-     * @param time the time string.
-     * @return the corresponding sleep period in millisecond.
-     */
-    private long timeToSleep(String time) throws Exception {
-        long sleep = 0;
-        if (time != null) {
-            if (!time.equals("now")) {
-                if (time.startsWith("+")) {
-                    // delay in number of minutes provided
-                    time = time.substring(1);
-                    try {
-                        sleep = Long.parseLong(time) * 60 * 1000;
-                    } catch (Exception e) {
-                        throw new IllegalArgumentException("Time " + time + " is not valid");
-                    }
-                } else {
-                    // try to parse the date in hh:mm
-                    String[] strings = time.split(":");
-                    if (strings.length != 2) {
-                        throw new IllegalArgumentException("Time " + time + " is not valid");
-                    }
-                    GregorianCalendar currentDate = new GregorianCalendar();
-                    GregorianCalendar shutdownDate = new GregorianCalendar(currentDate.get(Calendar.YEAR), currentDate.get(Calendar.MONTH), currentDate.get(Calendar.DATE), Integer.parseInt(strings[0]), Integer.parseInt(strings[1]));
-                    if (shutdownDate.before(currentDate)) {
-                        shutdownDate.set(Calendar.DATE, shutdownDate.get(Calendar.DATE) + 1);
-                    }
-                    sleep = shutdownDate.getTimeInMillis() - currentDate.getTimeInMillis();
-                }
-            }
-        }
-        return sleep;
-    }
-
-    @Override
-    public String getVersion() {
-        return System.getProperty("karaf.version");
-    }
-
-    @Override
-    public String getName() {
-        return bundleContext.getProperty("karaf.name");
-    }
-
-    @Override
-    public void setName(String name) {
-        try {
-            String karafEtc = bundleContext.getProperty("karaf.etc");
-            File etcDir = new File(karafEtc);
-            File syspropsFile = new File(etcDir, "system.properties");
-            FileInputStream fis = new FileInputStream(syspropsFile);
-            Properties props = new Properties();
-            props.load(fis);
-            fis.close();
-            props.setProperty("karaf.name", name);
-            FileOutputStream fos = new FileOutputStream(syspropsFile);
-            props.store(fos, "");
-            fos.close();
-        } catch (Exception e) {
-            throw new RuntimeException(e.getMessage(), e);
-        }
-    }
-    
-    public FrameworkType getFramework() {
-        if (bundleContext.getBundle(0).getSymbolicName().contains("felix")) {
-            return FrameworkType.felix;
-        } else {
-            return FrameworkType.equinox;
-        }
-    }
-
-    private Properties loadProps() throws IOException {
-        return new Properties(new File(System.getProperty("karaf.etc"), "config.properties"));
-    }
-
-    public void setFramework(FrameworkType framework) {
-        if (framework == null) {
-            return;
-        }
-        try {
-            Properties properties = loadProps();
-            properties.put("karaf.framework", framework.name());
-            properties.save();
-        } catch (IOException e) {
-            throw new RuntimeException("Error setting framework: " + e.getMessage(), e);
-        }
-    }
-
-    public void setFrameworkDebug(boolean debug) {
-        try {
-            Properties properties = loadProps();
-            if (debug) {
-                properties.put("felix.log.level", "4");
-                properties.put("osgi.debug", "etc/equinox-debug.properties");
-            } else {
-                properties.remove("felix.log.level");
-                properties.remove("osgi.debug");
-            }
-            // TODO populate the equinox-debug.properties file with the one provided in shell/dev module
-            properties.save();
-        } catch (IOException e) {
-            throw new RuntimeException("Error settting framework debugging: " + e.getMessage(), e);
-        }
-    }
-
-    @Override
-    public String setSystemProperty(String key, String value, boolean persist) {
-        if (persist) {
-            try {
-                String etc = System.getProperty("karaf.etc");
-                Properties props = new Properties(new File(etc, "system.properties"));
-                props.put(key, value);
-                props.save();
-            } catch (IOException e) {
-                throw new RuntimeException("Error persisting system property", e);
-            }
-        }
-        return System.setProperty(key, value);
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/0a100d76/system/core/src/main/java/org/apache/karaf/system/internal/osgi/Activator.java
----------------------------------------------------------------------
diff --git a/system/core/src/main/java/org/apache/karaf/system/internal/osgi/Activator.java b/system/core/src/main/java/org/apache/karaf/system/internal/osgi/Activator.java
deleted file mode 100644
index b7f8eab..0000000
--- a/system/core/src/main/java/org/apache/karaf/system/internal/osgi/Activator.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * 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.karaf.system.internal.osgi;
-
-import org.apache.karaf.system.SystemService;
-import org.apache.karaf.system.internal.SystemServiceImpl;
-import org.apache.karaf.system.management.internal.SystemMBeanImpl;
-import org.apache.karaf.util.tracker.BaseActivator;
-
-public class Activator extends BaseActivator {
-
-    @Override
-    protected void doStart() throws Exception {
-        SystemServiceImpl systemService = new SystemServiceImpl();
-        systemService.setBundleContext(bundleContext);
-        register(SystemService.class, systemService);
-
-        SystemMBeanImpl mbean = new SystemMBeanImpl();
-        mbean.setBundleContext(bundleContext);
-        mbean.setSystemService(systemService);
-        registerMBean(mbean, "type=system");
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/0a100d76/system/core/src/main/java/org/apache/karaf/system/management/SystemMBean.java
----------------------------------------------------------------------
diff --git a/system/core/src/main/java/org/apache/karaf/system/management/SystemMBean.java b/system/core/src/main/java/org/apache/karaf/system/management/SystemMBean.java
deleted file mode 100644
index 5d9bdbc..0000000
--- a/system/core/src/main/java/org/apache/karaf/system/management/SystemMBean.java
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- * 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.karaf.system.management;
-
-import javax.management.MBeanException;
-import java.util.Map;
-
-/**
- * Describe the system MBean.
- */
-public interface SystemMBean {
-
-    /**
-     * Stop the Karaf instance
-     *
-     * @throws Exception
-     */
-    void halt() throws MBeanException;
-
-    /**
-     * Stop the Karaf instance at a given time.
-     *
-     * @param time the time when to stop the Karaf instance.
-     * @throws Exception
-     */
-    void halt(String time) throws MBeanException;
-
-    /**
-     * Reboot the Karaf instance.
-     *
-     * @throws Exception
-     */
-    void reboot() throws MBeanException;
-
-    /**
-     * Reboot the Karaf instance at a given time.
-     *
-     * @param time the time when to reboot the Karaf instance.
-     * @throws Exception
-     */
-    void reboot(String time) throws MBeanException;
-
-    /**
-     * Reboot the Karaf instance at a given time and clean the cache.
-     *
-     * @param time the time when to reboot the Karaf instance.
-     * @throws Exception
-     */
-    void rebootCleanCache(String time) throws MBeanException;
-
-    /**
-     * Reboot the Karaf instance at a given time and clean all working files.
-     *
-     * @param time the time when to reboot the Karaf instance.
-     * @throws Exception
-     */
-    void rebootCleanAll(String time) throws MBeanException;
-
-    /**
-     * Set the system bundle start level.
-     *
-     * @param startLevel the new system bundle start level.
-     * @throws Exception
-     */
-    void setStartLevel(int startLevel) throws MBeanException;
-
-    /**
-     * Get the current system bundle start level.
-     *
-     * @return the current system bundle start level.
-     * @throws Exception
-     */
-    int getStartLevel() throws MBeanException;
-
-    /**
-     * Get the current OSGi framework in use.
-     *
-     * @return the name of the OSGi framework in use.
-     * @throws Exception
-     */
-    String getFramework();
-
-    /**
-     * change OSGi framework
-     *
-     * @param framework to use.
-     */
-    void setFramework(String framework);
-    
-    /**
-     * Enable or diable debgging
-     * @param debug enable if true
-     */
-    void setFrameworkDebug(boolean debug);
-
-    /**
-     * Get the current Karaf instance name.
-     *
-     * @return the current Karaf instance name.
-     */
-    String getName();
-
-    /**
-     * Change Karaf instance name.
-     *
-     * @param name the new Karaf instance name.
-     */
-    void setName(String name);
-
-    /**
-     * Get the version of the current Karaf instance.
-     *
-     * @return the current Karaf instance version.
-     */
-    String getVersion();
-
-    /**
-     * Get all system properties.
-     *
-     * @param unset if true, display the OSGi properties even if they are not defined (with "undef" value).
-     * @param dumpToFile if true, dump the properties into a file in the data folder.
-     * @return the list of system properties.
-     */
-    Map<String, String> getProperties(boolean unset, boolean dumpToFile) throws MBeanException;
-
-    /**
-     * Get the value of a given system property.
-     *
-     * @param key the system property key.
-     * @return the system property value.
-     */
-    String getProperty(String key);
-
-    /**
-     * Set the value of a system property.
-     *
-     * @param key the system property key.
-     * @param value the new system property value.
-     * @param persistent if true, persist the new value to the etc/system.properties file.
-     */
-    void setProperty(String key, String value, boolean persistent);
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/0a100d76/system/core/src/main/java/org/apache/karaf/system/management/internal/SystemMBeanImpl.java
----------------------------------------------------------------------
diff --git a/system/core/src/main/java/org/apache/karaf/system/management/internal/SystemMBeanImpl.java b/system/core/src/main/java/org/apache/karaf/system/management/internal/SystemMBeanImpl.java
deleted file mode 100644
index c0f34cd..0000000
--- a/system/core/src/main/java/org/apache/karaf/system/management/internal/SystemMBeanImpl.java
+++ /dev/null
@@ -1,259 +0,0 @@
-/*
- * 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.karaf.system.management.internal;
-
-import org.apache.karaf.system.FrameworkType;
-import org.apache.karaf.system.SystemService;
-import org.apache.karaf.system.management.SystemMBean;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.Constants;
-
-import javax.management.MBeanException;
-import javax.management.NotCompliantMBeanException;
-import javax.management.StandardMBean;
-import java.io.File;
-import java.io.PrintStream;
-import java.text.SimpleDateFormat;
-import java.util.*;
-
-/**
- * System MBean implementation.
- */
-public class SystemMBeanImpl extends StandardMBean implements SystemMBean {
-
-    private SystemService systemService;
-    private BundleContext bundleContext;
-
-    public void setBundleContext(BundleContext bundleContext) {
-        this.bundleContext = bundleContext;
-    }
-
-    public SystemMBeanImpl() throws NotCompliantMBeanException {
-        super(SystemMBean.class);
-    }
-
-    public void setSystemService(SystemService systemService) {
-        this.systemService = systemService;
-    }
-
-    public SystemService getSystemService() {
-        return this.systemService;
-    }
-
-    public void halt() throws MBeanException {
-        try {
-            systemService.halt();
-        } catch (Exception e) {
-            throw new MBeanException(null, e.getMessage());
-        }
-    }
-
-    public void halt(String time) throws MBeanException {
-        try {
-            systemService.halt(time);
-        } catch (Exception e) {
-            throw new MBeanException(null, e.getMessage());
-        }
-    }
-
-    public void reboot() throws MBeanException {
-        try {
-            systemService.reboot();
-        } catch (Exception e) {
-            throw new MBeanException(null, e.getMessage());
-        }
-    }
-
-    public void reboot(String time) throws MBeanException {
-        try {
-            systemService.reboot(time, SystemService.Swipe.NONE);
-        } catch (Exception e) {
-            throw new MBeanException(null, e.getMessage());
-        }
-    }
-
-    public void rebootCleanCache(String time) throws MBeanException {
-        try {
-            systemService.reboot(time, SystemService.Swipe.CACHE);
-        } catch (Exception e) {
-            throw new MBeanException(null, e.getMessage());
-        }
-    }
-
-    public void rebootCleanAll(String time) throws MBeanException {
-        try {
-            systemService.reboot(time, SystemService.Swipe.ALL);
-        } catch (Exception e) {
-            throw new MBeanException(null, e.getMessage());
-        }
-    }
-
-    public void setStartLevel(int startLevel) throws MBeanException {
-        try {
-            systemService.setStartLevel(startLevel);
-        } catch (Exception e) {
-            throw new MBeanException(null, e.getMessage());
-        }
-    }
-
-    public int getStartLevel() throws MBeanException {
-        try {
-            return systemService.getStartLevel();
-        } catch (Exception e) {
-            throw new MBeanException(null, e.getMessage());
-        }
-    }
-
-    @Override
-    public String getFramework() {
-        return this.systemService.getFramework().toString();
-    }
-
-    @Override
-    public void setFramework(String framework) {
-        this.systemService.setFramework(FrameworkType.valueOf(framework.toLowerCase()));
-    }
-
-    @Override
-    public void setFrameworkDebug(boolean debug) {
-        this.systemService.setFrameworkDebug(debug);
-    }
-
-    @Override
-    public String getName() {
-        return this.systemService.getName();
-    }
-
-    @Override
-    public void setName(String name) {
-        if (name == null || name.trim().isEmpty()) {
-            throw new IllegalArgumentException("Instance name can't be null or empty");
-        }
-        this.systemService.setName(name);
-    }
-
-    @Override
-    public String getVersion() {
-        return this.systemService.getVersion();
-    }
-
-    @Override
-    public Map<String, String> getProperties(boolean unset, boolean dumpToFile) throws MBeanException {
-        try {
-            Map<String, String> result = new HashMap<String, String>();
-
-            Properties props = (Properties) java.lang.System.getProperties().clone();
-
-            String def = null;
-            if (unset) {
-                def = "unset";
-            }
-
-            setProperty(props, Constants.FRAMEWORK_BEGINNING_STARTLEVEL, def);
-            setProperty(props, Constants.FRAMEWORK_BOOTDELEGATION, def);
-            setProperty(props, Constants.FRAMEWORK_BUNDLE_PARENT, def);
-            setProperty(props, Constants.FRAMEWORK_BUNDLE_PARENT_APP, def);
-            setProperty(props, Constants.FRAMEWORK_BUNDLE_PARENT_BOOT, def);
-            setProperty(props, Constants.FRAMEWORK_BUNDLE_PARENT_EXT, def);
-            setProperty(props, Constants.FRAMEWORK_BUNDLE_PARENT_FRAMEWORK, def);
-            setProperty(props, Constants.FRAMEWORK_EXECPERMISSION, def);
-            setProperty(props, Constants.FRAMEWORK_EXECUTIONENVIRONMENT, def);
-            setProperty(props, Constants.FRAMEWORK_LANGUAGE, def);
-            setProperty(props, Constants.FRAMEWORK_LIBRARY_EXTENSIONS, def);
-            setProperty(props, Constants.FRAMEWORK_OS_NAME, def);
-            setProperty(props, Constants.FRAMEWORK_OS_VERSION, def);
-            setProperty(props, Constants.FRAMEWORK_PROCESSOR, def);
-            setProperty(props, Constants.FRAMEWORK_SECURITY, def);
-            setProperty(props, Constants.FRAMEWORK_SECURITY_OSGI, def);
-            setProperty(props, Constants.FRAMEWORK_STORAGE, def);
-            setProperty(props, Constants.FRAMEWORK_STORAGE_CLEAN_ONFIRSTINIT, def);
-            setProperty(props, Constants.FRAMEWORK_SYSTEMPACKAGES, def);
-            setProperty(props, Constants.FRAMEWORK_SYSTEMPACKAGES_EXTRA, def);
-            setProperty(props, Constants.FRAMEWORK_VENDOR, def);
-            setProperty(props, Constants.FRAMEWORK_VERSION, def);
-            setProperty(props, Constants.FRAMEWORK_WINDOWSYSTEM, def);
-
-            setProperty(props, Constants.SUPPORTS_BOOTCLASSPATH_EXTENSION, def);
-            setProperty(props, Constants.SUPPORTS_FRAMEWORK_EXTENSION, def);
-            setProperty(props, Constants.SUPPORTS_FRAMEWORK_FRAGMENT, def);
-            setProperty(props, Constants.SUPPORTS_FRAMEWORK_REQUIREBUNDLE, def);
-
-            if (dumpToFile) {
-                PrintStream ps = new PrintStream(new File(bundleContext.getProperty("karaf.data"), "dump-properties-" + java.lang.System.currentTimeMillis() + ".properties"));
-                ps.println("#Dump of the System and OSGi properties");
-                ps.println("#Dump executed at " + new SimpleDateFormat().format(new Date()));
-                printOrderedProperties(props, ps);
-                ps.flush();
-                ps.close();
-            } else {
-                printOrderedProperties(props, result);
-            }
-
-            return result;
-        } catch (Exception e) {
-            throw new MBeanException(null, e.getMessage());
-        }
-    }
-
-    private void printOrderedProperties(Properties props, PrintStream out) {
-        Set<Object> keys = props.keySet();
-        Vector<String> order = new Vector<String>(keys.size());
-        for (Iterator<Object> i = keys.iterator(); i.hasNext(); ) {
-            Object str = (Object) i.next();
-            order.add((String) str);
-        }
-        Collections.sort(order);
-        for (Iterator<String> i = order.iterator(); i.hasNext(); ) {
-            String key = (String) i.next();
-            out.println(key + "=" + props.getProperty(key));
-        }
-    }
-
-    private void printOrderedProperties(Properties props, Map<String, String> result) {
-        Set<Object> keys = props.keySet();
-        Vector<String> order = new Vector<String>(keys.size());
-        for (Iterator<Object> i = keys.iterator(); i.hasNext(); ) {
-            Object str = (Object) i.next();
-            order.add((String) str);
-        }
-        Collections.sort(order);
-        for (Iterator<String> i = order.iterator(); i.hasNext(); ) {
-            String key = (String) i.next();
-            result.put(key, props.getProperty(key));
-        }
-    }
-
-    private void setProperty(Properties props, String key, String def) {
-        String val = bundleContext.getProperty(key);
-        if (val == null && def != null) {
-            props.setProperty(key, def);
-        } else if (val != null) {
-            props.setProperty(key, val);
-        }
-    }
-
-    @Override
-    public String getProperty(String key) {
-        return java.lang.System.getProperty(key);
-    }
-
-    @Override
-    public void setProperty(String key, String value, boolean persistent) {
-        systemService.setSystemProperty(key, value, persistent);
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/0a100d76/system/core/src/main/resources/OSGI-INF/bundle.info
----------------------------------------------------------------------
diff --git a/system/core/src/main/resources/OSGI-INF/bundle.info b/system/core/src/main/resources/OSGI-INF/bundle.info
deleted file mode 100644
index acca1c8..0000000
--- a/system/core/src/main/resources/OSGI-INF/bundle.info
+++ /dev/null
@@ -1,16 +0,0 @@
-h1. Synopsis
-
-${project.name}
-
-${project.description}
-
-Maven URL:
-[mvn:${project.groupId}/${project.artifactId}/${project.version}]
-
-h1. Description
-
-This bundle provides support of the system service, which control the Karaf container.
-
-h1. See also
-
-Shutdown - section of the Karaf User Guide

http://git-wip-us.apache.org/repos/asf/karaf/blob/0a100d76/system/core/src/test/java/org/apache/karaf/system/internal/SystemServiceImplTest.java
----------------------------------------------------------------------
diff --git a/system/core/src/test/java/org/apache/karaf/system/internal/SystemServiceImplTest.java b/system/core/src/test/java/org/apache/karaf/system/internal/SystemServiceImplTest.java
deleted file mode 100644
index 2de4e1e..0000000
--- a/system/core/src/test/java/org/apache/karaf/system/internal/SystemServiceImplTest.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
-* 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.karaf.system.internal;
-
-import java.io.File;
-import java.io.IOException;
-import java.net.URISyntaxException;
-import java.net.URL;
-
-import org.apache.felix.utils.properties.Properties;
-import org.easymock.EasyMock;
-import org.junit.Assert;
-import org.junit.Test;
-import org.osgi.framework.BundleContext;
-
-/**
- * Implementation of the system service.
- */
-
-public class SystemServiceImplTest {
-
-    private static final String NEW_NAME = "newName";
-
-    @Test
-    public void testSetName() throws URISyntaxException, IOException {
-        SystemServiceImpl system = new SystemServiceImpl();
-        BundleContext bundleContext = EasyMock.createMock(BundleContext.class);
-        URL propUrl = this.getClass().getClassLoader().getResource("etc/system.properties");
-        File propfile = new File(propUrl.toURI());        
-        EasyMock.expect(bundleContext.getProperty("karaf.etc")).andReturn(propfile.getParentFile().getParent() + "/etc");
-        EasyMock.replay(bundleContext);
-        system.setBundleContext(bundleContext);
-        system.setName(NEW_NAME);
-        EasyMock.verify(bundleContext);
-        Properties props = new Properties(propfile);
-        String nameAfter = props.getProperty("karaf.name");
-        Assert.assertEquals(NEW_NAME, nameAfter);
-    }
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/0a100d76/system/core/src/test/resources/etc/system.properties
----------------------------------------------------------------------
diff --git a/system/core/src/test/resources/etc/system.properties b/system/core/src/test/resources/etc/system.properties
deleted file mode 100644
index 6749fbb..0000000
--- a/system/core/src/test/resources/etc/system.properties
+++ /dev/null
@@ -1,22 +0,0 @@
-################################################################################
-#
-#    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.
-#
-################################################################################
-
-#Comment
-karaf.name=oldName
-#Comment2

http://git-wip-us.apache.org/repos/asf/karaf/blob/0a100d76/system/pom.xml
----------------------------------------------------------------------
diff --git a/system/pom.xml b/system/pom.xml
index 39ce101..59d338a 100644
--- a/system/pom.xml
+++ b/system/pom.xml
@@ -29,13 +29,86 @@
     </parent>
 
     <groupId>org.apache.karaf.system</groupId>
-    <artifactId>system</artifactId>
-    <packaging>pom</packaging>
-    <name>Apache Karaf :: System</name>
-
-    <modules>
-        <module>core</module>
-        <module>command</module>
-    </modules>
+    <artifactId>org.apache.karaf.system.core</artifactId>
+    <packaging>bundle</packaging>
+    <name>Apache Karaf :: System :: Core</name>
+    <description>
+        This bundle provides services to manipulate the Karaf container itself (system).
+    </description>
+
+    <properties>
+        <appendedResourcesDirectory>${basedir}/../../etc/appended-resources</appendedResourcesDirectory>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>org.osgi.core</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-api</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.karaf</groupId>
+            <artifactId>org.apache.karaf.util</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.felix</groupId>
+            <artifactId>org.apache.felix.utils</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.karaf.shell</groupId>
+            <artifactId>org.apache.karaf.shell.core</artifactId>
+            <optional>true</optional>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <resources>
+            <resource>
+                <directory>${project.basedir}/src/main/resources</directory>
+                <includes>
+                    <include>**/*</include>
+                </includes>
+            </resource>
+            <resource>
+                <directory>${project.basedir}/src/main/resources</directory>
+                <filtering>true</filtering>
+                <includes>
+                    <include>**/*.info</include>
+                </includes>
+            </resource>
+        </resources>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+                <configuration>
+                    <instructions>
+                        <Export-Package>
+                            org.apache.karaf.system,
+                            org.apache.karaf.system.management
+                        </Export-Package>
+                        <Private-Package>
+                            org.apache.karaf.system.commands,
+                            org.apache.karaf.system.internal,
+                            org.apache.karaf.system.internal.osgi,
+                            org.apache.karaf.system.management.internal,
+                            org.apache.karaf.util.tracker,
+                            org.apache.felix.utils.properties
+                        </Private-Package>
+                        <Bundle-Activator>
+                            org.apache.karaf.system.internal.osgi.Activator
+                        </Bundle-Activator>
+                        <Karaf-Commands>*</Karaf-Commands>
+                    </instructions>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
 
 </project>

http://git-wip-us.apache.org/repos/asf/karaf/blob/0a100d76/system/src/main/java/org/apache/karaf/system/FrameworkType.java
----------------------------------------------------------------------
diff --git a/system/src/main/java/org/apache/karaf/system/FrameworkType.java b/system/src/main/java/org/apache/karaf/system/FrameworkType.java
new file mode 100644
index 0000000..67720a7
--- /dev/null
+++ b/system/src/main/java/org/apache/karaf/system/FrameworkType.java
@@ -0,0 +1,19 @@
+/*
+ * 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.system;
+
+public enum FrameworkType {
+    felix,
+    equinox
+}


[34/59] [abbrv] git commit: [KARAF-2852] Merge kar/core and kar/command

Posted by gn...@apache.org.
[KARAF-2852] Merge kar/core and kar/command

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

Branch: refs/heads/master
Commit: f13d140c3a055686caa587883c74d987971b8e06
Parents: 886863a
Author: Guillaume Nodet <gn...@gmail.com>
Authored: Wed Apr 9 23:07:47 2014 +0200
Committer: Guillaume Nodet <gn...@gmail.com>
Committed: Thu Apr 10 16:01:24 2014 +0200

----------------------------------------------------------------------
 .../standard/src/main/feature/feature.xml       |   1 -
 kar/NOTICE                                      |  71 ++++
 kar/command/NOTICE                              |  71 ----
 kar/command/pom.xml                             |  89 -----
 .../karaf/kar/command/CreateKarCommand.java     |  50 ---
 .../karaf/kar/command/InstallKarCommand.java    |  43 ---
 .../karaf/kar/command/ListKarCommand.java       |  52 ---
 .../karaf/kar/command/UninstallKarCommand.java  |  45 ---
 .../kar/command/completers/KarCompleter.java    |  50 ---
 .../src/main/resources/OSGI-INF/bundle.info     |  22 --
 kar/core/NOTICE                                 |  71 ----
 kar/core/pom.xml                                | 118 ------
 .../java/org/apache/karaf/kar/KarService.java   |  80 ----
 .../java/org/apache/karaf/kar/KarsMBean.java    |  57 ---
 .../karaf/kar/internal/FeatureDetector.java     |  87 -----
 .../java/org/apache/karaf/kar/internal/Kar.java | 203 ----------
 .../karaf/kar/internal/KarServiceImpl.java      | 382 -------------------
 .../karaf/kar/internal/KarsMBeanImpl.java       |  72 ----
 .../karaf/kar/internal/osgi/Activator.java      |  54 ---
 .../src/main/resources/OSGI-INF/bundle.info     |  19 -
 kar/pom.xml                                     | 102 ++++-
 .../java/org/apache/karaf/kar/KarService.java   |  80 ++++
 .../java/org/apache/karaf/kar/KarsMBean.java    |  57 +++
 .../karaf/kar/command/CreateKarCommand.java     |  50 +++
 .../karaf/kar/command/InstallKarCommand.java    |  43 +++
 .../karaf/kar/command/ListKarCommand.java       |  52 +++
 .../karaf/kar/command/UninstallKarCommand.java  |  45 +++
 .../kar/command/completers/KarCompleter.java    |  50 +++
 .../karaf/kar/internal/FeatureDetector.java     |  87 +++++
 .../java/org/apache/karaf/kar/internal/Kar.java | 203 ++++++++++
 .../karaf/kar/internal/KarServiceImpl.java      | 382 +++++++++++++++++++
 .../karaf/kar/internal/KarsMBeanImpl.java       |  72 ++++
 .../karaf/kar/internal/osgi/Activator.java      |  54 +++
 kar/src/main/resources/OSGI-INF/bundle.info     |  19 +
 34 files changed, 1359 insertions(+), 1574 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/karaf/blob/f13d140c/assemblies/features/standard/src/main/feature/feature.xml
----------------------------------------------------------------------
diff --git a/assemblies/features/standard/src/main/feature/feature.xml b/assemblies/features/standard/src/main/feature/feature.xml
index af81c40..99554c2 100644
--- a/assemblies/features/standard/src/main/feature/feature.xml
+++ b/assemblies/features/standard/src/main/feature/feature.xml
@@ -195,7 +195,6 @@
 
     <feature name="kar" description="Provide KAR (KARaf archive) support" version="${project.version}" resolver="(obr)">
         <bundle start-level="30">mvn:org.apache.karaf.kar/org.apache.karaf.kar.core/${project.version}</bundle>
-        <bundle start-level="30">mvn:org.apache.karaf.kar/org.apache.karaf.kar.command/${project.version}</bundle>
     </feature>
 
     <feature name="webconsole" description="Base support of the Karaf WebConsole" version="${project.version}" resolver="(obr)">

http://git-wip-us.apache.org/repos/asf/karaf/blob/f13d140c/kar/NOTICE
----------------------------------------------------------------------
diff --git a/kar/NOTICE b/kar/NOTICE
new file mode 100644
index 0000000..b70f1f9
--- /dev/null
+++ b/kar/NOTICE
@@ -0,0 +1,71 @@
+Apache Karaf
+Copyright 2010-2014 The Apache Software Foundation
+
+
+I. Included Software
+
+This product includes software developed at
+The Apache Software Foundation (http://www.apache.org/).
+Licensed under the Apache License 2.0.
+
+This product uses software developed at
+The OSGi Alliance (http://www.osgi.org/).
+Copyright (c) OSGi Alliance (2000, 2010).
+Licensed under the Apache License 2.0.
+
+This product includes software developed at
+OW2 (http://www.ow2.org/).
+Licensed under the BSD License.
+
+This product includes software developed at
+OPS4J (http://www.ops4j.org/).
+Licensed under the Apache License 2.0.
+
+This product includes software developed at
+Eclipse Foundation (http://www.eclipse.org/).
+Licensed under the EPL.
+
+This product includes software written by
+Antony Lesuisse.
+Licensed under Public Domain.
+
+
+II. Used Software
+
+This product uses software developed at
+FUSE Source (http://www.fusesource.org/).
+Licensed under the Apache License 2.0.
+
+This product uses software developed at
+AOP Alliance (http://aopalliance.sourceforge.net/).
+Licensed under the Public Domain.
+
+This product uses software developed at
+Tanuki Software (http://www.tanukisoftware.com/).
+Licensed under the Apache License 2.0.
+
+This product uses software developed at
+Jasypt (http://jasypt.sourceforge.net/).
+Licensed under the Apache License 2.0.
+
+This product uses software developed at
+JLine (http://jline.sourceforge.net).
+Licensed under the BSD License.
+
+This product uses software developed at
+SLF4J (http://www.slf4j.org/).
+Licensed under the MIT License.
+
+This product uses software developed at
+SpringSource (http://www.springsource.org/).
+Licensed under the Apache License 2.0.
+
+This product includes software from http://www.json.org.
+Copyright (c) 2002 JSON.org
+
+
+III. License Summary
+- Apache License 2.0
+- BSD License
+- EPL License
+- MIT License

http://git-wip-us.apache.org/repos/asf/karaf/blob/f13d140c/kar/command/NOTICE
----------------------------------------------------------------------
diff --git a/kar/command/NOTICE b/kar/command/NOTICE
deleted file mode 100644
index b70f1f9..0000000
--- a/kar/command/NOTICE
+++ /dev/null
@@ -1,71 +0,0 @@
-Apache Karaf
-Copyright 2010-2014 The Apache Software Foundation
-
-
-I. Included Software
-
-This product includes software developed at
-The Apache Software Foundation (http://www.apache.org/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-The OSGi Alliance (http://www.osgi.org/).
-Copyright (c) OSGi Alliance (2000, 2010).
-Licensed under the Apache License 2.0.
-
-This product includes software developed at
-OW2 (http://www.ow2.org/).
-Licensed under the BSD License.
-
-This product includes software developed at
-OPS4J (http://www.ops4j.org/).
-Licensed under the Apache License 2.0.
-
-This product includes software developed at
-Eclipse Foundation (http://www.eclipse.org/).
-Licensed under the EPL.
-
-This product includes software written by
-Antony Lesuisse.
-Licensed under Public Domain.
-
-
-II. Used Software
-
-This product uses software developed at
-FUSE Source (http://www.fusesource.org/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-AOP Alliance (http://aopalliance.sourceforge.net/).
-Licensed under the Public Domain.
-
-This product uses software developed at
-Tanuki Software (http://www.tanukisoftware.com/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-Jasypt (http://jasypt.sourceforge.net/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-JLine (http://jline.sourceforge.net).
-Licensed under the BSD License.
-
-This product uses software developed at
-SLF4J (http://www.slf4j.org/).
-Licensed under the MIT License.
-
-This product uses software developed at
-SpringSource (http://www.springsource.org/).
-Licensed under the Apache License 2.0.
-
-This product includes software from http://www.json.org.
-Copyright (c) 2002 JSON.org
-
-
-III. License Summary
-- Apache License 2.0
-- BSD License
-- EPL License
-- MIT License

http://git-wip-us.apache.org/repos/asf/karaf/blob/f13d140c/kar/command/pom.xml
----------------------------------------------------------------------
diff --git a/kar/command/pom.xml b/kar/command/pom.xml
deleted file mode 100644
index 220eec4..0000000
--- a/kar/command/pom.xml
+++ /dev/null
@@ -1,89 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-
-    <!--
-
-        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.
-    -->
-
-    <modelVersion>4.0.0</modelVersion>
-
-    <parent>
-        <groupId>org.apache.karaf.kar</groupId>
-        <artifactId>kar</artifactId>
-        <version>4.0.0-SNAPSHOT</version>
-        <relativePath>../pom.xml</relativePath>
-    </parent>
-
-    <artifactId>org.apache.karaf.kar.command</artifactId>
-    <packaging>bundle</packaging>
-    <name>Apache Karaf :: KAR :: Command</name>
-    <description>This bundle provides a set of Karaf shell commands to manipulate KAR files.</description>
-
-    <properties>
-        <appendedResourcesDirectory>${basedir}/../../etc/appended-resources</appendedResourcesDirectory>
-    </properties>
-
-    <dependencies>
-        <dependency>
-            <groupId>org.apache.karaf.kar</groupId>
-            <artifactId>org.apache.karaf.kar.core</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.karaf.shell</groupId>
-            <artifactId>org.apache.karaf.shell.core</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.karaf.features</groupId>
-            <artifactId>org.apache.karaf.features.command</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.osgi</groupId>
-            <artifactId>org.osgi.core</artifactId>
-        </dependency>
-    </dependencies>
-
-    <build>
-        <resources>
-            <resource>
-                <directory>${project.basedir}/src/main/resources</directory>
-                <includes>
-                    <include>**/*</include>
-                </includes>
-            </resource>
-            <resource>
-                <directory>${project.basedir}/src/main/resources</directory>
-                <filtering>true</filtering>
-                <includes>
-                    <include>**/*.info</include>
-                </includes>
-            </resource>
-        </resources>
-        <plugins>
-            <plugin>
-                <groupId>org.apache.felix</groupId>
-                <artifactId>maven-bundle-plugin</artifactId>
-                <configuration>
-                    <instructions>
-                        <Export-Package>!*</Export-Package>
-                        <Karaf-Commands>org.apache.karaf.kar.command.*</Karaf-Commands>
-                    </instructions>
-                </configuration>
-            </plugin>
-        </plugins>
-    </build>
-
-</project>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/karaf/blob/f13d140c/kar/command/src/main/java/org/apache/karaf/kar/command/CreateKarCommand.java
----------------------------------------------------------------------
diff --git a/kar/command/src/main/java/org/apache/karaf/kar/command/CreateKarCommand.java b/kar/command/src/main/java/org/apache/karaf/kar/command/CreateKarCommand.java
deleted file mode 100644
index a93706c..0000000
--- a/kar/command/src/main/java/org/apache/karaf/kar/command/CreateKarCommand.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * 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.karaf.kar.command;
-
-import java.util.List;
-
-import org.apache.karaf.features.command.completers.InstalledRepoNameCompleter;
-import org.apache.karaf.kar.KarService;
-import org.apache.karaf.shell.api.action.Action;
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Completion;
-import org.apache.karaf.shell.api.action.lifecycle.Reference;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-
-@Command(scope = "kar", name = "create", description = "Create a kar file for a list of feature repos")
-@Service
-public class CreateKarCommand implements Action {
-    
-    @Argument(index = 0, name = "repoName", description = "Repository name. The kar will contain all features of the named repository by default", required = true, multiValued = false)
-    @Completion(InstalledRepoNameCompleter.class)
-    private String repoName;
-    
-    @Argument(index = 1, name = "features", description = "Names of the features to include. If set then only these features will be added", required = false, multiValued = true)
-    private List<String> features;
-
-    @Reference
-    private KarService karService;
-
-    @Override
-    public Object execute() throws Exception {
-        karService.create(repoName, features, System.out);
-        return null;
-    }
-    
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/f13d140c/kar/command/src/main/java/org/apache/karaf/kar/command/InstallKarCommand.java
----------------------------------------------------------------------
diff --git a/kar/command/src/main/java/org/apache/karaf/kar/command/InstallKarCommand.java b/kar/command/src/main/java/org/apache/karaf/kar/command/InstallKarCommand.java
deleted file mode 100644
index 806367a..0000000
--- a/kar/command/src/main/java/org/apache/karaf/kar/command/InstallKarCommand.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * 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.karaf.kar.command;
-
-import org.apache.karaf.kar.KarService;
-import org.apache.karaf.shell.api.action.Action;
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.lifecycle.Reference;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-
-import java.net.URI;
-
-@Command(scope = "kar", name = "install", description = "Installs a KAR file.")
-@Service
-public class InstallKarCommand implements Action {
-
-    @Argument(index = 0, name = "url", description = "The URL of the KAR file to install.", required = true, multiValued = false)
-    private String url;
-
-    @Reference
-    private KarService karService;
-
-    public Object execute() throws Exception {
-        karService.install(new URI(url));
-        return null;
-    }
-    
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/f13d140c/kar/command/src/main/java/org/apache/karaf/kar/command/ListKarCommand.java
----------------------------------------------------------------------
diff --git a/kar/command/src/main/java/org/apache/karaf/kar/command/ListKarCommand.java b/kar/command/src/main/java/org/apache/karaf/kar/command/ListKarCommand.java
deleted file mode 100644
index 98813ff..0000000
--- a/kar/command/src/main/java/org/apache/karaf/kar/command/ListKarCommand.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * 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.karaf.kar.command;
-
-import org.apache.karaf.kar.KarService;
-import org.apache.karaf.shell.api.action.Action;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Option;
-import org.apache.karaf.shell.api.action.lifecycle.Reference;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.apache.karaf.shell.support.table.ShellTable;
-
-@Command(scope = "kar", name = "list", description = "List the installed KAR files.")
-@Service
-public class ListKarCommand implements Action {
-
-    @Option(name = "--no-format", description = "Disable table rendered output", required = false, multiValued = false)
-    boolean noFormat;
-
-    @Reference
-    private KarService karService;
-
-    @Override
-    public Object execute() throws Exception {
-
-        ShellTable table = new ShellTable();
-        table.column("KAR Name");
-
-        for (String karName : karService.list()) {
-            table.addRow().addContent(karName);
-        }
-
-        table.print(System.out, !noFormat);
-
-        return null;
-    }
-    
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/f13d140c/kar/command/src/main/java/org/apache/karaf/kar/command/UninstallKarCommand.java
----------------------------------------------------------------------
diff --git a/kar/command/src/main/java/org/apache/karaf/kar/command/UninstallKarCommand.java b/kar/command/src/main/java/org/apache/karaf/kar/command/UninstallKarCommand.java
deleted file mode 100644
index 506bdb3..0000000
--- a/kar/command/src/main/java/org/apache/karaf/kar/command/UninstallKarCommand.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * 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.karaf.kar.command;
-
-import org.apache.karaf.kar.KarService;
-import org.apache.karaf.kar.command.completers.KarCompleter;
-import org.apache.karaf.shell.api.action.Action;
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Completion;
-import org.apache.karaf.shell.api.action.lifecycle.Reference;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-
-@Command(scope = "kar", name = "uninstall", description = "Uninstall a KAR file.")
-@Service
-public class UninstallKarCommand implements Action {
-
-    @Argument(index = 0, name = "name", description = "The name of the KAR file to uninstall.", required = true, multiValued = false)
-    @Completion(KarCompleter.class)
-    private String name;
-
-    @Reference
-    private KarService karService;
-
-    @Override
-    public Object execute() throws Exception {
-        karService.uninstall(name);
-        return null;
-    }
-    
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/f13d140c/kar/command/src/main/java/org/apache/karaf/kar/command/completers/KarCompleter.java
----------------------------------------------------------------------
diff --git a/kar/command/src/main/java/org/apache/karaf/kar/command/completers/KarCompleter.java b/kar/command/src/main/java/org/apache/karaf/kar/command/completers/KarCompleter.java
deleted file mode 100644
index 539cfaf..0000000
--- a/kar/command/src/main/java/org/apache/karaf/kar/command/completers/KarCompleter.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * 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.karaf.kar.command.completers;
-
-import java.util.List;
-
-import org.apache.karaf.kar.KarService;
-import org.apache.karaf.shell.api.action.lifecycle.Reference;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.apache.karaf.shell.api.console.CommandLine;
-import org.apache.karaf.shell.api.console.Completer;
-import org.apache.karaf.shell.api.console.Session;
-import org.apache.karaf.shell.support.completers.StringsCompleter;
-
-/**
- * Completer on all installed KAR files.
- */
-@Service
-public class KarCompleter implements Completer {
-
-    @Reference
-    private KarService karService;
-    
-    public int complete(Session session, CommandLine commandLine, List<String> candidates) {
-        StringsCompleter delegate = new StringsCompleter();
-        try {
-            for (String karName : karService.list()) {
-                delegate.getStrings().add(karName);
-            }
-        } catch (Exception e) {
-            // ignore
-        }
-        return delegate.complete(session, commandLine, candidates);
-    }
-    
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/f13d140c/kar/command/src/main/resources/OSGI-INF/bundle.info
----------------------------------------------------------------------
diff --git a/kar/command/src/main/resources/OSGI-INF/bundle.info b/kar/command/src/main/resources/OSGI-INF/bundle.info
deleted file mode 100644
index 79a21ae..0000000
--- a/kar/command/src/main/resources/OSGI-INF/bundle.info
+++ /dev/null
@@ -1,22 +0,0 @@
-h1. Synopsis
-
-${project.name}
-
-${project.description}
-
-Maven URL:
-[mvn:${project.groupId}/${project.artifactId}/${project.version}]
-
-h1. Description
-
-This bundle provides the shell commands to manipulate the KAR artifacts.
-
-Especially, the following commands are available:
-
-* kar:list
-* kar:install
-* kar:uninstall
-
-h1. See also
-
-KAR - section of the Karaf User Guide
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/karaf/blob/f13d140c/kar/core/NOTICE
----------------------------------------------------------------------
diff --git a/kar/core/NOTICE b/kar/core/NOTICE
deleted file mode 100644
index b70f1f9..0000000
--- a/kar/core/NOTICE
+++ /dev/null
@@ -1,71 +0,0 @@
-Apache Karaf
-Copyright 2010-2014 The Apache Software Foundation
-
-
-I. Included Software
-
-This product includes software developed at
-The Apache Software Foundation (http://www.apache.org/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-The OSGi Alliance (http://www.osgi.org/).
-Copyright (c) OSGi Alliance (2000, 2010).
-Licensed under the Apache License 2.0.
-
-This product includes software developed at
-OW2 (http://www.ow2.org/).
-Licensed under the BSD License.
-
-This product includes software developed at
-OPS4J (http://www.ops4j.org/).
-Licensed under the Apache License 2.0.
-
-This product includes software developed at
-Eclipse Foundation (http://www.eclipse.org/).
-Licensed under the EPL.
-
-This product includes software written by
-Antony Lesuisse.
-Licensed under Public Domain.
-
-
-II. Used Software
-
-This product uses software developed at
-FUSE Source (http://www.fusesource.org/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-AOP Alliance (http://aopalliance.sourceforge.net/).
-Licensed under the Public Domain.
-
-This product uses software developed at
-Tanuki Software (http://www.tanukisoftware.com/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-Jasypt (http://jasypt.sourceforge.net/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-JLine (http://jline.sourceforge.net).
-Licensed under the BSD License.
-
-This product uses software developed at
-SLF4J (http://www.slf4j.org/).
-Licensed under the MIT License.
-
-This product uses software developed at
-SpringSource (http://www.springsource.org/).
-Licensed under the Apache License 2.0.
-
-This product includes software from http://www.json.org.
-Copyright (c) 2002 JSON.org
-
-
-III. License Summary
-- Apache License 2.0
-- BSD License
-- EPL License
-- MIT License

http://git-wip-us.apache.org/repos/asf/karaf/blob/f13d140c/kar/core/pom.xml
----------------------------------------------------------------------
diff --git a/kar/core/pom.xml b/kar/core/pom.xml
deleted file mode 100644
index 92f30c8..0000000
--- a/kar/core/pom.xml
+++ /dev/null
@@ -1,118 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-
-    <!--
-
-        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.
-    -->
-
-    <modelVersion>4.0.0</modelVersion>
-
-    <parent>
-        <groupId>org.apache.karaf.kar</groupId>
-        <artifactId>kar</artifactId>
-        <version>4.0.0-SNAPSHOT</version>
-        <relativePath>../pom.xml</relativePath>
-    </parent>
-
-    <artifactId>org.apache.karaf.kar.core</artifactId>
-    <packaging>bundle</packaging>
-    <name>Apache Karaf :: KAR :: Core</name>
-    <description>This bundle provides core implementation of the KAR management service.</description>
-
-    <properties>
-        <appendedResourcesDirectory>${basedir}/../../etc/appended-resources</appendedResourcesDirectory>
-    </properties>
-
-    <dependencies>
-        <dependency>
-            <groupId>org.apache.felix</groupId>
-            <artifactId>org.apache.felix.utils</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.karaf</groupId>
-            <artifactId>org.apache.karaf.util</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.osgi</groupId>
-            <artifactId>org.osgi.core</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.osgi</groupId>
-            <artifactId>org.osgi.compendium</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.ops4j.pax.swissbox</groupId>
-            <artifactId>pax-swissbox-property</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.karaf.features</groupId>
-            <artifactId>org.apache.karaf.features.core</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.slf4j</groupId>
-            <artifactId>slf4j-api</artifactId>
-            <scope>provided</scope>
-        </dependency>
-    </dependencies>
-
-    <build>
-        <resources>
-            <resource>
-                <directory>${project.basedir}/src/main/resources</directory>
-                <includes>
-                    <include>**/*</include>
-                </includes>
-            </resource>
-            <resource>
-                <directory>${project.basedir}/src/main/resources</directory>
-                <filtering>true</filtering>
-                <includes>
-                    <include>**/*.info</include>
-                </includes>
-            </resource>
-        </resources>
-        <plugins>
-            <plugin>
-                <groupId>org.apache.felix</groupId>
-                <artifactId>maven-bundle-plugin</artifactId>
-                <configuration>
-                    <instructions>
-                        <Export-Package>
-                            org.apache.karaf.kar
-                        </Export-Package>
-                        <Private-Package>
-                            org.apache.karaf.kar.internal,
-                            org.apache.karaf.kar.internal.osgi,
-                            org.apache.karaf.util.maven,
-                            org.apache.karaf.util.tracker,
-                            org.apache.felix.utils.properties
-                        </Private-Package>
-                        <Bundle-Activator>
-                            org.apache.karaf.kar.internal.osgi.Activator
-                        </Bundle-Activator>
-                    </instructions>
-                </configuration>
-            </plugin>
-        </plugins>
-    </build>
-
-</project>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/karaf/blob/f13d140c/kar/core/src/main/java/org/apache/karaf/kar/KarService.java
----------------------------------------------------------------------
diff --git a/kar/core/src/main/java/org/apache/karaf/kar/KarService.java b/kar/core/src/main/java/org/apache/karaf/kar/KarService.java
deleted file mode 100644
index 60acb77..0000000
--- a/kar/core/src/main/java/org/apache/karaf/kar/KarService.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * 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.karaf.kar;
-
-import java.io.File;
-import java.io.PrintStream;
-import java.net.URI;
-import java.util.List;
-
-/**
- * The service managing KAR.
- */
-public interface KarService {
-
-    /**
-     * Install KAR from a given URI
-     * 
-     * Resources will be copied to the karaf base dir
-     * Repository contents will be copied to a subdir in the 
-     * karaf data directory
-     *
-     * @param karUri Uri of the kar to be installed
-     * @throws Exception in case of installation failure.
-     */
-    void install(URI karUri) throws Exception;
-    
-    /**
-     * Install a kar with manually given repository and 
-     * resource directories.
-     * 
-     * @param karUri Uri of the kar to be installed
-     * @param repoDir destination for the repository contents of the kar
-     * @param resourceDir destination for the resource contents of the kar
-     * @throws Exception
-     */
-    void install(URI karUri, File repoDir, File resourceDir) throws Exception;
-
-    /**
-     * Uninstall the given KAR
-     *
-     * @param name the name of the KAR
-     * @throws Exception in case of failure
-     */
-    void uninstall(String name) throws Exception;
-
-    /**
-     * List the KAR stored in the data folder.
-     * 
-     * @return the list of KAR stored.
-     * @throws Exception in case of listing failure.
-     */
-    List<String> list() throws Exception;
-    
-    /**
-     * Create a kar from the given feature and repo names.
-     * Each named feature including all transitive deps will be added.
-     * For each named repo all features in the repo and their transitive deps will be added.
-     * 
-     * @param repoName
-     * @param features 
-     * @param console
-     */
-    void create(String repoName, List<String> features, PrintStream console);
-
-    
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/f13d140c/kar/core/src/main/java/org/apache/karaf/kar/KarsMBean.java
----------------------------------------------------------------------
diff --git a/kar/core/src/main/java/org/apache/karaf/kar/KarsMBean.java b/kar/core/src/main/java/org/apache/karaf/kar/KarsMBean.java
deleted file mode 100644
index b1a86c9..0000000
--- a/kar/core/src/main/java/org/apache/karaf/kar/KarsMBean.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * 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.karaf.kar;
-
-import javax.management.MBeanException;
-import java.util.List;
-
-public interface KarsMBean {
-
-    /**
-     * List the installed KAR files.
-     *
-     * @return the list of KAR files.
-     * @throws Exception in case of listing failure.
-     */
-    List<String> getKars() throws MBeanException;
-
-    /**
-     * Create a kar file for a list of feature repos
-     *
-     * @param repoName the name of features repository
-     * @param features the features to include in the kar
-     * @throws Exception in case of creation failure
-     */
-    void create(String repoName, List<String> features);
-
-    /**
-     * Install a KAR file from the given URL.
-     *
-     * @param url the JAR URL.
-     * @throws Exception in case of installation failure.
-     */
-    void install(String url) throws MBeanException;
-
-    /**
-     * Uninstall a KAR file.
-     * 
-     * @param name the name of the KAR file.
-     * @throws Exception in case of uninstall failure.
-     */
-    void uninstall(String name) throws MBeanException;
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/f13d140c/kar/core/src/main/java/org/apache/karaf/kar/internal/FeatureDetector.java
----------------------------------------------------------------------
diff --git a/kar/core/src/main/java/org/apache/karaf/kar/internal/FeatureDetector.java b/kar/core/src/main/java/org/apache/karaf/kar/internal/FeatureDetector.java
deleted file mode 100644
index aca1f53..0000000
--- a/kar/core/src/main/java/org/apache/karaf/kar/internal/FeatureDetector.java
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * 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.karaf.kar.internal;
-
-import java.io.File;
-
-import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.DocumentBuilderFactory;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.w3c.dom.Document;
-import org.xml.sax.ErrorHandler;
-import org.xml.sax.SAXException;
-import org.xml.sax.SAXParseException;
-
-/**
- * Simple helper to determine if a file is a feature repo
- */
-class FeatureDetector {
-
-    private static final Logger LOGGER = LoggerFactory.getLogger(FeatureDetector.class);
-    
-    private DocumentBuilderFactory dbf;
-
-    FeatureDetector() {
-        dbf = DocumentBuilderFactory.newInstance();
-        dbf.setNamespaceAware(true);
-    }
-    /**
-     * Check if a file is a features XML.
-     *
-     * @param artifact the file to check.
-     * @return true if the artifact is a features XML, false else.
-     */
-    boolean isFeaturesRepository(File artifact) {
-        try {
-            if (artifact.isFile() && artifact.getName().endsWith(".xml")) {
-                Document doc = parse(artifact);
-                String name = doc.getDocumentElement().getLocalName();
-                String uri  = doc.getDocumentElement().getNamespaceURI();
-                if ("features".equals(name) && (uri == null || "".equals(uri) || uri.startsWith("http://karaf.apache.org/xmlns/features/v"))) {
-                    return true;
-                }
-            }
-        } catch (Exception e) {
-            LOGGER.debug("File '{}' is not a features file.", artifact.getName(), e);
-        }
-        return false;
-    }
-    
-    /**
-     * Parse a features XML.
-     *
-     * @param artifact the features XML to parse.
-     * @return the parsed document.
-     * @throws Exception in case of parsing failure.
-     */
-    private Document parse(File artifact) throws Exception {
-        DocumentBuilder db = dbf.newDocumentBuilder();
-        db.setErrorHandler(new ErrorHandler() {
-            public void warning(SAXParseException exception) throws SAXException {
-            }
-            public void error(SAXParseException exception) throws SAXException {
-            }
-            public void fatalError(SAXParseException exception) throws SAXException {
-                throw exception;
-            }
-        });
-        return db.parse(artifact);
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/f13d140c/kar/core/src/main/java/org/apache/karaf/kar/internal/Kar.java
----------------------------------------------------------------------
diff --git a/kar/core/src/main/java/org/apache/karaf/kar/internal/Kar.java b/kar/core/src/main/java/org/apache/karaf/kar/internal/Kar.java
deleted file mode 100644
index 005cd17..0000000
--- a/kar/core/src/main/java/org/apache/karaf/kar/internal/Kar.java
+++ /dev/null
@@ -1,203 +0,0 @@
-/*
- * 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.karaf.kar.internal;
-
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.net.MalformedURLException;
-import java.net.URI;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.jar.Attributes;
-import java.util.jar.JarInputStream;
-import java.util.jar.Manifest;
-import java.util.zip.ZipEntry;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Representation of a Karaf Kar archive
- * 
- * A Kar archive is a jar file with a special structure that can be used
- * to deploy feature repositories, maven repo contents and resources for the
- * karaf installation.
- * 
- * meta-inf/Manifest: 
- *   Karaf-Feature-Start: (true|false) Controls if the features in the feature repos should be started on deploy
- *   Karaf-Feature-Repos: (uri)* If present then only the given feature repo urls are added to karaf if it is not
- *      present then the karaf file is scanned for repo files
- *      
- * repository/
- *   Everything below this directory is treated as a maven repository. On deploy the contents
- *   will be copied to a directory below data. This directory will then be added to the 
- *   maven repos of pax url maven
- *   
- * resource/
- *   Everything below this directory will be copied to the karaf base dir on deploy
- * 
- */
-public class Kar {
-
-    public static final Logger LOGGER = LoggerFactory.getLogger(KarServiceImpl.class);
-    public static final String MANIFEST_ATTR_KARAF_FEATURE_START = "Karaf-Feature-Start";
-    public static final String MANIFEST_ATTR_KARAF_FEATURE_REPOS = "Karaf-Feature-Repos";
-    private final URI karUri;
-    private boolean shouldInstallFeatures;
-    private List<URI> featureRepos;
-
-    public Kar(URI karUri) {
-        this.karUri = karUri;
-    }
-
-    /**
-     * Extract a kar from a given URI into a repository dir and resource dir
-     * and populate shouldInstallFeatures and featureRepos
-     *
-     * @param repoDir directory to write the repository contents of the kar to
-     * @param resourceDir directory to write the resource contents of the kar to
-     */
-    public void extract(File repoDir, File resourceDir) {
-        InputStream is = null;
-        JarInputStream zipIs = null;
-        FeatureDetector featureDetector = new FeatureDetector();
-        this.featureRepos = new ArrayList<URI>();
-        this.shouldInstallFeatures = true;
-
-        try {
-            is = karUri.toURL().openStream();
-            repoDir.mkdirs();
-
-            if (!repoDir.isDirectory()) {
-                throw new RuntimeException("The KAR file " + karUri + " is already installed");
-            }
-
-            LOGGER.debug("Uncompress the KAR file {} into directory {}", karUri, repoDir);
-            zipIs = new JarInputStream(is);
-            boolean scanForRepos = true;
-
-            Manifest manifest = zipIs.getManifest();
-            if (manifest != null) {
-                Attributes attr = manifest.getMainAttributes();
-                String featureStartSt = (String)attr
-                    .get(new Attributes.Name(MANIFEST_ATTR_KARAF_FEATURE_START));
-                if ("false".equals(featureStartSt)) {
-                    shouldInstallFeatures = false;
-                }
-                String featureReposAttr = (String)attr
-                    .get(new Attributes.Name(MANIFEST_ATTR_KARAF_FEATURE_REPOS));
-                if (featureReposAttr != null) {
-                    featureRepos.add(new URI(featureReposAttr));
-                    scanForRepos = false;
-                }
-            }
-
-            ZipEntry entry = zipIs.getNextEntry();
-            while (entry != null) {
-                if (entry.getName().startsWith("repository")) {
-                    String path = entry.getName().substring("repository/".length());
-                    File destFile = new File(repoDir, path);
-                    extract(zipIs, entry, destFile);
-                    if (scanForRepos && featureDetector.isFeaturesRepository(destFile)) {
-                        featureRepos.add(destFile.toURI());
-                    }
-                }
-
-                if (entry.getName().startsWith("resource")) {
-                    String path = entry.getName().substring("resource/".length());
-                    File destFile = new File(resourceDir, path);
-                    extract(zipIs, entry, destFile);
-                }
-                entry = zipIs.getNextEntry();
-            }
-        } catch (Exception e) {
-            throw new RuntimeException("Error extracting kar file " + karUri + " into dir " + repoDir + ": " + e.getMessage(), e);
-        } finally {
-            closeStream(zipIs);
-            closeStream(is);
-        }
-    }
-
-    /**
-     * Extract an entry from a KAR file
-     * 
-     * @param is
-     * @param zipEntry
-     * @param dest
-     * @return
-     * @throws Exception
-     */
-    private static File extract(InputStream is, ZipEntry zipEntry, File dest) throws Exception {
-        if (zipEntry.isDirectory()) {
-            LOGGER.debug("Creating directory {}", dest.getName());
-            dest.mkdirs();
-        } else {
-            dest.getParentFile().mkdirs();
-            FileOutputStream out = new FileOutputStream(dest);
-            copyStream(is, out);
-            out.close();
-        }
-        return dest;
-    }
-
-    private static void closeStream(InputStream is) {
-        if (is != null) {
-            try {
-                is.close();
-            } catch (IOException e) {
-                LOGGER.warn("Error closing stream", e);
-            }
-        }
-    }
-
-    static long copyStream(InputStream input, OutputStream output) throws IOException {
-        byte[] buffer = new byte[10000];
-        long count = 0;
-        int n = 0;
-        while (-1 != (n = input.read(buffer))) {
-            output.write(buffer, 0, n);
-            count += n;
-        }
-        return count;
-    }
-
-    public String getKarName() {
-        try {
-            String karName = new File(karUri.toURL().getFile()).getName();
-            karName = karName.substring(0, karName.lastIndexOf("."));
-            return karName;
-        } catch (MalformedURLException e) {
-            throw new RuntimeException("Invalid kar URI " + karUri, e);
-        }
-    }
-    
-    public URI getKarUri() {
-        return karUri;
-    }
-
-    public boolean isShouldInstallFeatures() {
-        return shouldInstallFeatures;
-    }
-
-    public List<URI> getFeatureRepos() {
-        return featureRepos;
-    } 
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/f13d140c/kar/core/src/main/java/org/apache/karaf/kar/internal/KarServiceImpl.java
----------------------------------------------------------------------
diff --git a/kar/core/src/main/java/org/apache/karaf/kar/internal/KarServiceImpl.java b/kar/core/src/main/java/org/apache/karaf/kar/internal/KarServiceImpl.java
deleted file mode 100644
index 0f86466..0000000
--- a/kar/core/src/main/java/org/apache/karaf/kar/internal/KarServiceImpl.java
+++ /dev/null
@@ -1,382 +0,0 @@
-/*
- * 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.karaf.kar.internal;
-
-import java.io.BufferedOutputStream;
-import java.io.BufferedReader;
-import java.io.ByteArrayInputStream;
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.FileReader;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.PrintStream;
-import java.io.UnsupportedEncodingException;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.util.ArrayList;
-import java.util.EnumSet;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.jar.JarEntry;
-import java.util.jar.JarOutputStream;
-import java.util.jar.Manifest;
-
-import org.apache.karaf.features.BundleInfo;
-import org.apache.karaf.features.ConfigFileInfo;
-import org.apache.karaf.features.Dependency;
-import org.apache.karaf.features.Feature;
-import org.apache.karaf.features.FeaturesService;
-import org.apache.karaf.features.Repository;
-import org.apache.karaf.kar.KarService;
-import org.apache.karaf.util.maven.Parser;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Implementation of the KAR service.
- */
-public class KarServiceImpl implements KarService {
-    private static final String FEATURE_CONFIG_FILE = "features.cfg";
-    private static final Logger LOGGER = LoggerFactory.getLogger(KarServiceImpl.class);
-
-    private File storage;
-    private File base;
-    private FeaturesService featuresService;
-    
-    private boolean noAutoRefreshBundles;
-
-    public KarServiceImpl(String karafBase, FeaturesService featuresService) {
-        this.base = new File(karafBase);
-        this.storage = new File(this.base, "data" + File.separator + "kar");
-        this.featuresService = featuresService;
-        this.storage.mkdirs();
-        if (!storage.isDirectory()) {
-            throw new IllegalStateException("KAR storage " + storage + " is not a directory");
-        }
-    }
-    
-    @Override
-    public void install(URI karUri) throws Exception {
-        String karName = new Kar(karUri).getKarName();
-        LOGGER.debug("Installing KAR {} from {}", karName, karUri);
-        File karDir = new File(storage, karName);
-        install(karUri, karDir, base);
-    }
-    
-    @Override
-    public void install(URI karUri, File repoDir, File resourceDir) throws Exception {
-        Kar kar = new Kar(karUri);
-        kar.extract(repoDir, resourceDir);
-        writeToFile(kar.getFeatureRepos(), new File(repoDir, FEATURE_CONFIG_FILE));
-        for (URI uri : kar.getFeatureRepos()) {
-            addToFeaturesRepositories(uri);
-        }
-        if (kar.isShouldInstallFeatures()) {
-            installFeatures(kar.getFeatureRepos());
-        }
-
-    }
-
-
-    private List<URI> readFromFile(File repoListFile) {
-        ArrayList<URI> uriList = new ArrayList<URI>();
-        FileReader fr = null;
-        try {
-            fr = new FileReader(repoListFile);
-            BufferedReader br = new BufferedReader(fr);
-            String line;
-            while ((line = br.readLine()) != null) {
-                uriList.add(new URI(line));
-            }
-        } catch (Exception e) {
-            throw new RuntimeException("Error reading repo list from file " + repoListFile.getAbsolutePath(), e);
-        } finally {
-            try {
-                fr.close();
-            } catch (IOException e) {
-                LOGGER.warn("Error closing reader for file " + repoListFile, e);
-            }
-        }
-        return uriList;
-    }
-    
-    private void writeToFile(List<URI> featuresRepositoriesInKar, File repoListFile) {
-        FileOutputStream fos = null;
-        PrintStream ps = null;
-        try {
-            fos = new FileOutputStream(repoListFile);
-            ps = new PrintStream(fos);
-            for (URI uri : featuresRepositoriesInKar) {
-                ps.println(uri);
-            }
-            ps.close();
-            fos.close();
-        } catch (Exception e) {
-            throw new RuntimeException("Error writing feature repo list to file " + repoListFile.getAbsolutePath(), e);
-        } finally {
-            closeStream(ps);
-            closeStream(fos);
-        }
-    }
-
-    private void deleteRecursively(File dir) {
-        if (dir.isDirectory()) {
-            File[] children = dir.listFiles();
-            for (File child : children) {
-                deleteRecursively(child);
-            }
-        }
-        dir.delete();
-    }
-
-    @Override
-    public void uninstall(String karName) throws Exception {
-        File karDir = new File(storage, karName);
-
-        if (!karDir.exists()) {
-            throw new IllegalArgumentException("The KAR " + karName + " is not installed");
-        }
-
-        List<URI> featuresRepositories = readFromFile(new File(karDir, FEATURE_CONFIG_FILE));
-        uninstallFeatures(featuresRepositories);
-        for (URI featuresRepository : featuresRepositories) {
-            featuresService.removeRepository(featuresRepository);
-        }
-        
-        deleteRecursively(karDir);
-    }
-    
-    @Override
-    public List<String> list() throws Exception {
-        List<String> kars = new ArrayList<String>();
-        for (File kar : storage.listFiles()) {
-            if (kar.isDirectory()) {
-                kars.add(kar.getName());
-            }
-        }
-        return kars;
-    }
-
-
-
-    /**
-     * Add an URI to the list of features repositories.
-     *
-     * @param uri the URI to add.
-     * @throws Exception in case of add failure.
-     */
-    private void addToFeaturesRepositories(URI uri) throws Exception {
-        try {
-            featuresService.removeRepository(uri);
-            featuresService.addRepository(uri);
-            LOGGER.info("Added feature repository '{}'", uri);
-        } catch (Exception e) {
-            LOGGER.warn("Unable to add repository '{}'", uri, e);
-        }
-    }
-
-    /**
-     * Install all features contained in the list of features XML.
-     *
-     * @param featuresRepositories the list of features XML.
-     */
-    private void installFeatures(List<URI> featuresRepositories) throws Exception {
-        for (Repository repository : featuresService.listRepositories()) {
-            for (URI karFeatureRepoUri : featuresRepositories) {
-                if (repository.getURI().equals(karFeatureRepoUri)) {
-                    try {
-                        for (Feature feature : repository.getFeatures()) {
-                            try {
-                                LOGGER.debug("noAutoRefreshBundles is " + isNoAutoRefreshBundles());
-                                if (isNoAutoRefreshBundles()) {
-                                    featuresService.installFeature(feature, EnumSet.of(FeaturesService.Option.NoAutoRefreshBundles));
-                                } else {
-                                    featuresService.installFeature(feature, EnumSet.noneOf(FeaturesService.Option.class));
-                                }
-                            } catch (Exception e) {
-                                LOGGER.warn("Unable to install Kar feature {}", feature.getName() + "/" + feature.getVersion(), e);
-                            }
-                        }
-                    } catch (Exception e) {
-                        LOGGER.warn("Can't get features for KAR {}", karFeatureRepoUri, e);
-                    }
-                }
-            }
-        }
-    }
-    
-    @Override
-    public void create(String repoName, List<String> features, PrintStream console) {
-        FileOutputStream fos = null;
-        JarOutputStream jos = null;
-        try {
-            Repository repo = featuresService.getRepository(repoName);
-            if (repo == null) {
-                throw new RuntimeException("Could not find a repository with name " + repoName);
-            }
-            String karPath = storage + File.separator + repoName + ".kar";
-            File karFile = new File(karPath);
-            karFile.getParentFile().mkdirs();
-            fos = new FileOutputStream(karFile);
-            Manifest manifest = createNonAutoStartManifest(repo.getURI());
-            jos = new JarOutputStream(new BufferedOutputStream(fos, 100000), manifest);
-            
-            Map<URI, Integer> locationMap = new HashMap<URI, Integer>();
-            copyResourceToJar(jos, repo.getURI(), locationMap);
-        
-            Map<String, Feature> featureMap = new HashMap<String, Feature>();
-            for (Feature feature : repo.getFeatures()) {
-                featureMap.put(feature.getName(), feature);
-            }
-            
-            Set<Feature> featuresToCopy = getFeatures(featureMap, features, 1);
-            
-            for (Feature feature : featuresToCopy) {
-                if (console != null)
-                    console.println("Adding feature " + feature.getName());
-                copyFeatureToJar(jos, feature, locationMap);
-            }
-
-            if (console != null)
-                console.println("Kar file created : " + karPath);
-        } catch (Exception e) {
-            throw new RuntimeException("Error creating kar: " + e.getMessage(), e);
-        } finally {
-            closeStream(jos);
-            closeStream(fos);
-        }
-        
-    }
-
-    private Set<Feature> getFeatures(Map<String, Feature> featureMap, List<String> features, int depth) {
-        Set<Feature> featureSet = new HashSet<Feature>();
-        if (depth > 5) {
-            // Break after some recursions to avoid endless loops 
-            return featureSet;
-        }
-        if (features == null) {
-            featureSet.addAll(featureMap.values());
-            return featureSet;
-        }
-        for (String featureName : features) {
-            Feature feature = featureMap.get(featureName);
-            if (feature == null) {
-                System.out.println("Feature " + featureName + " not found in repository.");
-                //throw new RuntimeException();
-            } else {
-                featureSet.add(feature);
-                List<Dependency> deps = feature.getDependencies();
-                List<String> depNames = new ArrayList<String>();
-                for (Dependency dependency : deps) {
-                    depNames.add(dependency.getName());
-                }
-                featureSet.addAll(getFeatures(featureMap, depNames, depth ++));
-            }
-        }
-        return featureSet;
-    }
-
-    private Manifest createNonAutoStartManifest(URI repoUri) throws UnsupportedEncodingException, IOException {
-        String manifestSt = "Manifest-Version: 1.0\n" +
-            Kar.MANIFEST_ATTR_KARAF_FEATURE_START +": false\n" +
-            Kar.MANIFEST_ATTR_KARAF_FEATURE_REPOS + ": " + repoUri.toString() + "\n";
-        InputStream manifestIs = new ByteArrayInputStream(manifestSt.getBytes("UTF-8"));
-        Manifest manifest = new Manifest(manifestIs);
-        return manifest;
-    }
-
-    private void closeStream(OutputStream os) {
-        if (os != null) {
-            try {
-                os.close();
-            } catch (IOException e) {
-                LOGGER.warn("Error closing stream", e);
-            }
-        }
-    }
-
-    private void copyFeatureToJar(JarOutputStream jos, Feature feature, Map<URI, Integer> locationMap)
-        throws URISyntaxException {
-        for (BundleInfo bundleInfo : feature.getBundles()) {
-            URI location = new URI(bundleInfo.getLocation());
-            copyResourceToJar(jos, location, locationMap);
-        }
-        for (ConfigFileInfo configFileInfo : feature.getConfigurationFiles()) {
-            URI location = new URI(configFileInfo.getLocation());
-            copyResourceToJar(jos, location, locationMap);
-        }
-    }
-
-    private void copyResourceToJar(JarOutputStream jos, URI location, Map<URI, Integer> locationMap) {
-        if (locationMap.containsKey(location)) {
-            return;
-        }
-        try {
-            String noPrefixLocation = location.toString().substring(location.toString().lastIndexOf(":") + 1);
-            Parser parser = new Parser(noPrefixLocation);
-            InputStream is = location.toURL().openStream();
-            String path = "repository/" + parser.getArtifactPath();
-            jos.putNextEntry(new JarEntry(path));
-            Kar.copyStream(is, jos);
-            is.close();
-            locationMap.put(location, 1);
-        } catch (Exception e) {
-            LOGGER.error("Error adding " + location, e);
-        }
-    }
-
-    /**
-     * Uninstall all features contained in the list of features XML.
-     *
-     * @param featuresRepositories the list of features XML.
-     */
-    private void uninstallFeatures(List<URI> featuresRepositories) throws Exception {
-        for (Repository repository : featuresService.listRepositories()) {
-            for (URI karFeatureRepoUri : featuresRepositories) {
-                if (repository.getURI().equals(karFeatureRepoUri)) {
-                    try {
-                        for (Feature feature : repository.getFeatures()) {
-                            try {
-                                featuresService.uninstallFeature(feature.getName(), feature.getVersion());
-                            } catch (Exception e) {
-                                LOGGER.warn("Unable to uninstall Kar feature {}", feature.getName() + "/" + feature.getVersion(), e);
-                            }
-                        }
-                    } catch (Exception e) {
-                        LOGGER.warn("Can't get features for KAR {}", karFeatureRepoUri, e);
-                    }
-                }
-            }
-        }
-    }
-
-    public boolean isNoAutoRefreshBundles() {
-        return noAutoRefreshBundles;
-    }
-
-    public void setNoAutoRefreshBundles(boolean noAutoRefreshBundles) {
-        this.noAutoRefreshBundles = noAutoRefreshBundles;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/f13d140c/kar/core/src/main/java/org/apache/karaf/kar/internal/KarsMBeanImpl.java
----------------------------------------------------------------------
diff --git a/kar/core/src/main/java/org/apache/karaf/kar/internal/KarsMBeanImpl.java b/kar/core/src/main/java/org/apache/karaf/kar/internal/KarsMBeanImpl.java
deleted file mode 100644
index b274e21..0000000
--- a/kar/core/src/main/java/org/apache/karaf/kar/internal/KarsMBeanImpl.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * 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.karaf.kar.internal;
-
-import org.apache.karaf.kar.KarService;
-import org.apache.karaf.kar.KarsMBean;
-
-import javax.management.MBeanException;
-import javax.management.NotCompliantMBeanException;
-import javax.management.StandardMBean;
-import java.net.URI;
-import java.util.List;
-
-public class KarsMBeanImpl extends StandardMBean implements KarsMBean {
-
-    private KarService karService;
-
-    public KarsMBeanImpl() throws NotCompliantMBeanException {
-        super(KarsMBean.class);
-    }
-
-    public List<String> getKars() throws MBeanException {
-        try {
-            return karService.list();
-        } catch (Exception e) {
-            throw new MBeanException(null, e.getMessage());
-        }
-    }
-
-    public void create(String repoName, List<String> features) {
-        karService.create(repoName, features, null);
-    }
-
-    public void install(String url) throws MBeanException {
-        try {
-            karService.install(new URI(url));
-        } catch (Exception e) {
-            throw new MBeanException(null, e.getMessage());
-        }
-    }
-
-    public void uninstall(String name) throws MBeanException {
-        try {
-            karService.uninstall(name);
-        } catch (Exception e) {
-            throw new MBeanException(null, e.getMessage());
-        }
-    }
-
-    public KarService getKarService() {
-        return karService;
-    }
-
-    public void setKarService(KarService karService) {
-        this.karService = karService;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/f13d140c/kar/core/src/main/java/org/apache/karaf/kar/internal/osgi/Activator.java
----------------------------------------------------------------------
diff --git a/kar/core/src/main/java/org/apache/karaf/kar/internal/osgi/Activator.java b/kar/core/src/main/java/org/apache/karaf/kar/internal/osgi/Activator.java
deleted file mode 100644
index 05a1b59..0000000
--- a/kar/core/src/main/java/org/apache/karaf/kar/internal/osgi/Activator.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * 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.karaf.kar.internal.osgi;
-
-import org.apache.karaf.features.FeaturesService;
-import org.apache.karaf.kar.KarService;
-import org.apache.karaf.kar.internal.KarServiceImpl;
-import org.apache.karaf.kar.internal.KarsMBeanImpl;
-import org.apache.karaf.util.tracker.BaseActivator;
-import org.osgi.service.cm.ManagedService;
-
-public class Activator extends BaseActivator implements ManagedService {
-
-    @Override
-    protected void doOpen() throws Exception {
-        manage("org.apache.karaf.kar");
-        trackService(FeaturesService.class);
-    }
-
-    protected void doStart() throws Exception {
-        FeaturesService featuresService = getTrackedService(FeaturesService.class);
-        if (featuresService == null) {
-            return;
-        }
-
-        boolean noAutoRefreshBundles = getBoolean("noAutoRefreshBundles", false);
-
-        KarServiceImpl karService = new KarServiceImpl(
-                System.getProperty("karaf.base"),
-                featuresService
-        );
-        karService.setNoAutoRefreshBundles(noAutoRefreshBundles);
-        register(KarService.class, karService);
-
-        KarsMBeanImpl mbean = new KarsMBeanImpl();
-        mbean.setKarService(karService);
-        registerMBean(mbean, "type=kar");
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/f13d140c/kar/core/src/main/resources/OSGI-INF/bundle.info
----------------------------------------------------------------------
diff --git a/kar/core/src/main/resources/OSGI-INF/bundle.info b/kar/core/src/main/resources/OSGI-INF/bundle.info
deleted file mode 100644
index 7056453..0000000
--- a/kar/core/src/main/resources/OSGI-INF/bundle.info
+++ /dev/null
@@ -1,19 +0,0 @@
-h1. Synopsis
-
-${project.name}
-
-${project.description}
-
-Maven URL:
-[mvn:${project.groupId}/${project.artifactId}/${project.version}]
-
-h1. Description
-
-This bundle is the core implementation of the Karaf kar support.
-
-Karaf Archives (KAR) is an artifact (zip file) shipping a features XML and the associated bundles or configuration
-files.
-
-h1. See also
-
-KAR - section of the Karaf User Guide

http://git-wip-us.apache.org/repos/asf/karaf/blob/f13d140c/kar/pom.xml
----------------------------------------------------------------------
diff --git a/kar/pom.xml b/kar/pom.xml
index 44a8f77..78629f6 100644
--- a/kar/pom.xml
+++ b/kar/pom.xml
@@ -29,13 +29,99 @@
     </parent>
 
     <groupId>org.apache.karaf.kar</groupId>
-    <artifactId>kar</artifactId>
-    <packaging>pom</packaging>
-    <name>Apache Karaf :: KAR</name>
-
-    <modules>
-        <module>core</module>
-        <module>command</module>
-    </modules>
+    <artifactId>org.apache.karaf.kar.core</artifactId>
+    <packaging>bundle</packaging>
+    <name>Apache Karaf :: KAR :: Core</name>
+    <description>This bundle provides core implementation of the KAR management service.</description>
+
+    <properties>
+        <appendedResourcesDirectory>${basedir}/../../etc/appended-resources</appendedResourcesDirectory>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.felix</groupId>
+            <artifactId>org.apache.felix.utils</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.karaf</groupId>
+            <artifactId>org.apache.karaf.util</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>org.osgi.core</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>org.osgi.compendium</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.ops4j.pax.swissbox</groupId>
+            <artifactId>pax-swissbox-property</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.karaf.features</groupId>
+            <artifactId>org.apache.karaf.features.core</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-api</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.karaf.shell</groupId>
+            <artifactId>org.apache.karaf.shell.core</artifactId>
+            <optional>true</optional>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <resources>
+            <resource>
+                <directory>${project.basedir}/src/main/resources</directory>
+                <includes>
+                    <include>**/*</include>
+                </includes>
+            </resource>
+            <resource>
+                <directory>${project.basedir}/src/main/resources</directory>
+                <filtering>true</filtering>
+                <includes>
+                    <include>**/*.info</include>
+                </includes>
+            </resource>
+        </resources>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+                <configuration>
+                    <instructions>
+                        <Export-Package>
+                            org.apache.karaf.kar
+                        </Export-Package>
+                        <Private-Package>
+                            org.apache.karaf.kar.command,
+                            org.apache.karaf.kar.command.completers,
+                            org.apache.karaf.kar.internal,
+                            org.apache.karaf.kar.internal.osgi,
+                            org.apache.karaf.util.maven,
+                            org.apache.karaf.util.tracker,
+                            org.apache.felix.utils.properties
+                        </Private-Package>
+                        <Bundle-Activator>
+                            org.apache.karaf.kar.internal.osgi.Activator
+                        </Bundle-Activator>
+                        <Karaf-Commands>org.apache.karaf.kar.command.*</Karaf-Commands>
+                    </instructions>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
 
 </project>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/karaf/blob/f13d140c/kar/src/main/java/org/apache/karaf/kar/KarService.java
----------------------------------------------------------------------
diff --git a/kar/src/main/java/org/apache/karaf/kar/KarService.java b/kar/src/main/java/org/apache/karaf/kar/KarService.java
new file mode 100644
index 0000000..60acb77
--- /dev/null
+++ b/kar/src/main/java/org/apache/karaf/kar/KarService.java
@@ -0,0 +1,80 @@
+/*
+ * 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.karaf.kar;
+
+import java.io.File;
+import java.io.PrintStream;
+import java.net.URI;
+import java.util.List;
+
+/**
+ * The service managing KAR.
+ */
+public interface KarService {
+
+    /**
+     * Install KAR from a given URI
+     * 
+     * Resources will be copied to the karaf base dir
+     * Repository contents will be copied to a subdir in the 
+     * karaf data directory
+     *
+     * @param karUri Uri of the kar to be installed
+     * @throws Exception in case of installation failure.
+     */
+    void install(URI karUri) throws Exception;
+    
+    /**
+     * Install a kar with manually given repository and 
+     * resource directories.
+     * 
+     * @param karUri Uri of the kar to be installed
+     * @param repoDir destination for the repository contents of the kar
+     * @param resourceDir destination for the resource contents of the kar
+     * @throws Exception
+     */
+    void install(URI karUri, File repoDir, File resourceDir) throws Exception;
+
+    /**
+     * Uninstall the given KAR
+     *
+     * @param name the name of the KAR
+     * @throws Exception in case of failure
+     */
+    void uninstall(String name) throws Exception;
+
+    /**
+     * List the KAR stored in the data folder.
+     * 
+     * @return the list of KAR stored.
+     * @throws Exception in case of listing failure.
+     */
+    List<String> list() throws Exception;
+    
+    /**
+     * Create a kar from the given feature and repo names.
+     * Each named feature including all transitive deps will be added.
+     * For each named repo all features in the repo and their transitive deps will be added.
+     * 
+     * @param repoName
+     * @param features 
+     * @param console
+     */
+    void create(String repoName, List<String> features, PrintStream console);
+
+    
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/f13d140c/kar/src/main/java/org/apache/karaf/kar/KarsMBean.java
----------------------------------------------------------------------
diff --git a/kar/src/main/java/org/apache/karaf/kar/KarsMBean.java b/kar/src/main/java/org/apache/karaf/kar/KarsMBean.java
new file mode 100644
index 0000000..b1a86c9
--- /dev/null
+++ b/kar/src/main/java/org/apache/karaf/kar/KarsMBean.java
@@ -0,0 +1,57 @@
+/*
+ * 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.karaf.kar;
+
+import javax.management.MBeanException;
+import java.util.List;
+
+public interface KarsMBean {
+
+    /**
+     * List the installed KAR files.
+     *
+     * @return the list of KAR files.
+     * @throws Exception in case of listing failure.
+     */
+    List<String> getKars() throws MBeanException;
+
+    /**
+     * Create a kar file for a list of feature repos
+     *
+     * @param repoName the name of features repository
+     * @param features the features to include in the kar
+     * @throws Exception in case of creation failure
+     */
+    void create(String repoName, List<String> features);
+
+    /**
+     * Install a KAR file from the given URL.
+     *
+     * @param url the JAR URL.
+     * @throws Exception in case of installation failure.
+     */
+    void install(String url) throws MBeanException;
+
+    /**
+     * Uninstall a KAR file.
+     * 
+     * @param name the name of the KAR file.
+     * @throws Exception in case of uninstall failure.
+     */
+    void uninstall(String name) throws MBeanException;
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/f13d140c/kar/src/main/java/org/apache/karaf/kar/command/CreateKarCommand.java
----------------------------------------------------------------------
diff --git a/kar/src/main/java/org/apache/karaf/kar/command/CreateKarCommand.java b/kar/src/main/java/org/apache/karaf/kar/command/CreateKarCommand.java
new file mode 100644
index 0000000..a93706c
--- /dev/null
+++ b/kar/src/main/java/org/apache/karaf/kar/command/CreateKarCommand.java
@@ -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.karaf.kar.command;
+
+import java.util.List;
+
+import org.apache.karaf.features.command.completers.InstalledRepoNameCompleter;
+import org.apache.karaf.kar.KarService;
+import org.apache.karaf.shell.api.action.Action;
+import org.apache.karaf.shell.api.action.Argument;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.Completion;
+import org.apache.karaf.shell.api.action.lifecycle.Reference;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+
+@Command(scope = "kar", name = "create", description = "Create a kar file for a list of feature repos")
+@Service
+public class CreateKarCommand implements Action {
+    
+    @Argument(index = 0, name = "repoName", description = "Repository name. The kar will contain all features of the named repository by default", required = true, multiValued = false)
+    @Completion(InstalledRepoNameCompleter.class)
+    private String repoName;
+    
+    @Argument(index = 1, name = "features", description = "Names of the features to include. If set then only these features will be added", required = false, multiValued = true)
+    private List<String> features;
+
+    @Reference
+    private KarService karService;
+
+    @Override
+    public Object execute() throws Exception {
+        karService.create(repoName, features, System.out);
+        return null;
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/f13d140c/kar/src/main/java/org/apache/karaf/kar/command/InstallKarCommand.java
----------------------------------------------------------------------
diff --git a/kar/src/main/java/org/apache/karaf/kar/command/InstallKarCommand.java b/kar/src/main/java/org/apache/karaf/kar/command/InstallKarCommand.java
new file mode 100644
index 0000000..806367a
--- /dev/null
+++ b/kar/src/main/java/org/apache/karaf/kar/command/InstallKarCommand.java
@@ -0,0 +1,43 @@
+/*
+ * 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.karaf.kar.command;
+
+import org.apache.karaf.kar.KarService;
+import org.apache.karaf.shell.api.action.Action;
+import org.apache.karaf.shell.api.action.Argument;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.lifecycle.Reference;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+
+import java.net.URI;
+
+@Command(scope = "kar", name = "install", description = "Installs a KAR file.")
+@Service
+public class InstallKarCommand implements Action {
+
+    @Argument(index = 0, name = "url", description = "The URL of the KAR file to install.", required = true, multiValued = false)
+    private String url;
+
+    @Reference
+    private KarService karService;
+
+    public Object execute() throws Exception {
+        karService.install(new URI(url));
+        return null;
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/f13d140c/kar/src/main/java/org/apache/karaf/kar/command/ListKarCommand.java
----------------------------------------------------------------------
diff --git a/kar/src/main/java/org/apache/karaf/kar/command/ListKarCommand.java b/kar/src/main/java/org/apache/karaf/kar/command/ListKarCommand.java
new file mode 100644
index 0000000..98813ff
--- /dev/null
+++ b/kar/src/main/java/org/apache/karaf/kar/command/ListKarCommand.java
@@ -0,0 +1,52 @@
+/*
+ * 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.karaf.kar.command;
+
+import org.apache.karaf.kar.KarService;
+import org.apache.karaf.shell.api.action.Action;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.Option;
+import org.apache.karaf.shell.api.action.lifecycle.Reference;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.apache.karaf.shell.support.table.ShellTable;
+
+@Command(scope = "kar", name = "list", description = "List the installed KAR files.")
+@Service
+public class ListKarCommand implements Action {
+
+    @Option(name = "--no-format", description = "Disable table rendered output", required = false, multiValued = false)
+    boolean noFormat;
+
+    @Reference
+    private KarService karService;
+
+    @Override
+    public Object execute() throws Exception {
+
+        ShellTable table = new ShellTable();
+        table.column("KAR Name");
+
+        for (String karName : karService.list()) {
+            table.addRow().addContent(karName);
+        }
+
+        table.print(System.out, !noFormat);
+
+        return null;
+    }
+    
+}


[57/59] [abbrv] [KARAF-2852] Merge jndi/core and jndi/command

Posted by gn...@apache.org.
http://git-wip-us.apache.org/repos/asf/karaf/blob/85c65dd6/jndi/src/main/java/org/apache/karaf/jndi/command/AliasCommand.java
----------------------------------------------------------------------
diff --git a/jndi/src/main/java/org/apache/karaf/jndi/command/AliasCommand.java b/jndi/src/main/java/org/apache/karaf/jndi/command/AliasCommand.java
new file mode 100644
index 0000000..08e3912
--- /dev/null
+++ b/jndi/src/main/java/org/apache/karaf/jndi/command/AliasCommand.java
@@ -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.karaf.jndi.command;
+
+import org.apache.karaf.jndi.JndiService;
+import org.apache.karaf.jndi.command.completers.ContextsCompleter;
+import org.apache.karaf.jndi.command.completers.NamesCompleter;
+import org.apache.karaf.shell.api.action.Action;
+import org.apache.karaf.shell.api.action.Argument;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.Completion;
+import org.apache.karaf.shell.api.action.lifecycle.Reference;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+
+@Command(scope = "jndi", name = "alias", description = "Create a JNDI alias on a given name.")
+@Service
+public class AliasCommand implements Action {
+
+    @Argument(index = 0, name = "name", description = "The JNDI name", required = true, multiValued = false)
+    @Completion(NamesCompleter.class)
+    String name;
+
+    @Argument(index = 1, name = "alias", description = "The JNDI alias", required = true, multiValued = false)
+    @Completion(ContextsCompleter.class)
+    String alias;
+
+    @Reference
+    JndiService jndiService;
+
+    @Override
+    public Object execute() throws Exception {
+        jndiService.alias(name, alias);
+        return null;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/85c65dd6/jndi/src/main/java/org/apache/karaf/jndi/command/BindCommand.java
----------------------------------------------------------------------
diff --git a/jndi/src/main/java/org/apache/karaf/jndi/command/BindCommand.java b/jndi/src/main/java/org/apache/karaf/jndi/command/BindCommand.java
new file mode 100644
index 0000000..b181762
--- /dev/null
+++ b/jndi/src/main/java/org/apache/karaf/jndi/command/BindCommand.java
@@ -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.karaf.jndi.command;
+
+import org.apache.karaf.jndi.JndiService;
+import org.apache.karaf.jndi.command.completers.ContextsCompleter;
+import org.apache.karaf.jndi.command.completers.ServicesIdCompleter;
+import org.apache.karaf.shell.api.action.Action;
+import org.apache.karaf.shell.api.action.Argument;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.Completion;
+import org.apache.karaf.shell.api.action.lifecycle.Reference;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+
+@Command(scope = "jndi", name = "bind", description = "Bind an OSGi service in the JNDI context")
+@Service
+public class BindCommand implements Action {
+
+    @Argument(index = 0, name = "service", description = "The ID of the OSGi service to bind", required = true, multiValued = false)
+    @Completion(ServicesIdCompleter.class)
+    Long serviceId;
+
+    @Argument(index = 1, name = "name", description = "The JNDI name to bind the OSGi service", required = true, multiValued = false)
+    @Completion(ContextsCompleter.class)
+    String name;
+
+    @Reference
+    JndiService jndiService;
+
+    @Override
+    public Object execute() throws Exception {
+        jndiService.bind(serviceId, name);
+        return null;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/85c65dd6/jndi/src/main/java/org/apache/karaf/jndi/command/ContextsCommand.java
----------------------------------------------------------------------
diff --git a/jndi/src/main/java/org/apache/karaf/jndi/command/ContextsCommand.java b/jndi/src/main/java/org/apache/karaf/jndi/command/ContextsCommand.java
new file mode 100644
index 0000000..2209479
--- /dev/null
+++ b/jndi/src/main/java/org/apache/karaf/jndi/command/ContextsCommand.java
@@ -0,0 +1,64 @@
+/*
+ * 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.karaf.jndi.command;
+
+import org.apache.karaf.jndi.JndiService;
+import org.apache.karaf.jndi.command.completers.ContextsCompleter;
+import org.apache.karaf.shell.api.action.Action;
+import org.apache.karaf.shell.api.action.Argument;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.Completion;
+import org.apache.karaf.shell.api.action.lifecycle.Reference;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.apache.karaf.shell.support.table.ShellTable;
+
+import java.util.List;
+
+@Command(scope = "jndi", name = "contexts", description = "List the JNDI sub-contexts.")
+@Service
+public class ContextsCommand implements Action {
+
+    @Argument(index = 0, name = "context", description = "The base JNDI context", required = false, multiValued = false)
+    @Completion(ContextsCompleter.class)
+    String context;
+
+    @Reference
+    JndiService jndiService;
+
+    @Override
+    public Object execute() throws Exception {
+        ShellTable table = new ShellTable();
+
+        table.column("JNDI Sub-Context");
+
+        List<String> contexts;
+        if (context == null) {
+            contexts = jndiService.contexts();
+        } else {
+            contexts = jndiService.contexts(context);
+        }
+
+        for (String c : contexts) {
+            table.addRow().addContent(c);
+        }
+
+        table.print(System.out);
+
+        return null;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/85c65dd6/jndi/src/main/java/org/apache/karaf/jndi/command/CreateCommand.java
----------------------------------------------------------------------
diff --git a/jndi/src/main/java/org/apache/karaf/jndi/command/CreateCommand.java b/jndi/src/main/java/org/apache/karaf/jndi/command/CreateCommand.java
new file mode 100644
index 0000000..86663bf
--- /dev/null
+++ b/jndi/src/main/java/org/apache/karaf/jndi/command/CreateCommand.java
@@ -0,0 +1,45 @@
+/*
+ * 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.karaf.jndi.command;
+
+import org.apache.karaf.jndi.JndiService;
+import org.apache.karaf.jndi.command.completers.ContextsCompleter;
+import org.apache.karaf.shell.api.action.Action;
+import org.apache.karaf.shell.api.action.Argument;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.Completion;
+import org.apache.karaf.shell.api.action.lifecycle.Reference;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+
+@Command(scope = "jndi",  name = "create", description = "Create a new JNDI sub-context.")
+@Service
+public class CreateCommand implements Action {
+
+    @Argument(index = 0, name = "context", description = "The JNDI sub-context name", required = true, multiValued = false)
+    @Completion(ContextsCompleter.class)
+    String context;
+
+    @Reference
+    JndiService jndiService;
+
+    @Override
+    public Object execute() throws Exception {
+        jndiService.create(context);
+        return null;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/85c65dd6/jndi/src/main/java/org/apache/karaf/jndi/command/DeleteCommand.java
----------------------------------------------------------------------
diff --git a/jndi/src/main/java/org/apache/karaf/jndi/command/DeleteCommand.java b/jndi/src/main/java/org/apache/karaf/jndi/command/DeleteCommand.java
new file mode 100644
index 0000000..3cd3a40
--- /dev/null
+++ b/jndi/src/main/java/org/apache/karaf/jndi/command/DeleteCommand.java
@@ -0,0 +1,45 @@
+/*
+ * 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.karaf.jndi.command;
+
+import org.apache.karaf.jndi.JndiService;
+import org.apache.karaf.jndi.command.completers.ContextsCompleter;
+import org.apache.karaf.shell.api.action.Action;
+import org.apache.karaf.shell.api.action.Argument;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.Completion;
+import org.apache.karaf.shell.api.action.lifecycle.Reference;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+
+@Command(scope = "jndi", name = "delete", description = "Delete a JNDI sub-context.")
+@Service
+public class DeleteCommand implements Action {
+
+    @Argument(index = 0, name = "context", description = "The JNDI sub-context name", required = true, multiValued = false)
+    @Completion(ContextsCompleter.class)
+    String context;
+
+    @Reference
+    JndiService jndiService;
+
+    @Override
+    public Object execute() throws Exception {
+        jndiService.delete(context);
+        return null;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/85c65dd6/jndi/src/main/java/org/apache/karaf/jndi/command/NamesCommand.java
----------------------------------------------------------------------
diff --git a/jndi/src/main/java/org/apache/karaf/jndi/command/NamesCommand.java b/jndi/src/main/java/org/apache/karaf/jndi/command/NamesCommand.java
new file mode 100644
index 0000000..0345f11
--- /dev/null
+++ b/jndi/src/main/java/org/apache/karaf/jndi/command/NamesCommand.java
@@ -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.karaf.jndi.command;
+
+import org.apache.karaf.jndi.JndiService;
+import org.apache.karaf.jndi.command.completers.ContextsCompleter;
+import org.apache.karaf.shell.api.action.Action;
+import org.apache.karaf.shell.api.action.Argument;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.Completion;
+import org.apache.karaf.shell.api.action.lifecycle.Reference;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.apache.karaf.shell.support.table.ShellTable;
+
+import java.util.Map;
+
+@Command(scope = "jndi", name = "names", description = "List the JNDI names.")
+@Service
+public class NamesCommand implements Action {
+
+    @Argument(index = 0, name = "context", description = "The JNDI context to display the names", required = false, multiValued = false)
+    @Completion(ContextsCompleter.class)
+    String context;
+
+    @Reference
+    JndiService jndiService;
+
+    @Override
+    public Object execute() throws Exception {
+        ShellTable table = new ShellTable();
+
+        table.column("JNDI Name");
+        table.column("Class Name");
+
+        Map<String, String> names;
+        if (context == null) {
+            names = jndiService.names();
+        } else {
+            names = jndiService.names(context);
+        }
+
+        for (String name : names.keySet()) {
+            table.addRow().addContent(name, names.get(name));
+        }
+
+        table.print(System.out);
+
+        return null;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/85c65dd6/jndi/src/main/java/org/apache/karaf/jndi/command/UnbindCommand.java
----------------------------------------------------------------------
diff --git a/jndi/src/main/java/org/apache/karaf/jndi/command/UnbindCommand.java b/jndi/src/main/java/org/apache/karaf/jndi/command/UnbindCommand.java
new file mode 100644
index 0000000..b93c7b9
--- /dev/null
+++ b/jndi/src/main/java/org/apache/karaf/jndi/command/UnbindCommand.java
@@ -0,0 +1,45 @@
+/*
+ * 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.karaf.jndi.command;
+
+import org.apache.karaf.jndi.JndiService;
+import org.apache.karaf.jndi.command.completers.NamesCompleter;
+import org.apache.karaf.shell.api.action.Action;
+import org.apache.karaf.shell.api.action.Argument;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.Completion;
+import org.apache.karaf.shell.api.action.lifecycle.Reference;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+
+@Command(scope = "jndi", name = "unbind", description = "Unbind a JNDI name.")
+@Service
+public class UnbindCommand implements Action {
+
+    @Argument(index = 0, name = "name", description = "The JNDI name to unbind", required = true, multiValued = false)
+    @Completion(NamesCompleter.class)
+    String name;
+
+    @Reference
+    JndiService jndiService;
+
+    @Override
+    public Object execute() throws Exception {
+        jndiService.unbind(name);
+        return null;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/85c65dd6/jndi/src/main/java/org/apache/karaf/jndi/command/completers/ContextsCompleter.java
----------------------------------------------------------------------
diff --git a/jndi/src/main/java/org/apache/karaf/jndi/command/completers/ContextsCompleter.java b/jndi/src/main/java/org/apache/karaf/jndi/command/completers/ContextsCompleter.java
new file mode 100644
index 0000000..8f2ac29
--- /dev/null
+++ b/jndi/src/main/java/org/apache/karaf/jndi/command/completers/ContextsCompleter.java
@@ -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.karaf.jndi.command.completers;
+
+import org.apache.karaf.jndi.JndiService;
+import org.apache.karaf.shell.api.action.lifecycle.Reference;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.apache.karaf.shell.api.console.CommandLine;
+import org.apache.karaf.shell.api.console.Completer;
+import org.apache.karaf.shell.api.console.Session;
+import org.apache.karaf.shell.support.completers.StringsCompleter;
+
+import java.util.List;
+
+/**
+ * Completers on the JNDI contexts.
+ */
+@Service
+public class ContextsCompleter implements Completer {
+
+    @Reference
+    private JndiService jndiService;
+
+    @Override
+    public int complete(Session session, CommandLine commandLine, List<String> candidates) {
+        StringsCompleter delegate = new StringsCompleter();
+        try {
+            List<String> contexts = jndiService.contexts();
+            for (String context : contexts) {
+                delegate.getStrings().add(context);
+            }
+        } catch (Exception e) {
+            // nothing to do
+        }
+        return delegate.complete(session, commandLine, candidates);
+    }
+
+    public JndiService getJndiService() {
+        return jndiService;
+    }
+
+    public void setJndiService(JndiService jndiService) {
+        this.jndiService = jndiService;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/85c65dd6/jndi/src/main/java/org/apache/karaf/jndi/command/completers/NamesCompleter.java
----------------------------------------------------------------------
diff --git a/jndi/src/main/java/org/apache/karaf/jndi/command/completers/NamesCompleter.java b/jndi/src/main/java/org/apache/karaf/jndi/command/completers/NamesCompleter.java
new file mode 100644
index 0000000..d94e3f4
--- /dev/null
+++ b/jndi/src/main/java/org/apache/karaf/jndi/command/completers/NamesCompleter.java
@@ -0,0 +1,59 @@
+/*
+ * 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.karaf.jndi.command.completers;
+
+import org.apache.karaf.jndi.JndiService;
+import org.apache.karaf.shell.api.action.lifecycle.Reference;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.apache.karaf.shell.api.console.CommandLine;
+import org.apache.karaf.shell.api.console.Completer;
+import org.apache.karaf.shell.api.console.Session;
+import org.apache.karaf.shell.support.completers.StringsCompleter;
+
+import java.util.List;
+
+/**
+ * Completer to the JNDI names.
+ */
+@Service
+public class NamesCompleter implements Completer {
+
+    @Reference
+    private JndiService jndiService;
+
+    @Override
+    public int complete(Session session, CommandLine commandLine, List<String> candidates) {
+        StringsCompleter delegate = new StringsCompleter();
+        try {
+            for (String name : jndiService.names().keySet()) {
+                delegate.getStrings().add(name);
+            }
+        } catch (Exception e) {
+            // nothing to do
+        }
+        return delegate.complete(session, commandLine, candidates);
+    }
+
+    public JndiService getJndiService() {
+        return jndiService;
+    }
+
+    public void setJndiService(JndiService jndiService) {
+        this.jndiService = jndiService;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/85c65dd6/jndi/src/main/java/org/apache/karaf/jndi/command/completers/ServicesIdCompleter.java
----------------------------------------------------------------------
diff --git a/jndi/src/main/java/org/apache/karaf/jndi/command/completers/ServicesIdCompleter.java b/jndi/src/main/java/org/apache/karaf/jndi/command/completers/ServicesIdCompleter.java
new file mode 100644
index 0000000..c7cdb80
--- /dev/null
+++ b/jndi/src/main/java/org/apache/karaf/jndi/command/completers/ServicesIdCompleter.java
@@ -0,0 +1,66 @@
+/*
+ * 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.karaf.jndi.command.completers;
+
+import org.apache.karaf.shell.api.action.lifecycle.Reference;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.apache.karaf.shell.api.console.CommandLine;
+import org.apache.karaf.shell.api.console.Completer;
+import org.apache.karaf.shell.api.console.Session;
+import org.apache.karaf.shell.support.completers.StringsCompleter;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceReference;
+
+import java.util.List;
+
+/**
+ * Completer on the OSGi services ID.
+ */
+@Service
+public class ServicesIdCompleter implements Completer {
+
+    @Reference
+    private BundleContext bundleContext;
+
+    @Override
+    public int complete(Session session, CommandLine commandLine, List<String> candidates) {
+        StringsCompleter delegate = new StringsCompleter();
+        Bundle[] bundles = bundleContext.getBundles();
+        for (Bundle bundle : bundles) {
+            ServiceReference[] references = bundle.getRegisteredServices();
+            if (references != null) {
+                for (ServiceReference reference : references) {
+                    if (reference.getProperty(Constants.SERVICE_ID) != null) {
+                        delegate.getStrings().add(reference.getProperty(Constants.SERVICE_ID).toString());
+                    }
+                }
+            }
+        }
+        return delegate.complete(session, commandLine, candidates);
+    }
+
+    public BundleContext getBundleContext() {
+        return bundleContext;
+    }
+
+    public void setBundleContext(BundleContext bundleContext) {
+        this.bundleContext = bundleContext;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/85c65dd6/jndi/src/main/java/org/apache/karaf/jndi/internal/JndiMBeanImpl.java
----------------------------------------------------------------------
diff --git a/jndi/src/main/java/org/apache/karaf/jndi/internal/JndiMBeanImpl.java b/jndi/src/main/java/org/apache/karaf/jndi/internal/JndiMBeanImpl.java
new file mode 100644
index 0000000..2433618
--- /dev/null
+++ b/jndi/src/main/java/org/apache/karaf/jndi/internal/JndiMBeanImpl.java
@@ -0,0 +1,122 @@
+/*
+ * 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.karaf.jndi.internal;
+
+import org.apache.karaf.jndi.JndiService;
+import org.apache.karaf.jndi.JndiMBean;
+
+import javax.management.MBeanException;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Implementation of the JndiMBean
+ */
+public class JndiMBeanImpl implements JndiMBean {
+
+    private JndiService jndiService;
+
+    @Override
+    public Map<String, String> getNames() throws MBeanException {
+        try {
+            return this.jndiService.names();
+        } catch (Throwable t) {
+            throw new MBeanException(null, t.getMessage());
+        }
+    }
+
+    @Override
+    public List<String> getContexts() throws MBeanException {
+        try {
+            return this.jndiService.contexts();
+        } catch (Throwable t) {
+            throw new MBeanException(null, t.getMessage());
+        }
+    }
+
+    @Override
+    public Map<String, String> getNames(String context) throws MBeanException {
+        try {
+            return this.jndiService.names(context);
+        } catch (Throwable t) {
+            throw new MBeanException(null, t.getMessage());
+        }
+    }
+
+    @Override
+    public List<String> getContexts(String context) throws MBeanException {
+        try {
+            return this.jndiService.contexts(context);
+        } catch (Throwable t) {
+            throw new MBeanException(null, t.getMessage());
+        }
+    }
+
+    @Override
+    public void alias(String name, String alias) throws MBeanException {
+        try {
+            this.jndiService.alias(name, alias);
+        } catch (Throwable t) {
+            throw new MBeanException(null, t.getMessage());
+        }
+    }
+
+    @Override
+    public void bind(Long serviceId, String name) throws MBeanException {
+        try {
+            this.jndiService.bind(serviceId, name);
+        } catch (Throwable t) {
+            throw new MBeanException(null, t.getMessage());
+        }
+    }
+
+    @Override
+    public void unbind(String name) throws MBeanException {
+        try {
+            this.jndiService.unbind(name);
+        } catch (Throwable t) {
+            throw new MBeanException(null, t.getMessage());
+        }
+    }
+
+    @Override
+    public void create(String context) throws MBeanException {
+        try {
+            this.jndiService.create(context);
+        } catch (Throwable t) {
+            throw new MBeanException(null, t.getMessage());
+        }
+    }
+
+    @Override
+    public void delete(String context) throws MBeanException {
+        try {
+            this.jndiService.delete(context);
+        } catch (Throwable t) {
+            throw new MBeanException(null, t.getMessage());
+        }
+    }
+
+    public JndiService getJndiService() {
+        return jndiService;
+    }
+
+    public void setJndiService(JndiService jndiService) {
+        this.jndiService = jndiService;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/85c65dd6/jndi/src/main/java/org/apache/karaf/jndi/internal/JndiServiceImpl.java
----------------------------------------------------------------------
diff --git a/jndi/src/main/java/org/apache/karaf/jndi/internal/JndiServiceImpl.java b/jndi/src/main/java/org/apache/karaf/jndi/internal/JndiServiceImpl.java
new file mode 100644
index 0000000..68d6b94
--- /dev/null
+++ b/jndi/src/main/java/org/apache/karaf/jndi/internal/JndiServiceImpl.java
@@ -0,0 +1,313 @@
+/*
+ * 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.karaf.jndi.internal;
+
+import org.apache.aries.proxy.ProxyManager;
+import org.apache.karaf.jndi.JndiService;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceReference;
+
+import javax.naming.*;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Implementation of the JNDI Service.
+ */
+public class JndiServiceImpl implements JndiService {
+
+    private BundleContext bundleContext;
+    private ProxyManager proxyManager;
+
+    private final static String OSGI_JNDI_CONTEXT_PREFIX = "osgi:service/";
+    private final static String OSGI_JNDI_SERVICE_PROPERTY = "osgi.jndi.service.name";
+
+    @Override
+    public Map<String, String> names() throws Exception {
+        Map<String, String> result = names("/");
+        result.putAll(names(OSGI_JNDI_CONTEXT_PREFIX));
+        return result;
+    }
+
+    @Override
+    public Map<String, String> names(String name) throws Exception {
+        Map<String, String> map = new HashMap<String, String>();
+        if (name.startsWith(OSGI_JNDI_CONTEXT_PREFIX)) {
+            // OSGi service binding
+            // make a lookup using directly the OSGi service
+            Bundle[] bundles = bundleContext.getBundles();
+            for (Bundle bundle : bundles) {
+                ServiceReference<?>[] services = bundle.getRegisteredServices();
+                if (services != null) {
+                    for (ServiceReference service : services) {
+                        if (service.getProperty(OSGI_JNDI_SERVICE_PROPERTY) != null) {
+                            Object actualService = bundleContext.getService(service);
+                            if (proxyManager.isProxy(actualService)) {
+                                actualService = proxyManager.unwrap(actualService).call();
+                            }
+                            map.put(OSGI_JNDI_CONTEXT_PREFIX + service.getProperty(OSGI_JNDI_SERVICE_PROPERTY), actualService.getClass().getName());
+                            bundleContext.ungetService(service);
+                        }
+                    }
+                }
+            }
+        } else {
+            // "real" JNDI lookup
+            Context context = new InitialContext();
+            NamingEnumeration<NameClassPair> pairs = context.list(name);
+            while (pairs.hasMoreElements()) {
+                NameClassPair pair = pairs.nextElement();
+                Object o;
+                if (name != null) {
+                    o = context.lookup(name + "/" + pair.getName());
+                } else {
+                    o = context.lookup(pair.getName());
+                }
+                if (o instanceof Context) {
+                    StringBuilder sb = new StringBuilder();
+                    sb.append("/" + pair.getName());
+                    names((Context) o, sb, map);
+                } else {
+                    map.put("/" + pair.getName(), pair.getClassName());
+                }
+            }
+        }
+        return map;
+    }
+
+    public List<String> contexts() throws Exception {
+        return contexts("/");
+    }
+
+    public List<String> contexts(String name) throws Exception {
+        List<String> contexts = new ArrayList<String>();
+        Context context = new InitialContext();
+        NamingEnumeration<NameClassPair> pairs = context.list(name);
+        while (pairs.hasMoreElements()) {
+            NameClassPair pair = pairs.nextElement();
+            Object o;
+            if (name != null) {
+                o = context.lookup(name + "/" + pair.getName());
+            } else {
+                o = context.lookup(pair.getName());
+            }
+            if (o instanceof Context) {
+                StringBuilder sb = new StringBuilder();
+                sb.append("/" + pair.getName());
+                contexts((Context) o, sb, contexts);
+            }
+        }
+        return contexts;
+    }
+
+    private void contexts(Context context, StringBuilder sb, List<String> contexts) throws Exception {
+        NamingEnumeration list = context.listBindings("");
+        while (list.hasMore()) {
+            Binding item = (Binding) list.next();
+            String name = item.getName();
+            Object o = item.getObject();
+            if (o instanceof Context) {
+                if (((Context) o).list("").hasMoreElements()) {
+                    sb.append("/").append(name);
+                    contexts((Context) o, sb, contexts);
+                } else {
+                    contexts.add(sb.toString() + "/" + name);
+                }
+            }
+        }
+    }
+
+    /**
+     * Recursively list a context/names
+     *
+     * @param ctx the startup context.
+     * @param sb the string builder where to construct the full qualified name.
+     * @param map the final map containing name/class name pairs.
+     * @throws Exception
+     */
+    private static final void names(Context ctx, StringBuilder sb, Map<String, String> map) throws Exception {
+        NamingEnumeration list = ctx.listBindings("");
+        while (list.hasMore()) {
+            Binding item = (Binding) list.next();
+            String className = item.getClassName();
+            String name = item.getName();
+            Object o = item.getObject();
+            if (o instanceof Context) {
+                sb.append("/").append(name);
+                names((Context) o, sb, map);
+            } else {
+                map.put(sb.toString() + "/" + name, className);
+            }
+        }
+    }
+
+    @Override
+    public void create(String name) throws Exception {
+        Context context = new InitialContext();
+        String[] splitted = name.split("/");
+        if (splitted.length > 0) {
+            for (int i = 0; i < splitted.length; i++) {
+                try {
+                    Object o = context.lookup(splitted[i]);
+                    if (!(o instanceof Context)) {
+                        throw new NamingException("Name " + splitted[i] + " already exists");
+                    }
+                } catch (NameNotFoundException e) {
+                    context.createSubcontext(splitted[i]);
+                }
+                context = (Context) context.lookup(splitted[i]);
+            }
+        } else {
+            context.createSubcontext(name);
+        }
+    }
+
+    @Override
+    public void delete(String name) throws Exception {
+        Context context = new InitialContext();
+        context.destroySubcontext(name);
+    }
+
+    @Override
+    public void bind(long serviceId, String name) throws Exception {
+        Context context = new InitialContext();
+        Bundle[] bundles = bundleContext.getBundles();
+        for (Bundle bundle : bundles) {
+            ServiceReference<?>[] services = bundle.getRegisteredServices();
+            if (services != null) {
+                for (ServiceReference service : services) {
+                    if (service.getProperty(Constants.SERVICE_ID) != null && ((Long) service.getProperty(Constants.SERVICE_ID)) == serviceId) {
+                        Object actualService = bundleContext.getService(service);
+                        if (proxyManager.isProxy(actualService)) {
+                            actualService = proxyManager.unwrap(actualService).call();
+                        }
+                        try {
+                            String[] splitted = name.split("/");
+                            if (splitted.length > 0) {
+                                for (int i = 0; i < splitted.length - 1; i++) {
+                                    try {
+                                        Object o = context.lookup(splitted[i]);
+                                        if (!(o instanceof Context)) {
+                                            throw new NamingException("Name " + splitted[i] + " already exists");
+                                        }
+                                    } catch (NameNotFoundException nnfe) {
+                                        context.createSubcontext(splitted[i]);
+                                    }
+                                    context = (Context) context.lookup(splitted[i]);
+                                }
+                                name = splitted[splitted.length - 1];
+                            }
+                            context.bind(name, actualService);
+                        } finally {
+                            bundleContext.ungetService(service);
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    @Override
+    public void alias(String name, String alias) throws Exception {
+        Context context = new InitialContext();
+        if (name.startsWith(OSGI_JNDI_CONTEXT_PREFIX)) {
+            // get the object
+            Bundle[] bundles = bundleContext.getBundles();
+            for (Bundle bundle : bundles) {
+                ServiceReference<?>[] services = bundle.getRegisteredServices();
+                if (services != null) {
+                    for (ServiceReference service : services) {
+                        if (service.getProperty(OSGI_JNDI_SERVICE_PROPERTY) != null && ((String) service.getProperty(OSGI_JNDI_SERVICE_PROPERTY)).equals(name.substring(OSGI_JNDI_CONTEXT_PREFIX.length()))) {
+                            Object actualService = bundleContext.getService(service);
+                            try {
+                                if (proxyManager.isProxy(actualService)) {
+                                    actualService = proxyManager.unwrap(actualService).call();
+                                }
+                                String[] splitted = alias.split("/");
+                                if (splitted.length > 0) {
+                                    for (int i = 0; i < splitted.length - 1; i++) {
+                                        try {
+                                            Object o = context.lookup(splitted[i]);
+                                            if (!(o instanceof Context)) {
+                                                throw new NamingException("Name " + splitted[i] + " already exists");
+                                            }
+                                        } catch (NameNotFoundException nnfe) {
+                                            context.createSubcontext(splitted[i]);
+                                        }
+                                        context = (Context) context.lookup(splitted[i]);
+                                    }
+                                    alias = splitted[splitted.length -1];
+                                }
+                                context.bind(alias, actualService);
+                            } finally {
+                                bundleContext.ungetService(service);
+                            }
+                        }
+                    }
+                }
+            }
+        } else {
+            Object object = context.lookup(name);
+            String[] splitted = alias.split("/");
+            if (splitted.length > 0) {
+                for (int i = 0; i < splitted.length - 1; i++) {
+                    try {
+                        Object o = context.lookup(splitted[i]);
+                        if (!(o instanceof Context)) {
+                            throw new NamingException("Name " + splitted[i] + " already exists");
+                        }
+                    } catch (NameNotFoundException nnfe) {
+                        context.createSubcontext(splitted[i]);
+                    }
+                    context = (Context) context.lookup(splitted[i]);
+                }
+                alias = splitted[splitted.length - 1];
+            }
+            context.bind(alias, object);
+        }
+    }
+
+    @Override
+    public void unbind(String name) throws Exception {
+        InitialContext context = new InitialContext();
+        if (name.startsWith(OSGI_JNDI_CONTEXT_PREFIX)) {
+            throw new IllegalArgumentException("You can't unbind a name from the " + OSGI_JNDI_CONTEXT_PREFIX + " JNDI context.");
+        }
+        context.unbind(name);
+    }
+
+    public BundleContext getBundleContext() {
+        return bundleContext;
+    }
+
+    public void setBundleContext(BundleContext bundleContext) {
+        this.bundleContext = bundleContext;
+    }
+
+    public ProxyManager getProxyManager() {
+        return proxyManager;
+    }
+
+    public void setProxyManager(ProxyManager proxyManager) {
+        this.proxyManager = proxyManager;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/85c65dd6/jndi/src/main/resources/OSGI-INF/blueprint/jndi-core.xml
----------------------------------------------------------------------
diff --git a/jndi/src/main/resources/OSGI-INF/blueprint/jndi-core.xml b/jndi/src/main/resources/OSGI-INF/blueprint/jndi-core.xml
new file mode 100644
index 0000000..e6be3b1
--- /dev/null
+++ b/jndi/src/main/resources/OSGI-INF/blueprint/jndi-core.xml
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+        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.
+    -->
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
+           xmlns:ext="http://aries.apache.org/blueprint/xmlns/blueprint-ext/v1.0.0"
+           default-activation="lazy">
+
+    <ext:property-placeholder placeholder-prefix="$[" placeholder-suffix="]"/>
+
+    <bean id="karafInitialContextFactory" class="org.apache.karaf.jndi.KarafInitialContextFactory"/>
+
+    <reference id="proxyManager" interface="org.apache.aries.proxy.ProxyManager"/>
+
+    <service ref="karafInitialContextFactory" interface="javax.naming.spi.InitialContextFactory"/>
+
+    <bean id="jndiService" class="org.apache.karaf.jndi.internal.JndiServiceImpl">
+        <property name="bundleContext" ref="blueprintBundleContext"/>
+        <property name="proxyManager" ref="proxyManager"/>
+    </bean>
+
+    <service ref="jndiService" interface="org.apache.karaf.jndi.JndiService">
+        <service-properties>
+            <!-- bind the JNDI service itself in the JNDI context -->
+            <entry key="osgi.jndi.service.name" value="jndi"/>
+        </service-properties>
+    </service>
+
+    <!-- Management -->
+    <bean id="jndiMBeanImpl" class="org.apache.karaf.jndi.internal.JndiMBeanImpl">
+        <property name="jndiService" ref="jndiService"/>
+    </bean>
+
+    <service ref="jndiMBeanImpl" auto-export="interfaces">
+        <service-properties>
+            <entry key="jmx.objectname" value="org.apache.karaf:type=jndi,name=$[karaf.name]"/>
+        </service-properties>
+    </service>
+
+</blueprint>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/karaf/blob/85c65dd6/jndi/src/main/resources/OSGI-INF/bundle.info
----------------------------------------------------------------------
diff --git a/jndi/src/main/resources/OSGI-INF/bundle.info b/jndi/src/main/resources/OSGI-INF/bundle.info
new file mode 100644
index 0000000..4a7a606
--- /dev/null
+++ b/jndi/src/main/resources/OSGI-INF/bundle.info
@@ -0,0 +1,19 @@
+h1. Synopsis
+
+${project.name}
+
+${project.description}
+
+Maven URL:
+[mvn:${project.groupId}/${project.artifactId}/${project.version}]
+
+h1. Description
+
+This bundle is the core implementation of the JNDI service support.
+
+JNDI allows to expose any OSGi services as JNDI names. Karaf JNDI also provides a set of commands and a MBean to list
+the current JNDI names, create JNDI aliases, ...
+
+h1. See also
+
+JNDI - section of the Karaf User Guide


[45/59] [abbrv] git commit: [KARAF-2852] Merge obr/core and obr/command

Posted by gn...@apache.org.
[KARAF-2852] Merge obr/core and obr/command


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

Branch: refs/heads/master
Commit: b0a20b83891cbfd301bc3f13704285b34aba4311
Parents: d5ce026
Author: Guillaume Nodet <gn...@gmail.com>
Authored: Thu Apr 10 09:26:03 2014 +0200
Committer: Guillaume Nodet <gn...@gmail.com>
Committed: Thu Apr 10 16:02:45 2014 +0200

----------------------------------------------------------------------
 .../standard/src/main/feature/feature.xml       |   2 -
 obr/NOTICE                                      |  71 +++++
 obr/command/NOTICE                              |  71 -----
 obr/command/pom.xml                             | 113 --------
 .../apache/karaf/obr/command/AddUrlCommand.java |  39 ---
 .../apache/karaf/obr/command/DeployCommand.java |  44 ---
 .../apache/karaf/obr/command/FindCommand.java   | 130 ---------
 .../apache/karaf/obr/command/InfoCommand.java   | 108 -------
 .../apache/karaf/obr/command/ListCommand.java   |  85 ------
 .../karaf/obr/command/ListUrlCommand.java       |  50 ----
 .../karaf/obr/command/ObrCommandSupport.java    | 281 -------------------
 .../karaf/obr/command/RefreshUrlCommand.java    |  63 -----
 .../karaf/obr/command/RemoveUrlCommand.java     |  54 ----
 .../karaf/obr/command/ResolveCommand.java       | 145 ----------
 .../apache/karaf/obr/command/SourceCommand.java |  66 -----
 .../apache/karaf/obr/command/StartCommand.java  |  41 ---
 .../apache/karaf/obr/command/util/FileUtil.java | 177 ------------
 .../src/main/resources/OSGI-INF/bundle.info     |  29 --
 .../karaf/obr/command/ListCommandTest.java      |  59 ----
 obr/core/NOTICE                                 |  71 -----
 obr/core/pom.xml                                |  87 ------
 .../org/apache/karaf/obr/core/ObrMBean.java     |  37 ---
 .../karaf/obr/core/internal/ObrMBeanImpl.java   | 203 --------------
 .../resources/OSGI-INF/blueprint/blueprint.xml  |  34 ---
 .../src/main/resources/OSGI-INF/bundle.info     |  25 --
 obr/pom.xml                                     |  70 ++++-
 .../apache/karaf/obr/command/AddUrlCommand.java |  39 +++
 .../apache/karaf/obr/command/DeployCommand.java |  44 +++
 .../apache/karaf/obr/command/FindCommand.java   | 130 +++++++++
 .../apache/karaf/obr/command/InfoCommand.java   | 108 +++++++
 .../apache/karaf/obr/command/ListCommand.java   |  85 ++++++
 .../karaf/obr/command/ListUrlCommand.java       |  50 ++++
 .../karaf/obr/command/ObrCommandSupport.java    | 281 +++++++++++++++++++
 .../karaf/obr/command/RefreshUrlCommand.java    |  63 +++++
 .../karaf/obr/command/RemoveUrlCommand.java     |  54 ++++
 .../karaf/obr/command/ResolveCommand.java       | 145 ++++++++++
 .../apache/karaf/obr/command/SourceCommand.java |  66 +++++
 .../apache/karaf/obr/command/StartCommand.java  |  41 +++
 .../apache/karaf/obr/command/util/FileUtil.java | 177 ++++++++++++
 .../org/apache/karaf/obr/core/ObrMBean.java     |  37 +++
 .../karaf/obr/core/internal/ObrMBeanImpl.java   | 203 ++++++++++++++
 .../resources/OSGI-INF/blueprint/blueprint.xml  |  34 +++
 obr/src/main/resources/OSGI-INF/bundle.info     |  25 ++
 43 files changed, 1715 insertions(+), 2022 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/karaf/blob/b0a20b83/assemblies/features/standard/src/main/feature/feature.xml
----------------------------------------------------------------------
diff --git a/assemblies/features/standard/src/main/feature/feature.xml b/assemblies/features/standard/src/main/feature/feature.xml
index 4c2be08..e596a84 100644
--- a/assemblies/features/standard/src/main/feature/feature.xml
+++ b/assemblies/features/standard/src/main/feature/feature.xml
@@ -114,9 +114,7 @@
         <bundle start-level="30">mvn:org.apache.felix/org.osgi.service.obr/${felix.obr.version}</bundle>
         <bundle start-level="30">mvn:org.apache.felix/org.apache.felix.bundlerepository/${felix.bundlerepository.version}</bundle>
         <bundle start-level="30">mvn:org.apache.karaf.obr/org.apache.karaf.obr.core/${project.version}</bundle>
-        <bundle start-level="30">mvn:org.apache.karaf.obr/org.apache.karaf.obr.command/${project.version}</bundle>
         <bundle start-level="30">mvn:org.ops4j.pax.url/pax-url-obr/${pax.url.version}/jar/uber</bundle>
-        <bundle start-level="31">mvn:org.apache.karaf.features/org.apache.karaf.features.obr/${project.version}</bundle>
     </feature>
 
     <feature name="bundle" description="Provide Bundle support" version="${project.version}">

http://git-wip-us.apache.org/repos/asf/karaf/blob/b0a20b83/obr/NOTICE
----------------------------------------------------------------------
diff --git a/obr/NOTICE b/obr/NOTICE
new file mode 100644
index 0000000..b70f1f9
--- /dev/null
+++ b/obr/NOTICE
@@ -0,0 +1,71 @@
+Apache Karaf
+Copyright 2010-2014 The Apache Software Foundation
+
+
+I. Included Software
+
+This product includes software developed at
+The Apache Software Foundation (http://www.apache.org/).
+Licensed under the Apache License 2.0.
+
+This product uses software developed at
+The OSGi Alliance (http://www.osgi.org/).
+Copyright (c) OSGi Alliance (2000, 2010).
+Licensed under the Apache License 2.0.
+
+This product includes software developed at
+OW2 (http://www.ow2.org/).
+Licensed under the BSD License.
+
+This product includes software developed at
+OPS4J (http://www.ops4j.org/).
+Licensed under the Apache License 2.0.
+
+This product includes software developed at
+Eclipse Foundation (http://www.eclipse.org/).
+Licensed under the EPL.
+
+This product includes software written by
+Antony Lesuisse.
+Licensed under Public Domain.
+
+
+II. Used Software
+
+This product uses software developed at
+FUSE Source (http://www.fusesource.org/).
+Licensed under the Apache License 2.0.
+
+This product uses software developed at
+AOP Alliance (http://aopalliance.sourceforge.net/).
+Licensed under the Public Domain.
+
+This product uses software developed at
+Tanuki Software (http://www.tanukisoftware.com/).
+Licensed under the Apache License 2.0.
+
+This product uses software developed at
+Jasypt (http://jasypt.sourceforge.net/).
+Licensed under the Apache License 2.0.
+
+This product uses software developed at
+JLine (http://jline.sourceforge.net).
+Licensed under the BSD License.
+
+This product uses software developed at
+SLF4J (http://www.slf4j.org/).
+Licensed under the MIT License.
+
+This product uses software developed at
+SpringSource (http://www.springsource.org/).
+Licensed under the Apache License 2.0.
+
+This product includes software from http://www.json.org.
+Copyright (c) 2002 JSON.org
+
+
+III. License Summary
+- Apache License 2.0
+- BSD License
+- EPL License
+- MIT License

http://git-wip-us.apache.org/repos/asf/karaf/blob/b0a20b83/obr/command/NOTICE
----------------------------------------------------------------------
diff --git a/obr/command/NOTICE b/obr/command/NOTICE
deleted file mode 100644
index b70f1f9..0000000
--- a/obr/command/NOTICE
+++ /dev/null
@@ -1,71 +0,0 @@
-Apache Karaf
-Copyright 2010-2014 The Apache Software Foundation
-
-
-I. Included Software
-
-This product includes software developed at
-The Apache Software Foundation (http://www.apache.org/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-The OSGi Alliance (http://www.osgi.org/).
-Copyright (c) OSGi Alliance (2000, 2010).
-Licensed under the Apache License 2.0.
-
-This product includes software developed at
-OW2 (http://www.ow2.org/).
-Licensed under the BSD License.
-
-This product includes software developed at
-OPS4J (http://www.ops4j.org/).
-Licensed under the Apache License 2.0.
-
-This product includes software developed at
-Eclipse Foundation (http://www.eclipse.org/).
-Licensed under the EPL.
-
-This product includes software written by
-Antony Lesuisse.
-Licensed under Public Domain.
-
-
-II. Used Software
-
-This product uses software developed at
-FUSE Source (http://www.fusesource.org/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-AOP Alliance (http://aopalliance.sourceforge.net/).
-Licensed under the Public Domain.
-
-This product uses software developed at
-Tanuki Software (http://www.tanukisoftware.com/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-Jasypt (http://jasypt.sourceforge.net/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-JLine (http://jline.sourceforge.net).
-Licensed under the BSD License.
-
-This product uses software developed at
-SLF4J (http://www.slf4j.org/).
-Licensed under the MIT License.
-
-This product uses software developed at
-SpringSource (http://www.springsource.org/).
-Licensed under the Apache License 2.0.
-
-This product includes software from http://www.json.org.
-Copyright (c) 2002 JSON.org
-
-
-III. License Summary
-- Apache License 2.0
-- BSD License
-- EPL License
-- MIT License

http://git-wip-us.apache.org/repos/asf/karaf/blob/b0a20b83/obr/command/pom.xml
----------------------------------------------------------------------
diff --git a/obr/command/pom.xml b/obr/command/pom.xml
deleted file mode 100644
index 0c9457f..0000000
--- a/obr/command/pom.xml
+++ /dev/null
@@ -1,113 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-
-    <!--
-
-        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.
-    -->
-
-    <modelVersion>4.0.0</modelVersion>
-
-    <parent>
-        <groupId>org.apache.karaf.obr</groupId>
-        <artifactId>obr</artifactId>
-        <version>4.0.0-SNAPSHOT</version>
-        <relativePath>../pom.xml</relativePath>
-    </parent>
-
-    <artifactId>org.apache.karaf.obr.command</artifactId>
-    <packaging>bundle</packaging>
-    <name>Apache Karaf :: OBR :: Command</name>
-    <description>Shell commands to manipulate the OBR service</description>
-
-    <properties>
-        <appendedResourcesDirectory>${basedir}/../../etc/appended-resources</appendedResourcesDirectory>
-    </properties>
-
-    <dependencies>
-
-        <dependency>
-            <groupId>commons-collections</groupId>
-            <artifactId>commons-collections</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>commons-lang</groupId>
-            <artifactId>commons-lang</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.osgi</groupId>
-            <artifactId>org.osgi.core</artifactId>
-            <scope>provided</scope>
-        </dependency>
-
-        <dependency>
-            <groupId>org.apache.felix</groupId>
-            <artifactId>org.apache.felix.bundlerepository</artifactId>
-            <scope>provided</scope>
-        </dependency>
-
-        <dependency>
-            <groupId>org.apache.karaf.shell</groupId>
-            <artifactId>org.apache.karaf.shell.core</artifactId>
-        </dependency>
-
-        <dependency>
-            <groupId>org.easymock</groupId>
-            <artifactId>easymock</artifactId>
-            <scope>test</scope>
-        </dependency>
-		<dependency>
-            <groupId>org.slf4j</groupId>
-            <artifactId>slf4j-jdk14</artifactId>
-            <scope>test</scope>
-        </dependency>
-    </dependencies>
-
-    <build>
-        <resources>
-            <resource>
-                <directory>${project.basedir}/src/main/resources</directory>
-                <includes>
-                    <include>**/*</include>
-                </includes>
-            </resource>
-            <resource>
-                <directory>${project.basedir}/src/main/resources</directory>
-                <filtering>true</filtering>
-                <includes>
-                    <include>**/*.info</include>
-                </includes>
-            </resource>
-        </resources>
-        <plugins>
-            <plugin>
-                <groupId>org.apache.felix</groupId>
-                <artifactId>maven-bundle-plugin</artifactId>
-                <configuration>
-                    <instructions>
-                        <Export-Package>
-                            !*
-                        </Export-Package>
-                        <Karaf-Commands>*</Karaf-Commands>
-                    </instructions>
-                </configuration>
-            </plugin>
-        </plugins>
-    </build>
-
-</project>

http://git-wip-us.apache.org/repos/asf/karaf/blob/b0a20b83/obr/command/src/main/java/org/apache/karaf/obr/command/AddUrlCommand.java
----------------------------------------------------------------------
diff --git a/obr/command/src/main/java/org/apache/karaf/obr/command/AddUrlCommand.java b/obr/command/src/main/java/org/apache/karaf/obr/command/AddUrlCommand.java
deleted file mode 100644
index 5aaf13a..0000000
--- a/obr/command/src/main/java/org/apache/karaf/obr/command/AddUrlCommand.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * 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.karaf.obr.command;
-
-import java.util.List;
-
-import org.apache.felix.bundlerepository.RepositoryAdmin;
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-
-@Command(scope = "obr", name = "url-add", description = "Adds a list of repository URLs to the OBR service.")
-@Service
-public class AddUrlCommand extends ObrCommandSupport {
-
-    @Argument(index = 0, name = "urls", description = "Repository URLs to add to the OBR service separated by whitespaces", required = true, multiValued = true)
-    List<String> urls;
-
-    protected void doExecute(RepositoryAdmin admin) throws Exception {
-        for (String url : urls) {
-            admin.addRepository(url);
-        }
-        persistRepositoryList(admin);
-    }
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/b0a20b83/obr/command/src/main/java/org/apache/karaf/obr/command/DeployCommand.java
----------------------------------------------------------------------
diff --git a/obr/command/src/main/java/org/apache/karaf/obr/command/DeployCommand.java b/obr/command/src/main/java/org/apache/karaf/obr/command/DeployCommand.java
deleted file mode 100644
index a852c70..0000000
--- a/obr/command/src/main/java/org/apache/karaf/obr/command/DeployCommand.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * 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.karaf.obr.command;
-
-import java.util.List;
-
-import org.apache.felix.bundlerepository.RepositoryAdmin;
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Option;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-
-@Command(scope = "obr", name = "deploy", description = "Deploys a list of bundles using OBR service.")
-@Service
-public class DeployCommand extends ObrCommandSupport {
-
-    @Argument(index = 0, name = "bundles", description = "List of bundle names to deploy (separated by whitespaces)", required = true, multiValued = true)
-    protected List<String> bundles;
-
-    @Option(name = "-s", aliases = { "--start" }, description = "Start the deployed bundles", required = false, multiValued = false)
-    protected boolean start = false;
-
-    @Option(name = "-d", aliases = { "--deployOptional" }, description = "Deploy optional bundles", required = false, multiValued = false)
-    protected boolean deployOptional = false;
-
-    protected void doExecute(RepositoryAdmin admin) throws Exception {
-        doDeploy(admin, bundles, start, deployOptional);
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/b0a20b83/obr/command/src/main/java/org/apache/karaf/obr/command/FindCommand.java
----------------------------------------------------------------------
diff --git a/obr/command/src/main/java/org/apache/karaf/obr/command/FindCommand.java b/obr/command/src/main/java/org/apache/karaf/obr/command/FindCommand.java
deleted file mode 100644
index fad967b..0000000
--- a/obr/command/src/main/java/org/apache/karaf/obr/command/FindCommand.java
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * 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.karaf.obr.command;
-
-import org.apache.felix.bundlerepository.Capability;
-import org.apache.felix.bundlerepository.RepositoryAdmin;
-import org.apache.felix.bundlerepository.Requirement;
-import org.apache.felix.bundlerepository.Resource;
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-
-import java.io.PrintStream;
-import java.lang.reflect.Array;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-
-@Command(scope = "obr", name = "find", description = "Find OBR bundles for a given filter.")
-@Service
-public class FindCommand extends ObrCommandSupport {
-
-    @Argument(index = 0, name = "requirements", description = "Requirement", required = true, multiValued = true)
-    List<String> requirements;
-
-    protected void doExecute(RepositoryAdmin admin) throws Exception {
-        Resource[] resources = admin.discoverResources(parseRequirements(admin, requirements));
-        if (resources == null)
-        {
-            System.err.println("No matching resources.");
-        }
-        else
-        {
-            for (int resIdx = 0; resIdx < resources.length; resIdx++)
-            {
-                if (resIdx > 0)
-                {
-                    System.out.println("");
-                }
-                printResource(System.out, resources[resIdx]);
-            }
-        }
-    }
-
-    private void printResource(PrintStream out, Resource resource)
-    {
-        String name = resource.getPresentationName();
-        if (name == null) {
-            name = resource.getSymbolicName();
-        }
-
-        printUnderline(out, name.length());
-        out.println(name);
-        printUnderline(out, name    .length());
-
-        Map map = resource.getProperties();
-        for (Iterator iter = map.entrySet().iterator(); iter.hasNext(); )
-        {
-            Map.Entry entry = (Map.Entry) iter.next();
-            if (entry.getValue().getClass().isArray())
-            {
-                out.println(entry.getKey() + ":");
-                for (int j = 0; j < Array.getLength(entry.getValue()); j++)
-                {
-                    out.println("   " + Array.get(entry.getValue(), j));
-                }
-            }
-            else
-            {
-                out.println(entry.getKey() + ": " + entry.getValue());
-            }
-        }
-
-        Requirement[] reqs = resource.getRequirements();
-        if ((reqs != null) && (reqs.length > 0))
-        {
-            boolean hdr = false;
-            for (int i = 0; i < reqs.length; i++)
-            {
-                if (!reqs[i].isOptional())
-                {
-                    if (!hdr)
-                    {
-                        hdr = true;
-                        out.println("Requirements:");
-                    }
-                    out.println("   " + reqs[i].getName() + ":" + reqs[i].getFilter());
-                }
-            }
-            hdr = false;
-            for (int i = 0; i < reqs.length; i++)
-            {
-                if (reqs[i].isOptional())
-                {
-                    if (!hdr)
-                    {
-                        hdr = true;
-                        out.println("Optional Requirements:");
-                    }
-                    out.println("   " + reqs[i].getName() + ":" + reqs[i].getFilter());
-                }
-            }
-        }
-
-        Capability[] caps = resource.getCapabilities();
-        if ((caps != null) && (caps.length > 0))
-        {
-            out.println("Capabilities:");
-            for (int i = 0; i < caps.length; i++)
-            {
-                out.println("   " + caps[i].getName() + ":" + caps[i].getPropertiesAsMap());
-            }
-        }
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/b0a20b83/obr/command/src/main/java/org/apache/karaf/obr/command/InfoCommand.java
----------------------------------------------------------------------
diff --git a/obr/command/src/main/java/org/apache/karaf/obr/command/InfoCommand.java b/obr/command/src/main/java/org/apache/karaf/obr/command/InfoCommand.java
deleted file mode 100644
index bacc61b..0000000
--- a/obr/command/src/main/java/org/apache/karaf/obr/command/InfoCommand.java
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * 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.karaf.obr.command;
-
-import java.io.PrintStream;
-import java.lang.reflect.Array;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-
-import org.apache.felix.bundlerepository.Capability;
-import org.apache.felix.bundlerepository.RepositoryAdmin;
-import org.apache.felix.bundlerepository.Requirement;
-import org.apache.felix.bundlerepository.Resource;
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-
-@Command(scope = "obr", name = "info", description = "Prints information about OBR bundles.")
-@Service
-public class InfoCommand extends ObrCommandSupport {
-
-    @Argument(index = 0, name = "bundles", description = "Specify bundles to query for information (separated by whitespaces)", required = true, multiValued = true)
-    List<String> bundles;
-
-    protected void doExecute(RepositoryAdmin admin) throws Exception {
-        for (String bundle : bundles) {
-            String[] target = getTarget(bundle);
-            Resource[] resources = searchRepository(admin, target[0], target[1]);
-            if (resources == null)
-            {
-                System.err.println("Unknown bundle and/or version: "
-                    + target[0]);
-            }
-            else
-            {
-                for (int resIdx = 0; resIdx < resources.length; resIdx++)
-                {
-                    if (resIdx > 0)
-                    {
-                        System.out.println("");
-                    }
-                    printResource(System.out, resources[resIdx]);
-                }
-            }
-        }
-    }
-
-    private void printResource(PrintStream out, Resource resource)
-    {
-        printUnderline(out, resource.getPresentationName().length());
-        out.println(resource.getPresentationName());
-        printUnderline(out, resource.getPresentationName().length());
-
-        Map map = resource.getProperties();
-        for (Iterator iter = map.entrySet().iterator(); iter.hasNext(); )
-        {
-            Map.Entry entry = (Map.Entry) iter.next();
-            if (entry.getValue().getClass().isArray())
-            {
-                out.println(entry.getKey() + ":");
-                for (int j = 0; j < Array.getLength(entry.getValue()); j++)
-                {
-                    out.println("   " + Array.get(entry.getValue(), j));
-                }
-            }
-            else
-            {
-                out.println(entry.getKey() + ": " + entry.getValue());
-            }
-        }
-
-        Requirement[] reqs = resource.getRequirements();
-        if ((reqs != null) && (reqs.length > 0))
-        {
-            out.println("Requires:");
-            for (int i = 0; i < reqs.length; i++)
-            {
-                out.println("   " + reqs[i].getName() + ":" + reqs[i].getFilter());
-            }
-        }
-
-        Capability[] caps = resource.getCapabilities();
-        if ((caps != null) && (caps.length > 0))
-        {
-            out.println("Capabilities:");
-            for (int i = 0; i < caps.length; i++)
-            {
-                out.println("   " + caps[i].getName() + ":" + caps[i].getPropertiesAsMap());
-            }
-        }
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/b0a20b83/obr/command/src/main/java/org/apache/karaf/obr/command/ListCommand.java
----------------------------------------------------------------------
diff --git a/obr/command/src/main/java/org/apache/karaf/obr/command/ListCommand.java b/obr/command/src/main/java/org/apache/karaf/obr/command/ListCommand.java
deleted file mode 100644
index 45db82f..0000000
--- a/obr/command/src/main/java/org/apache/karaf/obr/command/ListCommand.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * 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.karaf.obr.command;
-
-import java.util.List;
-
-import org.apache.felix.bundlerepository.RepositoryAdmin;
-import org.apache.felix.bundlerepository.Resource;
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Option;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.apache.karaf.shell.support.table.ShellTable;
-
-@Command(scope = "obr", name = "list", description = "Lists OBR bundles, optionally providing the given packages.")
-@Service
-public class ListCommand extends ObrCommandSupport {
-
-    @Argument(index = 0, name = "packages", description = "A list of packages separated by whitespaces.", required = false, multiValued = true)
-    List<String> packages;
-
-    @Option(name = "--no-format", description = "Disable table rendered output", required = false, multiValued = false)
-    boolean noFormat;
-
-    @Override
-    void doExecute(RepositoryAdmin admin) throws Exception {
-        StringBuilder substr = new StringBuilder();
-
-        if (packages != null) {
-            for (String packageName : packages) {
-                substr.append(" ");
-                substr.append(packageName);
-            }
-        }
-
-        String query;
-        if ((substr == null) || (substr.length() == 0)) {
-            query = "(|(presentationname=*)(symbolicname=*))";
-        } else {
-            query = "(|(presentationname=*" + substr + "*)(symbolicname=*" + substr + "*))";
-        }
-        Resource[] resources = admin.discoverResources(query);
-        int maxPName = 4;
-        int maxSName = 13;
-        int maxVersion = 7;
-        for (Resource resource : resources) {
-            maxPName = Math.max(maxPName, emptyIfNull(resource.getPresentationName()).length());
-            maxSName = Math.max(maxSName, emptyIfNull(resource.getSymbolicName()).length());
-            maxVersion = Math.max(maxVersion, emptyIfNull(resource.getVersion()).length());
-        }
-
-        ShellTable table = new ShellTable();
-        table.column("Name");
-        table.column("Symbolic Name");
-        table.column("Version");
-        table.emptyTableText("No matching bundles");
-
-        for (Resource resource : resources) {
-            table.addRow().addContent(emptyIfNull(resource.getPresentationName()),
-                    emptyIfNull(resource.getSymbolicName()),
-                    emptyIfNull(resource.getVersion()));
-        }
-
-        table.print(System.out, !noFormat);
-    }
-
-    private String emptyIfNull(Object st) {
-        return st == null ? "" : st.toString();
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/b0a20b83/obr/command/src/main/java/org/apache/karaf/obr/command/ListUrlCommand.java
----------------------------------------------------------------------
diff --git a/obr/command/src/main/java/org/apache/karaf/obr/command/ListUrlCommand.java b/obr/command/src/main/java/org/apache/karaf/obr/command/ListUrlCommand.java
deleted file mode 100644
index 1c07236..0000000
--- a/obr/command/src/main/java/org/apache/karaf/obr/command/ListUrlCommand.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * 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.karaf.obr.command;
-
-import org.apache.felix.bundlerepository.Repository;
-import org.apache.felix.bundlerepository.RepositoryAdmin;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Option;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.apache.karaf.shell.support.table.ShellTable;
-
-@Command(scope = "obr", name = "url-list", description = "Displays the repository URLs currently associated with the OBR service.")
-@Service
-public class ListUrlCommand extends ObrCommandSupport {
-
-    @Option(name = "--no-format", description = "Disable table rendered output", required = false, multiValued = false)
-    boolean noFormat;
-
-    protected void doExecute(RepositoryAdmin admin) {
-
-        ShellTable table = new ShellTable();
-        table.column("Index");
-        table.column("OBR URL");
-        table.emptyTableText("No OBR repository URL");
-
-        Repository[] repos = admin.listRepositories();
-        if (repos != null) {
-            for (int i = 0; i < repos.length; i++) {
-                table.addRow().addContent(i, repos[i].getURI());
-            }
-        }
-
-        table.print(System.out, !noFormat);
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/b0a20b83/obr/command/src/main/java/org/apache/karaf/obr/command/ObrCommandSupport.java
----------------------------------------------------------------------
diff --git a/obr/command/src/main/java/org/apache/karaf/obr/command/ObrCommandSupport.java b/obr/command/src/main/java/org/apache/karaf/obr/command/ObrCommandSupport.java
deleted file mode 100644
index 5f038b4..0000000
--- a/obr/command/src/main/java/org/apache/karaf/obr/command/ObrCommandSupport.java
+++ /dev/null
@@ -1,281 +0,0 @@
-/*
- * 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.karaf.obr.command;
-
-import java.io.BufferedReader;
-import java.io.BufferedWriter;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.InputStreamReader;
-import java.io.OutputStreamWriter;
-import java.io.PrintStream;
-import java.util.List;
-
-import org.apache.felix.bundlerepository.Reason;
-import org.apache.felix.bundlerepository.Repository;
-import org.apache.felix.bundlerepository.RepositoryAdmin;
-import org.apache.felix.bundlerepository.Requirement;
-import org.apache.felix.bundlerepository.Resolver;
-import org.apache.felix.bundlerepository.Resource;
-import org.apache.karaf.shell.api.action.Action;
-import org.apache.karaf.shell.api.action.lifecycle.Reference;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.InvalidSyntaxException;
-import org.osgi.framework.Version;
-
-public abstract class ObrCommandSupport implements Action {
-
-    protected static final char VERSION_DELIM = ',';
-
-    @Reference
-    private RepositoryAdmin repositoryAdmin;
-
-    @Reference
-    BundleContext bundleContext;
-
-    public void setRepositoryAdmin(RepositoryAdmin repositoryAdmin) {
-        this.repositoryAdmin = repositoryAdmin;
-    }
-
-    @Override
-    public Object execute() throws Exception {
-        doExecute(repositoryAdmin);
-        return null;
-    }
-
-    abstract void doExecute(RepositoryAdmin admin) throws Exception;
-
-    protected Resource[] searchRepository(RepositoryAdmin admin, String targetId, String targetVersion) throws InvalidSyntaxException {
-        // Try to see if the targetId is a bundle ID.
-        try {
-            Bundle bundle = bundleContext.getBundle(Long.parseLong(targetId));
-            targetId = bundle.getSymbolicName();
-        } catch (NumberFormatException ex) {
-            // It was not a number, so ignore.
-        }
-
-        // The targetId may be a bundle name or a bundle symbolic name,
-        // so create the appropriate LDAP query.
-        StringBuffer sb = new StringBuffer("(|(presentationname=");
-        sb.append(targetId);
-        sb.append(")(symbolicname=");
-        sb.append(targetId);
-        sb.append("))");
-        if (targetVersion != null) {
-            sb.insert(0, "(&");
-            sb.append("(version=");
-            sb.append(targetVersion);
-            sb.append("))");
-        }
-        return admin.discoverResources(sb.toString());
-    }
-
-    public Resource selectNewestVersion(Resource[] resources) {
-        int idx = -1;
-        Version v = null;
-        for (int i = 0; (resources != null) && (i < resources.length); i++) {
-            if (i == 0) {
-                idx = 0;
-                v = resources[i].getVersion();
-            } else {
-                Version vtmp = resources[i].getVersion();
-                if (vtmp.compareTo(v) > 0) {
-                    idx = i;
-                    v = vtmp;
-                }
-            }
-        }
-        return (idx < 0) ? null : resources[idx];
-    }
-
-    protected String[] getTarget(String bundle) {
-        String[] target;
-        int idx = bundle.indexOf(VERSION_DELIM);
-        if (idx > 0) {
-            target = new String[]{bundle.substring(0, idx), bundle.substring(idx + 1)};
-        } else {
-            target = new String[]{bundle, null};
-        }
-        return target;
-    }
-
-    protected void printUnderline(PrintStream out, int length) {
-        for (int i = 0; i < length; i++) {
-            out.print('-');
-        }
-        out.println("");
-    }
-
-    protected void doDeploy(RepositoryAdmin admin, List<String> bundles, boolean start, boolean deployOptional) throws Exception {
-        Resolver resolver = admin.resolver();
-        for (String bundle : bundles) {
-            String[] target = getTarget(bundle);
-            Resource resource = selectNewestVersion(searchRepository(admin, target[0], target[1]));
-            if (resource != null) {
-                resolver.add(resource);
-            } else {
-                System.err.println("Unknown bundle - " + target[0]);
-            }
-        }
-        if ((resolver.getAddedResources() != null) &&
-                (resolver.getAddedResources().length > 0)) {
-            if (resolver.resolve(deployOptional ? 0 : Resolver.NO_OPTIONAL_RESOURCES)) {
-                System.out.println("Target resource(s):");
-                printUnderline(System.out, 19);
-                Resource[] resources = resolver.getAddedResources();
-                for (int resIdx = 0; (resources != null) && (resIdx < resources.length); resIdx++) {
-                    System.out.println("   " + resources[resIdx].getPresentationName()
-                            + " (" + resources[resIdx].getVersion() + ")");
-                }
-                resources = resolver.getRequiredResources();
-                if ((resources != null) && (resources.length > 0)) {
-                    System.out.println("\nRequired resource(s):");
-                    printUnderline(System.out, 21);
-                    for (int resIdx = 0; resIdx < resources.length; resIdx++) {
-                        System.out.println("   " + resources[resIdx].getPresentationName()
-                                + " (" + resources[resIdx].getVersion() + ")");
-                    }
-                }
-                if (deployOptional) {
-                    resources = resolver.getOptionalResources();
-                    if ((resources != null) && (resources.length > 0)) {
-                        System.out.println("\nOptional resource(s):");
-                        printUnderline(System.out, 21);
-                        for (int resIdx = 0; resIdx < resources.length; resIdx++) {
-                            System.out.println("   " + resources[resIdx].getPresentationName() + " (" + resources[resIdx].getVersion() + ")");
-                        }
-                    }
-                }
-
-                try {
-                    System.out.print("\nDeploying...");
-                    resolver.deploy(start ? Resolver.START : 0);
-                    System.out.println("done.");
-                } catch (IllegalStateException ex) {
-                    System.err.println(ex);
-                }
-            } else {
-                Reason[] reqs = resolver.getUnsatisfiedRequirements();
-                if ((reqs != null) && (reqs.length > 0)) {
-                    System.out.println("Unsatisfied requirement(s):");
-                    printUnderline(System.out, 27);
-                    for (int reqIdx = 0; reqIdx < reqs.length; reqIdx++) {
-                        System.out.println("   " + reqs[reqIdx].getRequirement().getFilter());
-                        System.out.println("      " + reqs[reqIdx].getResource().getPresentationName());
-                    }
-                } else {
-                    System.out.println("Could not resolve targets.");
-                }
-            }
-        }
-
-    }
-
-
-    protected Requirement parseRequirement(RepositoryAdmin admin, String req) throws InvalidSyntaxException {
-        int p = req.indexOf(':');
-        String name;
-        String filter;
-        if (p > 0) {
-            name = req.substring(0, p);
-            filter = req.substring(p + 1);
-        } else {
-            if (req.contains("package")) {
-                name = "package";
-            } else if (req.contains("service")) {
-                name = "service";
-            } else {
-                name = "bundle";
-            }
-            filter = req;
-        }
-        if (!filter.startsWith("(")) {
-            filter = "(" + filter + ")";
-        }
-        return admin.getHelper().requirement(name, filter);
-    }
-
-    protected Requirement[] parseRequirements(RepositoryAdmin admin, List<String> requirements) throws InvalidSyntaxException {
-        Requirement[] reqs = new Requirement[requirements.size()];
-        for (int i = 0; i < reqs.length; i++) {
-            reqs[i] = parseRequirement(admin, requirements.get(i));
-        }
-        return reqs;
-    }
-
-    public static final String REPOSITORY_URL_PROP = "obr.repository.url";
-
-    protected void persistRepositoryList(RepositoryAdmin admin) {
-        try {
-            StringBuilder sb = new StringBuilder();
-            for (Repository repo : admin.listRepositories()) {
-                if (sb.length() > 0) {
-                    sb.append(" ");
-                }
-                sb.append(repo.getURI());
-            }
-            File etc = new File(System.getProperty("karaf.etc"));
-            File sys = new File(etc, "config.properties");
-            File sysTmp = new File(etc, "config.properties.tmp");
-
-            BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(sysTmp)));
-            boolean modified = false;
-            try {
-                if (sys.exists()) {
-                    BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(sys)));
-                    try {
-                        String line = reader.readLine();
-                        while (line != null) {
-                            if (line.matches("obr\\.repository\\.url[:= ].*")) {
-                                modified = true;
-                                line = "obr.repository.url = " + sb.toString();
-                            }
-                            writer.write(line);
-                            writer.newLine();
-                            line = reader.readLine();
-                        }
-                    } finally {
-                        reader.close();
-                    }
-                }
-                if (!modified) {
-                    writer.newLine();
-                    writer.write("# ");
-                    writer.newLine();
-                    writer.write("# OBR Repository list");
-                    writer.newLine();
-                    writer.write("# ");
-                    writer.newLine();
-                    writer.write("obr.repository.url = " + sb.toString());
-                    writer.newLine();
-                    writer.newLine();
-                }
-            } finally {
-                writer.close();
-            }
-
-            sys.delete();
-            sysTmp.renameTo(sys);
-
-        } catch (Exception e) {
-            System.err.println("Error while persisting repository list");
-        }
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/b0a20b83/obr/command/src/main/java/org/apache/karaf/obr/command/RefreshUrlCommand.java
----------------------------------------------------------------------
diff --git a/obr/command/src/main/java/org/apache/karaf/obr/command/RefreshUrlCommand.java b/obr/command/src/main/java/org/apache/karaf/obr/command/RefreshUrlCommand.java
deleted file mode 100644
index 20a65ed..0000000
--- a/obr/command/src/main/java/org/apache/karaf/obr/command/RefreshUrlCommand.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * 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.karaf.obr.command;
-
-import java.util.List;
-
-import org.apache.felix.bundlerepository.Repository;
-import org.apache.felix.bundlerepository.RepositoryAdmin;
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Option;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-
-@Command(scope = "obr", name = "url-refresh", description = "Reloads the repositories to obtain a fresh list of bundles.")
-@Service
-public class RefreshUrlCommand extends ObrCommandSupport {
-
-    @Option(name = "-i", aliases = { "--index" }, description = "Use index to identify URL", required = false, multiValued = false)
-    boolean useIndex;
-
-    @Argument(index = 0, name = "ids", description = "Repository URLs (or indexes if you use -i) to refresh (leave empty for all)", required = false, multiValued = true)
-    List<String> ids;
-
-    protected void doExecute(RepositoryAdmin admin) throws Exception {
-		if (ids != null && !ids.isEmpty()) {
-			for (String id : ids) {
-                if (useIndex) {
-                    Repository[] repos = admin.listRepositories();
-                    int index = Integer.parseInt(id);
-                    if (index >= 0 && index < repos.length) {
-                        admin.addRepository(repos[index].getURI());
-                    } else {
-                        System.err.println("Invalid index");
-                    }
-                } else {
-				    admin.addRepository(id);
-                }
-			}
-		} else {
-			Repository[] repos = admin.listRepositories();
-			if ((repos != null) && (repos.length > 0)) {
-				for (int i = 0; i < repos.length; i++) {
-					admin.addRepository(repos[i].getURI());
-				}
-			}
-		}
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/b0a20b83/obr/command/src/main/java/org/apache/karaf/obr/command/RemoveUrlCommand.java
----------------------------------------------------------------------
diff --git a/obr/command/src/main/java/org/apache/karaf/obr/command/RemoveUrlCommand.java b/obr/command/src/main/java/org/apache/karaf/obr/command/RemoveUrlCommand.java
deleted file mode 100644
index 2d41519..0000000
--- a/obr/command/src/main/java/org/apache/karaf/obr/command/RemoveUrlCommand.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * 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.karaf.obr.command;
-
-import java.util.List;
-
-import org.apache.felix.bundlerepository.Repository;
-import org.apache.felix.bundlerepository.RepositoryAdmin;
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Option;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-
-@Command(scope = "obr", name = "url-remove", description = "Removes a list of repository URLs from the OBR service.")
-@Service
-public class RemoveUrlCommand extends ObrCommandSupport {
-
-    @Option(name = "-i", aliases = { "--index" }, description = "Use index to identify URL", required = false, multiValued = false)
-    boolean useIndex;
-
-    @Argument(index = 0, name = "ids", description = "Repository URLs (or indexes if you use -i) to remove from OBR service", required = true, multiValued = true)
-    List<String> ids;
-
-    protected void doExecute(RepositoryAdmin admin) throws Exception {
-        for (String id : ids) {
-            if (useIndex) {
-                Repository[] repos = admin.listRepositories();
-                int index = Integer.parseInt(id);
-                if (index >= 0 && index < repos.length) {
-                    admin.removeRepository(repos[index].getURI());
-                } else {
-                    System.err.println("Invalid index");
-                }
-            } else {
-                admin.removeRepository(id);
-            }
-        }
-        persistRepositoryList(admin);
-    }
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/b0a20b83/obr/command/src/main/java/org/apache/karaf/obr/command/ResolveCommand.java
----------------------------------------------------------------------
diff --git a/obr/command/src/main/java/org/apache/karaf/obr/command/ResolveCommand.java b/obr/command/src/main/java/org/apache/karaf/obr/command/ResolveCommand.java
deleted file mode 100644
index ab1bd04..0000000
--- a/obr/command/src/main/java/org/apache/karaf/obr/command/ResolveCommand.java
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
- * 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.karaf.obr.command;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-
-import org.apache.felix.bundlerepository.Reason;
-import org.apache.felix.bundlerepository.Repository;
-import org.apache.felix.bundlerepository.RepositoryAdmin;
-import org.apache.felix.bundlerepository.Requirement;
-import org.apache.felix.bundlerepository.Resolver;
-import org.apache.felix.bundlerepository.Resource;
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Option;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-
-@Command(scope = "obr", name = "resolve", description = "Shows the resolution output for a given set of requirements.")
-@Service
-public class ResolveCommand extends ObrCommandSupport {
-
-    @Option(name = "-w", aliases = "--why", description = "Display the reason of the inclusion of the resource")
-    boolean why;
-
-    @Option(name = "-l", aliases = "--no-local", description = "Ignore local resources during resolution")
-    boolean noLocal;
-
-    @Option(name = "--no-remote", description = "Ignore remote resources during resolution")
-    boolean noRemote;
-
-    @Option(name = "--deploy", description = "Deploy the selected bundles")
-    boolean deploy;
-
-    @Option(name = "--start", description = "Deploy and start the selected bundles")
-    boolean start;
-
-    @Option(name = "--optional", description = "Resolve optional dependencies")
-    boolean optional;
-
-    @Argument(index = 0, name = "requirements", description = "Requirements", required = true, multiValued = true)
-    List<String> requirements;
-
-    protected void doExecute(RepositoryAdmin admin) throws Exception {
-        List<Repository> repositories = new ArrayList<Repository>();
-        repositories.add(admin.getSystemRepository());
-        if (!noLocal) {
-            repositories.add(admin.getLocalRepository());
-        }
-        if (!noRemote) {
-            repositories.addAll(Arrays.asList(admin.listRepositories()));
-        }
-        Resolver resolver = admin.resolver(repositories.toArray(new Repository[repositories.size()]));
-        for (Requirement requirement : parseRequirements(admin, requirements)) {
-            resolver.add(requirement);
-        }
-        if (resolver.resolve(optional ? 0 : Resolver.NO_OPTIONAL_RESOURCES)) {
-            Resource[] resources;
-            resources = resolver.getRequiredResources();
-            if ((resources != null) && (resources.length > 0)) {
-                System.out.println("Required resource(s):");
-                printUnderline(System.out, 21);
-                for (int resIdx = 0; resIdx < resources.length; resIdx++) {
-                    System.out.println("   " + resources[resIdx].getPresentationName() + " (" + resources[resIdx].getVersion() + ")");
-                    if (why) {
-                        Reason[] req = resolver.getReason(resources[resIdx]);
-                        for (int reqIdx = 0; req != null && reqIdx < req.length; reqIdx++) {
-                            if (!req[reqIdx].getRequirement().isOptional()) {
-                                Resource r = req[reqIdx].getResource();
-                                if (r != null) {
-                                    System.out.println("      - " + r.getPresentationName() + " / " + req[reqIdx].getRequirement().getName() + ":" + req[reqIdx].getRequirement().getFilter());
-                                } else {
-                                    System.out.println("      - " + req[reqIdx].getRequirement().getName() + ":" + req[reqIdx].getRequirement().getFilter());
-                                }
-                            }
-                        }
-                    }
-                }
-            }
-            resources = resolver.getOptionalResources();
-            if ((resources != null) && (resources.length > 0)) {
-                System.out.println();
-                System.out.println("Optional resource(s):");
-                printUnderline(System.out, 21);
-                for (int resIdx = 0; resIdx < resources.length; resIdx++) {
-                    System.out.println("   " + resources[resIdx].getPresentationName()
-                        + " (" + resources[resIdx].getVersion() + ")");
-                    if (why) {
-                        Reason[] req = resolver.getReason(resources[resIdx]);
-                        for (int reqIdx = 0; req != null && reqIdx < req.length; reqIdx++) {
-                            if (!req[reqIdx].getRequirement().isOptional()) {
-                                Resource r = req[reqIdx].getResource();
-                                if (r != null) {
-                                    System.out.println("      - " + r.getPresentationName() + " / " + req[reqIdx].getRequirement().getName() + ":" + req[reqIdx].getRequirement().getFilter());
-                                } else {
-                                    System.out.println("      - " + req[reqIdx].getRequirement().getName() + ":" + req[reqIdx].getRequirement().getFilter());
-                                }
-                            }
-                        }
-                    }
-                }
-            }
-            if (deploy || start) {
-                try
-                {
-                    System.out.print("\nDeploying...");
-                    resolver.deploy(start ? Resolver.START : 0);
-                    System.out.println("done.");
-                }
-                catch (IllegalStateException ex)
-                {
-                    System.err.println(ex);
-                }
-            }
-        } else {
-            Reason[] reqs = resolver.getUnsatisfiedRequirements();
-            if ((reqs != null) && (reqs.length > 0)) {
-                System.out.println("Unsatisfied requirement(s):");
-                printUnderline(System.out, 27);
-                for (int reqIdx = 0; reqIdx < reqs.length; reqIdx++) {
-                    System.out.println("   " + reqs[reqIdx].getRequirement().getName() + ":" + reqs[reqIdx].getRequirement().getFilter());
-                    System.out.println("      " +reqs[reqIdx].getResource().getPresentationName());
-                }
-            } else {
-                System.out.println("Could not resolve targets.");
-            }
-        }
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/b0a20b83/obr/command/src/main/java/org/apache/karaf/obr/command/SourceCommand.java
----------------------------------------------------------------------
diff --git a/obr/command/src/main/java/org/apache/karaf/obr/command/SourceCommand.java b/obr/command/src/main/java/org/apache/karaf/obr/command/SourceCommand.java
deleted file mode 100644
index 161ba82..0000000
--- a/obr/command/src/main/java/org/apache/karaf/obr/command/SourceCommand.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * 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.karaf.obr.command;
-
-import java.net.URI;
-import java.util.List;
-
-import org.apache.felix.bundlerepository.RepositoryAdmin;
-import org.apache.felix.bundlerepository.Resource;
-import org.apache.karaf.obr.command.util.FileUtil;
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Option;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-
-@Command(scope = "obr", name = "source", description = "Downloads the sources for an OBR bundle.")
-@Service
-public class SourceCommand extends ObrCommandSupport {
-
-    @Option(name = "-x", aliases = {}, description = "Extract the archive", required = false, multiValued = false)
-    boolean extract;
-
-    @Argument(index = 0, name = "folder", description = "Local folder for storing sources", required = true, multiValued = false)
-    String localDir;
-
-    @Argument(index = 1, name = "bundles", description = "List of bundles to download the sources for", required = true, multiValued = true)
-    List<String> bundles;
-
-    protected void doExecute(RepositoryAdmin admin) throws Exception {
-        for (String bundle : bundles) {
-            String[] target = getTarget(bundle);
-            Resource resource = selectNewestVersion(searchRepository(admin, target[0], target[1]));
-            if (resource == null)
-            {
-                System.err.println("Unknown bundle and/or version: " + target[0]);
-            }
-            else
-            {
-                URI srcURL = (URI) resource.getProperties().get(Resource.SOURCE_URI);
-                if (srcURL != null)
-                {
-                    FileUtil.downloadSource(System.out, System.err, srcURL.toURL(), localDir, extract);
-                }
-                else
-                {
-                    System.err.println("Missing source URL: " + target[0]);
-                }
-            }
-        }
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/b0a20b83/obr/command/src/main/java/org/apache/karaf/obr/command/StartCommand.java
----------------------------------------------------------------------
diff --git a/obr/command/src/main/java/org/apache/karaf/obr/command/StartCommand.java b/obr/command/src/main/java/org/apache/karaf/obr/command/StartCommand.java
deleted file mode 100644
index 0465bae..0000000
--- a/obr/command/src/main/java/org/apache/karaf/obr/command/StartCommand.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * 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.karaf.obr.command;
-
-import org.apache.felix.bundlerepository.RepositoryAdmin;
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Option;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-
-import java.util.List;
-
-@Command(scope = "obr", name = "start", description = "Deploys and starts a list of bundles using OBR.")
-@Service
-public class StartCommand extends ObrCommandSupport {
-
-    @Argument(index = 0, name = "bundles", description = "List of bundles to deploy (separated by whitespaces)", required = true, multiValued = true)
-    protected List<String> bundles;
-
-    @Option(name = "-d", aliases = { "--deployOptional" }, description = "Deploy optional bundles", required = false, multiValued = false)
-    protected boolean deployOptional = false;
-
-    protected void doExecute(RepositoryAdmin admin) throws Exception {
-        doDeploy(admin, bundles, true, deployOptional);
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/b0a20b83/obr/command/src/main/java/org/apache/karaf/obr/command/util/FileUtil.java
----------------------------------------------------------------------
diff --git a/obr/command/src/main/java/org/apache/karaf/obr/command/util/FileUtil.java b/obr/command/src/main/java/org/apache/karaf/obr/command/util/FileUtil.java
deleted file mode 100644
index 26aa0bd..0000000
--- a/obr/command/src/main/java/org/apache/karaf/obr/command/util/FileUtil.java
+++ /dev/null
@@ -1,177 +0,0 @@
-/*
- * 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.karaf.obr.command.util;
-
-import java.io.BufferedOutputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.PrintStream;
-import java.net.URL;
-import java.net.URLConnection;
-import java.util.jar.JarEntry;
-import java.util.jar.JarInputStream;
-
-public class FileUtil
-{
-    public static void downloadSource(
-        PrintStream out, PrintStream err,
-        URL srcURL, String dirStr, boolean extract)
-    {
-        // Get the file name from the URL.
-        String fileName = (srcURL.getFile().lastIndexOf('/') > 0)
-            ? srcURL.getFile().substring(srcURL.getFile().lastIndexOf('/') + 1)
-            : srcURL.getFile();
-
-        try
-        {
-            out.println("Connecting...");
-
-            File dir = new File(dirStr);
-            if (!dir.exists())
-            {
-                err.println("Destination directory does not exist.");
-            }
-            File file = new File(dir, fileName);
-
-            OutputStream os = new FileOutputStream(file);
-            URLConnection conn = srcURL.openConnection();
-            int total = conn.getContentLength();
-            InputStream is = conn.getInputStream();
-
-            if (total > 0)
-            {
-                out.println("Downloading " + fileName
-                    + " ( " + total + " bytes ).");
-            }
-            else
-            {
-                out.println("Downloading " + fileName + ".");
-            }
-            byte[] buffer = new byte[4096];
-            int count = 0;
-            for (int len = is.read(buffer); len > 0; len = is.read(buffer))
-            {
-                count += len;
-                os.write(buffer, 0, len);
-            }
-
-            os.close();
-            is.close();
-
-            if (extract)
-            {
-                is = new FileInputStream(file);
-                JarInputStream jis = new JarInputStream(is);
-                out.println("Extracting...");
-                unjar(jis, dir);
-                jis.close();
-                file.delete();
-            }
-        }
-        catch (Exception ex)
-        {
-            err.println(ex);
-        }
-    }
-
-    public static void unjar(JarInputStream jis, File dir)
-        throws IOException
-    {
-        // Reusable buffer.
-        byte[] buffer = new byte[4096];
-
-        // Loop through JAR entries.
-        for (JarEntry je = jis.getNextJarEntry();
-             je != null;
-             je = jis.getNextJarEntry())
-        {
-            if (je.getName().startsWith("/"))
-            {
-                throw new IOException("JAR resource cannot contain absolute paths.");
-            }
-
-            File target = new File(dir, je.getName());
-
-            // Check to see if the JAR entry is a directory.
-            if (je.isDirectory())
-            {
-                if (!target.exists())
-                {
-                    if (!target.mkdirs())
-                    {
-                        throw new IOException("Unable to create target directory: "
-                            + target);
-                    }
-                }
-                // Just continue since directories do not have content to copy.
-                continue;
-            }
-
-            int lastIndex = je.getName().lastIndexOf('/');
-            String name = (lastIndex >= 0) ?
-                je.getName().substring(lastIndex + 1) : je.getName();
-            String destination = (lastIndex >= 0) ?
-                je.getName().substring(0, lastIndex) : "";
-
-            // JAR files use '/', so convert it to platform separator.
-            destination = destination.replace('/', File.separatorChar);
-            copy(jis, dir, name, destination, buffer);
-        }
-    }
-
-    public static void copy(
-        InputStream is, File dir, String destName, String destDir, byte[] buffer)
-        throws IOException
-    {
-        if (destDir == null)
-        {
-            destDir = "";
-        }
-
-        // Make sure the target directory exists and
-        // that is actually a directory.
-        File targetDir = new File(dir, destDir);
-        if (!targetDir.exists())
-        {
-            if (!targetDir.mkdirs())
-            {
-                throw new IOException("Unable to create target directory: "
-                    + targetDir);
-            }
-        }
-        else if (!targetDir.isDirectory())
-        {
-            throw new IOException("Target is not a directory: "
-                + targetDir);
-        }
-
-        BufferedOutputStream bos = new BufferedOutputStream(
-            new FileOutputStream(new File(targetDir, destName)));
-        int count = 0;
-        while ((count = is.read(buffer)) > 0)
-        {
-            bos.write(buffer, 0, count);
-        }
-        bos.close();
-    }
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/b0a20b83/obr/command/src/main/resources/OSGI-INF/bundle.info
----------------------------------------------------------------------
diff --git a/obr/command/src/main/resources/OSGI-INF/bundle.info b/obr/command/src/main/resources/OSGI-INF/bundle.info
deleted file mode 100644
index cb73396..0000000
--- a/obr/command/src/main/resources/OSGI-INF/bundle.info
+++ /dev/null
@@ -1,29 +0,0 @@
-h1. Synopsis
-
-${project.name}
-
-${project.description}
-
-Maven URL:
-[mvn:${project.groupId}/${project.artifactId}/${project.version}]
-
-h1. Description
-
-This bundle provides Karaf shell commands to manipulate the Karaf embedded OBR (OSGi Bundle Repository).
-
-The following commands are available:
-* obr:addUrl - Adds a list of repository URLs to the OBR service.
-* obr:deploy - Deploys a list of bundles using OBR service.
-* obr:find - Find OBR bundles for a given filter.
-* obr:info - Prints information about OBR bundles.
-* obr:list - Lists OBR bundles.
-* obr:listUrl - Displays the repository URLs currently associated with the OBR service.
-* obr:refreshUrl - Reloads the repositories to obtain a fresh list of bundles.
-* obr:removeUrl - Removes a list of repository URLs from the OBR service.
-* obr:resolve - Shows the resolution output for a given set of requirements.
-* obr:source - Downloads the sources for an OBR bundle.
-* obr:start - Deploys and starts a list of bundles using OBR.
-
-h1. See also
-
-Commands - and Provisioning - sections of the Karaf User Guide.
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/karaf/blob/b0a20b83/obr/command/src/test/java/org/apache/karaf/obr/command/ListCommandTest.java
----------------------------------------------------------------------
diff --git a/obr/command/src/test/java/org/apache/karaf/obr/command/ListCommandTest.java b/obr/command/src/test/java/org/apache/karaf/obr/command/ListCommandTest.java
deleted file mode 100644
index a4bbb17..0000000
--- a/obr/command/src/test/java/org/apache/karaf/obr/command/ListCommandTest.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * 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.karaf.obr.command;
-
-import org.apache.felix.bundlerepository.RepositoryAdmin;
-import org.apache.felix.bundlerepository.Resource;
-import org.apache.felix.bundlerepository.impl.ResourceImpl;
-import org.easymock.EasyMock;
-import org.easymock.IMocksControl;
-import org.junit.Test;
-
-public class ListCommandTest {
-
-	/**
-	 * Show how the list of obr resources looks like 
-	 * @throws Exception
-	 */
-	@Test
-	public void testList() throws Exception {
-		IMocksControl control = EasyMock.createControl();
-		RepositoryAdmin repoAdmin = control.createMock(RepositoryAdmin.class);
-		ListCommand command = new ListCommand();
-		command.setRepositoryAdmin(repoAdmin);
-		
-		Resource[] resources = new Resource[] {
-			createResource("My bundle", "my.bundle", "1.0.0"),
-			createResource("My other Bundle", "org.apache.mybundle", "2.0.1")
-		};
-		EasyMock.expect(repoAdmin.discoverResources("(|(presentationname=*)(symbolicname=*))")).
-			andReturn(resources);
-		
-		control.replay();
-		command.execute();
-		control.verify();
-	}
-
-	private Resource createResource(String presentationName, String symbolicName, String version) {
-		ResourceImpl r1 = new ResourceImpl();
-		r1.put(Resource.PRESENTATION_NAME, presentationName);
-		r1.put(Resource.SYMBOLIC_NAME, symbolicName);
-		r1.put(Resource.VERSION, version);
-		return r1;
-	}
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/b0a20b83/obr/core/NOTICE
----------------------------------------------------------------------
diff --git a/obr/core/NOTICE b/obr/core/NOTICE
deleted file mode 100644
index b70f1f9..0000000
--- a/obr/core/NOTICE
+++ /dev/null
@@ -1,71 +0,0 @@
-Apache Karaf
-Copyright 2010-2014 The Apache Software Foundation
-
-
-I. Included Software
-
-This product includes software developed at
-The Apache Software Foundation (http://www.apache.org/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-The OSGi Alliance (http://www.osgi.org/).
-Copyright (c) OSGi Alliance (2000, 2010).
-Licensed under the Apache License 2.0.
-
-This product includes software developed at
-OW2 (http://www.ow2.org/).
-Licensed under the BSD License.
-
-This product includes software developed at
-OPS4J (http://www.ops4j.org/).
-Licensed under the Apache License 2.0.
-
-This product includes software developed at
-Eclipse Foundation (http://www.eclipse.org/).
-Licensed under the EPL.
-
-This product includes software written by
-Antony Lesuisse.
-Licensed under Public Domain.
-
-
-II. Used Software
-
-This product uses software developed at
-FUSE Source (http://www.fusesource.org/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-AOP Alliance (http://aopalliance.sourceforge.net/).
-Licensed under the Public Domain.
-
-This product uses software developed at
-Tanuki Software (http://www.tanukisoftware.com/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-Jasypt (http://jasypt.sourceforge.net/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-JLine (http://jline.sourceforge.net).
-Licensed under the BSD License.
-
-This product uses software developed at
-SLF4J (http://www.slf4j.org/).
-Licensed under the MIT License.
-
-This product uses software developed at
-SpringSource (http://www.springsource.org/).
-Licensed under the Apache License 2.0.
-
-This product includes software from http://www.json.org.
-Copyright (c) 2002 JSON.org
-
-
-III. License Summary
-- Apache License 2.0
-- BSD License
-- EPL License
-- MIT License

http://git-wip-us.apache.org/repos/asf/karaf/blob/b0a20b83/obr/core/pom.xml
----------------------------------------------------------------------
diff --git a/obr/core/pom.xml b/obr/core/pom.xml
deleted file mode 100644
index a9af4c3..0000000
--- a/obr/core/pom.xml
+++ /dev/null
@@ -1,87 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-
-    <!--
-
-        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.
-    -->
-
-    <modelVersion>4.0.0</modelVersion>
-
-    <parent>
-        <groupId>org.apache.karaf.obr</groupId>
-        <artifactId>obr</artifactId>
-        <version>4.0.0-SNAPSHOT</version>
-        <relativePath>../pom.xml</relativePath>
-    </parent>
-
-    <artifactId>org.apache.karaf.obr.core</artifactId>
-    <packaging>bundle</packaging>
-    <name>Apache Karaf :: OBR :: Core</name>
-    <description>OBR core services and MBeans</description>
-
-    <properties>
-        <appendedResourcesDirectory>${basedir}/../../../etc/appended-resources/</appendedResourcesDirectory>
-    </properties>
-
-    <dependencies>
-        <dependency>
-            <groupId>org.osgi</groupId>
-            <artifactId>org.osgi.core</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.felix</groupId>
-            <artifactId>org.apache.felix.bundlerepository</artifactId>
-            <scope>provided</scope>
-        </dependency>
-    </dependencies>
-
-    <build>
-        <resources>
-            <resource>
-                <directory>src/main/resources</directory>
-                <includes>
-                    <include>**/*</include>
-                </includes>
-            </resource>
-            <resource>
-                <directory>src/main/resources</directory>
-                <filtering>true</filtering>
-                <includes>
-                    <include>**/*.info</include>
-                </includes>
-            </resource>
-        </resources>
-        <plugins>
-            <plugin>
-                <groupId>org.apache.felix</groupId>
-                <artifactId>maven-bundle-plugin</artifactId>
-                <configuration>
-                    <instructions>
-                        <Export-Package>
-                            org.apache.karaf.obr.core
-                        </Export-Package>
-                        <Private-Package>
-                            org.apache.karaf.obr.core.internal
-                        </Private-Package>
-                    </instructions>
-                </configuration>
-            </plugin>
-        </plugins>
-    </build>
-
-</project>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/karaf/blob/b0a20b83/obr/core/src/main/java/org/apache/karaf/obr/core/ObrMBean.java
----------------------------------------------------------------------
diff --git a/obr/core/src/main/java/org/apache/karaf/obr/core/ObrMBean.java b/obr/core/src/main/java/org/apache/karaf/obr/core/ObrMBean.java
deleted file mode 100644
index bf5ebcb..0000000
--- a/obr/core/src/main/java/org/apache/karaf/obr/core/ObrMBean.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * 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.karaf.obr.core;
-
-import javax.management.MBeanException;
-import javax.management.openmbean.TabularData;
-import java.util.List;
-
-/**
- * OBR MBean.
- */
-public interface ObrMBean {
-
-    List<String> getUrls();
-    TabularData getBundles() throws MBeanException;
-
-    void addUrl(String url) throws MBeanException;
-    void removeUrl(String url);
-    void refreshUrl(String url) throws MBeanException;
-
-    void deployBundle(String bundle) throws MBeanException;
-    void deployBundle(String bundle, boolean start, boolean deployOptional) throws MBeanException;
-}


[40/59] [abbrv] git commit: [KARAF-2852] Merge service/command into service/core

Posted by gn...@apache.org.
[KARAF-2852] Merge service/command into service/core


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

Branch: refs/heads/master
Commit: 149822e903f5236ec48ce03af21dcfee8ade12b5
Parents: 91232f8
Author: Guillaume Nodet <gn...@gmail.com>
Authored: Wed Apr 9 23:26:53 2014 +0200
Committer: Guillaume Nodet <gn...@gmail.com>
Committed: Thu Apr 10 16:02:27 2014 +0200

----------------------------------------------------------------------
 .../standard/src/main/feature/feature.xml       |   1 -
 .../karaf/service/command/ListServices.java     | 163 -------------------
 .../service/command/ObjectClassCompleter.java   |  58 -------
 .../service/command/ObjectClassMatcher.java     |  43 -----
 .../org/apache/karaf/service/command/Wait.java  |  86 ----------
 .../service/command/ListServiceNamesTest.java   |  34 ----
 .../karaf/service/command/ListServicesTest.java |  35 ----
 .../service/command/ObjectClassMatcherTest.java |  45 -----
 .../service/command/TestBundleFactory.java      | 104 ------------
 service/core/pom.xml                            |   7 +
 .../karaf/service/command/ListServices.java     | 163 +++++++++++++++++++
 .../service/command/ObjectClassCompleter.java   |  58 +++++++
 .../service/command/ObjectClassMatcher.java     |  43 +++++
 .../org/apache/karaf/service/command/Wait.java  |  86 ++++++++++
 .../service/command/ListServiceNamesTest.java   |  34 ++++
 .../karaf/service/command/ListServicesTest.java |  35 ++++
 .../service/command/ObjectClassMatcherTest.java |  45 +++++
 .../service/command/TestBundleFactory.java      | 104 ++++++++++++
 service/pom.xml                                 |   1 -
 19 files changed, 575 insertions(+), 570 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/karaf/blob/149822e9/assemblies/features/standard/src/main/feature/feature.xml
----------------------------------------------------------------------
diff --git a/assemblies/features/standard/src/main/feature/feature.xml b/assemblies/features/standard/src/main/feature/feature.xml
index ae6ab68..90c38db 100644
--- a/assemblies/features/standard/src/main/feature/feature.xml
+++ b/assemblies/features/standard/src/main/feature/feature.xml
@@ -161,7 +161,6 @@
 
     <feature name="service" description="Provide Service support" version="${project.version}">
         <bundle start-level="30" start="true">mvn:org.apache.karaf.service/org.apache.karaf.service.core/${project.version}</bundle>
-        <bundle start-level="30" start="true">mvn:org.apache.karaf.service/org.apache.karaf.service.command/${project.version}</bundle>
     </feature>
 
     <feature name="system" description="Provide System support" version="${project.version}">

http://git-wip-us.apache.org/repos/asf/karaf/blob/149822e9/service/command/src/main/java/org/apache/karaf/service/command/ListServices.java
----------------------------------------------------------------------
diff --git a/service/command/src/main/java/org/apache/karaf/service/command/ListServices.java b/service/command/src/main/java/org/apache/karaf/service/command/ListServices.java
deleted file mode 100644
index caf546b..0000000
--- a/service/command/src/main/java/org/apache/karaf/service/command/ListServices.java
+++ /dev/null
@@ -1,163 +0,0 @@
-/*
- * 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.karaf.service.command;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import org.apache.karaf.shell.api.action.Action;
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Completion;
-import org.apache.karaf.shell.api.action.Option;
-import org.apache.karaf.shell.api.action.lifecycle.Reference;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.apache.karaf.shell.support.ShellUtil;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.Constants;
-import org.osgi.framework.ServiceReference;
-
-@Command(scope = "service", name = "list", description = "Lists OSGi services.")
-@Service
-public class ListServices implements Action {
-
-    @Argument(index = 0, name = "objectClass", description = "Name of service objectClass to filter for", required = false,
-        multiValued = false)
-    @Completion(ObjectClassCompleter.class)
-    String objectClass;
-    
-    @Option(name = "-a", aliases = {}, description = "Shows all services. (By default Karaf commands are hidden)", required = false, multiValued = false)
-    boolean showAll;
-    
-    @Option(name = "-n", aliases = {}, description = "Shows only service class names", required = false, multiValued = false)
-    boolean onlyNames;
-
-    @Reference
-    BundleContext bundleContext;
-
-    @Override
-    public Object execute() throws Exception {
-        if (onlyNames) {
-            listNames();
-            return null;
-        }
-        List<ServiceReference<?>> serviceRefs = new ArrayList<ServiceReference<?>>();
-        Bundle[] bundles = bundleContext.getBundles();
-        for (Bundle bundle : bundles) {
-            ServiceReference<?>[] services = bundle.getRegisteredServices();
-            if (services != null) {
-                for (ServiceReference<?> ref : services) {
-                    String[] objectClasses = (String[])ref.getProperty(Constants.OBJECTCLASS);
-                    if (objectClass == null || ObjectClassMatcher.matchesAtLeastOneName(objectClasses, objectClass)) {
-                        serviceRefs.add(ref);
-                    }
-                } 
-            }
-        }
-        
-        Collections.sort(serviceRefs, new ServiceClassComparator());
-        
-        for (ServiceReference<?> serviceRef : serviceRefs) {
-            if (showAll || !isCommand((String[])serviceRef.getProperty(Constants.OBJECTCLASS))) {
-                printServiceRef(serviceRef);
-            }
-        }
-        return null;
-    }
-    
-    private void listNames() {
-        Map<String, Integer> serviceNames = getServiceNamesMap(bundleContext);
-        ArrayList<String> serviceNamesList = new ArrayList<String>(serviceNames.keySet());
-        Collections.sort(serviceNamesList);
-        for (String name : serviceNamesList) {
-            System.out.println(name + " (" + serviceNames.get(name) + ")");
-        }
-    }
-    
-    public static Map<String, Integer> getServiceNamesMap(BundleContext bundleContext) {
-        Map<String, Integer> serviceNames = new HashMap<String, Integer>();
-        Bundle[] bundles = bundleContext.getBundles();
-        for (Bundle bundle : bundles) {
-            ServiceReference<?>[] services = bundle.getRegisteredServices();
-            if (services != null) {
-                for (ServiceReference<?> serviceReference : services) {
-                    String[] names = (String[])serviceReference.getProperty(Constants.OBJECTCLASS);
-                    for (String name : names) {
-                        int curCount = (serviceNames.containsKey(name)) ? serviceNames.get(name) : 0;
-                        serviceNames.put(name, curCount + 1);
-                    }
-                }
-            }
-        }
-        return serviceNames;
-    }
-
-    private void printServiceRef(ServiceReference<?> serviceRef) {
-        String[] objectClass = (String[]) serviceRef.getProperty(Constants.OBJECTCLASS);
-        String serviceClasses = ShellUtil.getValueString(objectClass);
-        System.out.println(serviceClasses);
-        System.out.println(ShellUtil.getUnderlineString(serviceClasses));
-        
-        printProperties(serviceRef);
-        
-        String bundleName = ShellUtil.getBundleName(serviceRef.getBundle());
-        System.out.println("Provided by : ");
-        System.out.println(" " + bundleName);
-        if (serviceRef.getUsingBundles() != null) {
-        System.out.println("Used by: ");
-            for (Bundle bundle : serviceRef.getUsingBundles()) {
-                System.out.println(" " + ShellUtil.getBundleName(bundle));
-            }
-        }
-        System.out.println();
-    }
-
-    private boolean isCommand(String[] objectClasses) {
-        for (String objectClass : objectClasses) {
-            if (objectClass.equals("org.apache.felix.service.command.Function")) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    private void printProperties(ServiceReference<?> serviceRef) {
-        for (String key : serviceRef.getPropertyKeys()) {
-            if (!Constants.OBJECTCLASS.equals(key)) {
-                System.out.println(" " + key + " = " + ShellUtil.getValueString(serviceRef.getProperty(key)));
-            }
-        }
-    }
-
-    public final class ServiceClassComparator implements Comparator<ServiceReference<?>> {
-        @Override
-        public int compare(ServiceReference<?> o1, ServiceReference<?> o2) {
-            String[] classes1 = (String[])o1.getProperty(Constants.OBJECTCLASS);
-            String[] classes2 = (String[])o2.getProperty(Constants.OBJECTCLASS);
-            return classes1[0].compareTo(classes2[0]);
-        }
-    }
-
-    public void setBundleContext(BundleContext bundleContext) {
-        this.bundleContext = bundleContext;
-    }
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/149822e9/service/command/src/main/java/org/apache/karaf/service/command/ObjectClassCompleter.java
----------------------------------------------------------------------
diff --git a/service/command/src/main/java/org/apache/karaf/service/command/ObjectClassCompleter.java b/service/command/src/main/java/org/apache/karaf/service/command/ObjectClassCompleter.java
deleted file mode 100644
index 6b62b0c..0000000
--- a/service/command/src/main/java/org/apache/karaf/service/command/ObjectClassCompleter.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * 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.karaf.service.command;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import org.apache.karaf.shell.api.action.lifecycle.Reference;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.apache.karaf.shell.api.console.CommandLine;
-import org.apache.karaf.shell.api.console.Completer;
-import org.apache.karaf.shell.api.console.Session;
-import org.apache.karaf.shell.support.completers.StringsCompleter;
-import org.osgi.framework.BundleContext;
-
-@Service
-public class ObjectClassCompleter implements Completer {
-
-    @Reference
-    private BundleContext context;
-
-    public void setContext(BundleContext context) {
-        this.context = context;
-    }
-
-    @SuppressWarnings("rawtypes")
-    @Override
-    public int complete(final Session session, final CommandLine commandLine, final List<String> candidates) {
-        Map<String, Integer> serviceNamesMap = ListServices.getServiceNamesMap(context);
-        Set<String> serviceNames = serviceNamesMap.keySet();
-        List<String> strings = new ArrayList<String>();
-        for (String name : serviceNames) {
-            strings.add(ObjectClassMatcher.getShortName(name));
-        }
-        strings.addAll(serviceNames);
-        return new StringsCompleter(strings).complete(session, commandLine, candidates);
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/149822e9/service/command/src/main/java/org/apache/karaf/service/command/ObjectClassMatcher.java
----------------------------------------------------------------------
diff --git a/service/command/src/main/java/org/apache/karaf/service/command/ObjectClassMatcher.java b/service/command/src/main/java/org/apache/karaf/service/command/ObjectClassMatcher.java
deleted file mode 100644
index 9068aed..0000000
--- a/service/command/src/main/java/org/apache/karaf/service/command/ObjectClassMatcher.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * 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.karaf.service.command;
-
-public class ObjectClassMatcher {
-    private ObjectClassMatcher() {
-    }
-    
-    static boolean matchesAtLeastOneName(String[] names, String pattern) {
-        for (String objectClass : names) {
-            if (matchesName(objectClass, pattern)) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    static boolean matchesName(String name, String pattern) {
-        return name.equals(pattern) || getShortName(name).equals(pattern);
-    }
-    
-    static String getShortName(String name) {
-        int idx = name.lastIndexOf(".");
-        if (idx + 1 > name.length()) {
-            idx = 0;
-        }
-        return name.substring(idx + 1);
-    }
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/149822e9/service/command/src/main/java/org/apache/karaf/service/command/Wait.java
----------------------------------------------------------------------
diff --git a/service/command/src/main/java/org/apache/karaf/service/command/Wait.java b/service/command/src/main/java/org/apache/karaf/service/command/Wait.java
deleted file mode 100644
index 9a0d286..0000000
--- a/service/command/src/main/java/org/apache/karaf/service/command/Wait.java
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * 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.karaf.service.command;
-
-import java.util.concurrent.TimeoutException;
-
-import org.apache.karaf.shell.api.action.Action;
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Option;
-import org.apache.karaf.shell.api.action.lifecycle.Reference;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.Constants;
-import org.osgi.framework.Filter;
-import org.osgi.framework.FrameworkUtil;
-import org.osgi.framework.InvalidSyntaxException;
-import org.osgi.util.tracker.ServiceTracker;
-
-/**
- * Command that can be used to wait for an OSGi service.
- */
-@Command(scope = "service", name = "wait", description = "Wait for a given OSGi service.")
-@Service
-public class Wait implements Action {
-
-    @Option(name = "-e", aliases = { "--exception" }, description = "throw an exception if the service is not found after the timeout")
-    boolean exception;
-
-    @Option(name = "-t", aliases = { "--timeout" }, description = "timeout to wait for the service (in milliseconds, negative to not wait at all, zero to wait forever)")
-    long timeout = 0;
-
-    @Argument(name = "service", description="The service class or filter", required = true, multiValued = false)
-    String service;
-
-    @Reference
-    BundleContext bundleContext;
-
-    @Override
-    public Object execute() throws Exception {
-        ServiceTracker<?,?> tracker = null;
-        try {
-            String filter = service;
-            if (!filter.startsWith("(")) {
-                if (!filter.contains("=")) {
-                    filter = Constants.OBJECTCLASS + "=" + filter;
-                }
-                filter = "(" + filter + ")";
-            }
-            Filter osgiFilter = FrameworkUtil.createFilter(filter);
-            tracker = new ServiceTracker<Object, Object>(bundleContext, osgiFilter, null);
-            tracker.open(true);
-            Object svc = tracker.getService();
-            if (timeout >= 0) {
-                svc = tracker.waitForService(timeout);
-            }
-            if (exception && svc == null) {
-                throw new TimeoutException("Can not find service '" + service + "' in the OSGi registry");
-            }
-            return svc != null;
-        } catch (InvalidSyntaxException e) {
-            throw new IllegalArgumentException("Invalid filter", e);
-        } catch (InterruptedException e) {
-            throw new RuntimeException(e);
-        } finally {
-            if (tracker != null) {
-                tracker.close();
-            }
-        }
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/149822e9/service/command/src/test/java/org/apache/karaf/service/command/ListServiceNamesTest.java
----------------------------------------------------------------------
diff --git a/service/command/src/test/java/org/apache/karaf/service/command/ListServiceNamesTest.java b/service/command/src/test/java/org/apache/karaf/service/command/ListServiceNamesTest.java
deleted file mode 100644
index 9f42147..0000000
--- a/service/command/src/test/java/org/apache/karaf/service/command/ListServiceNamesTest.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * 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.karaf.service.command;
-import org.junit.Test;
-
-public class ListServiceNamesTest {
-
-    public ListServiceNamesTest() {
-        
-    }
-    
-    @Test
-    public void listAll() throws Exception {
-        ListServices listServices = new ListServices();
-        listServices.setBundleContext(new TestBundleFactory().createBundleContext());
-        listServices.onlyNames = true;
-        listServices.execute();
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/149822e9/service/command/src/test/java/org/apache/karaf/service/command/ListServicesTest.java
----------------------------------------------------------------------
diff --git a/service/command/src/test/java/org/apache/karaf/service/command/ListServicesTest.java b/service/command/src/test/java/org/apache/karaf/service/command/ListServicesTest.java
deleted file mode 100644
index 510de6c..0000000
--- a/service/command/src/test/java/org/apache/karaf/service/command/ListServicesTest.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * 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.karaf.service.command;
-
-import org.junit.Test;
-
-public class ListServicesTest {
-
-    public ListServicesTest() {
-        
-    }
-    
-    @Test
-    public void listAll() throws Exception {
-        ListServices listServices = new ListServices();
-        listServices.setBundleContext(new TestBundleFactory().createBundleContext());
-        listServices.execute();
-    }
-    
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/149822e9/service/command/src/test/java/org/apache/karaf/service/command/ObjectClassMatcherTest.java
----------------------------------------------------------------------
diff --git a/service/command/src/test/java/org/apache/karaf/service/command/ObjectClassMatcherTest.java b/service/command/src/test/java/org/apache/karaf/service/command/ObjectClassMatcherTest.java
deleted file mode 100644
index 296b591..0000000
--- a/service/command/src/test/java/org/apache/karaf/service/command/ObjectClassMatcherTest.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * 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.karaf.service.command;
-
-import junit.framework.Assert;
-
-import org.junit.Test;
-
-public class ObjectClassMatcherTest {
-
-    @Test
-    public void testGetShortName() {
-        Assert.assertEquals("TestClass", ObjectClassMatcher.getShortName("org.apache.TestClass"));
-        Assert.assertEquals("", ObjectClassMatcher.getShortName("test."));
-        Assert.assertEquals("TestClass", ObjectClassMatcher.getShortName("TestClass"));
-    }
-
-    @Test
-    public void testMatchesName() {
-        Assert.assertTrue(ObjectClassMatcher.matchesName("org.apache.TestClass", "TestClass"));
-        Assert.assertTrue(ObjectClassMatcher.matchesName("TestClass", "TestClass"));
-    }
-
-    @Test
-    public void testMatchesAtLeastOneName() {
-        Assert.assertTrue(ObjectClassMatcher.matchesAtLeastOneName(new String[]{"other", "org.apache.TestClass"}, "TestClass"));
-        Assert.assertFalse(ObjectClassMatcher.matchesAtLeastOneName(new String[]{"TestClass2"}, "TestClass"));
-    }
-
-    
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/149822e9/service/command/src/test/java/org/apache/karaf/service/command/TestBundleFactory.java
----------------------------------------------------------------------
diff --git a/service/command/src/test/java/org/apache/karaf/service/command/TestBundleFactory.java b/service/command/src/test/java/org/apache/karaf/service/command/TestBundleFactory.java
deleted file mode 100644
index 3d83670..0000000
--- a/service/command/src/test/java/org/apache/karaf/service/command/TestBundleFactory.java
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * 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.karaf.service.command;
-
-import static org.easymock.EasyMock.createMock;
-import static org.easymock.EasyMock.expect;
-import static org.easymock.EasyMock.replay;
-
-import java.util.Collections;
-import java.util.Dictionary;
-import java.util.Hashtable;
-
-import org.osgi.framework.Bundle;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.Constants;
-import org.osgi.framework.ServiceReference;
-
-public class TestBundleFactory {
-    ServiceReference<?> createServiceRef(Object ... keyProp) {
-        ServiceReference<?> serviceRef = createMock(ServiceReference.class);
-        if (keyProp.length % 2 != 0) {
-            throw new IllegalArgumentException("");
-        }
-        Hashtable<String, Object> keyPropMap = new Hashtable<String, Object>();
-        int c = 0;
-        while (c < keyProp.length) {
-            String key = (String)keyProp[c++];
-            Object value = (Object)keyProp[c++];
-            keyPropMap.put(key, value);
-            expect(serviceRef.getProperty(key)).andReturn(value).anyTimes();
-        }
-        expect(serviceRef.getPropertyKeys()).andReturn(Collections.list(keyPropMap.keys()).toArray(new String[]{})).anyTimes();
-        return serviceRef;
-    }
-    
-    Bundle createBundle(long id, String name) {
-        Bundle bundle = createMock(Bundle.class);
-        expect(bundle.getBundleId()).andReturn(id).anyTimes();
-        Dictionary<String, String> headers = new Hashtable<String, String>();
-        headers.put(Constants.BUNDLE_NAME, name);
-        expect(bundle.getHeaders()).andReturn(headers).anyTimes();
-        return bundle;
-    }
-    
-    private Bundle[] createBundles() {
-        Bundle bundle1 = createBundle(1, "Bundle A");
-        Bundle bundle2 = createBundle(2, "Bundle B");
-        Bundle bundle3 = createBundle(3, "Bundle C");
-
-        ServiceReference<?> ref1 = createServiceRef(Constants.OBJECTCLASS, new String[]{"org.example.MyService"},
-            "key1", "value1");
-        ServiceReference<?> ref2 = createServiceRef(Constants.OBJECTCLASS, new String[]{"org.example.OtherService"}, "key2", 1);
-
-        addRegisteredServices(bundle1, ref1, ref2);
-        addRegisteredServices(bundle2, ref2);
-        expect(bundle3.getRegisteredServices()).andReturn(null).anyTimes();
-
-        expect(bundle1.getServicesInUse()).andReturn(null).anyTimes();
-        addUsedServices(bundle2, ref1);
-        addUsedServices(bundle3, ref1, ref2);
-        
-        expect(ref1.getUsingBundles()).andReturn(new Bundle[]{bundle2, bundle3}).anyTimes();
-        expect(ref2.getUsingBundles()).andReturn(new Bundle[]{bundle3}).anyTimes();
-
-        replay(bundle1, bundle2, bundle3, ref1, ref2);
-        return new Bundle[] { bundle1, bundle2, bundle3 };
-    }
-    
-    private void addUsedServices(Bundle bundle, ServiceReference<?> ... refs) {
-        expect(bundle.getServicesInUse()).andReturn(refs).anyTimes();
-    }
-    
-    private void addRegisteredServices(Bundle bundle, ServiceReference<?> ... refs) {
-        expect(bundle.getRegisteredServices()).andReturn(refs).anyTimes();
-        for (ServiceReference<?> ref : refs) {
-            expect(ref.getBundle()).andReturn(bundle);
-        }
-    }
-
-    public BundleContext createBundleContext() {
-        BundleContext bundleContext = createMock(BundleContext.class);
-        Bundle[] bundles = createBundles();
-        expect(bundleContext.getBundles()).andReturn(bundles).anyTimes();
-        expect(bundleContext.getBundle(0)).andReturn(null).anyTimes();
-        expect(bundleContext.getBundle(1)).andReturn(bundles[0]).anyTimes();
-        expect(bundleContext.getBundle(2)).andReturn(bundles[1]).anyTimes();
-        replay(bundleContext);
-        return bundleContext;
-    }
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/149822e9/service/core/pom.xml
----------------------------------------------------------------------
diff --git a/service/core/pom.xml b/service/core/pom.xml
index e617fc3..4d10257 100644
--- a/service/core/pom.xml
+++ b/service/core/pom.xml
@@ -48,6 +48,11 @@
             <artifactId>org.apache.karaf.util</artifactId>
             <scope>provided</scope>
         </dependency>
+        <dependency>
+            <groupId>org.apache.karaf.shell</groupId>
+            <artifactId>org.apache.karaf.shell.core</artifactId>
+            <optional>true</optional>
+        </dependency>
 
     </dependencies>
 
@@ -77,6 +82,7 @@
                             org.apache.karaf.service.core;-noimport:=true
                         </Export-Package>
                         <Private-Package>
+                            org.apache.karaf.service.command,
                             org.apache.karaf.service.core.internal,
                             org.apache.karaf.service.core.internal.osgi,
                             org.apache.karaf.util.tracker
@@ -84,6 +90,7 @@
                         <Bundle-Activator>
                             org.apache.karaf.service.core.internal.osgi.Activator
                         </Bundle-Activator>
+                        <Karaf-Commands>org.apache.karaf.service.command</Karaf-Commands>
                     </instructions>
                 </configuration>
             </plugin>

http://git-wip-us.apache.org/repos/asf/karaf/blob/149822e9/service/core/src/main/java/org/apache/karaf/service/command/ListServices.java
----------------------------------------------------------------------
diff --git a/service/core/src/main/java/org/apache/karaf/service/command/ListServices.java b/service/core/src/main/java/org/apache/karaf/service/command/ListServices.java
new file mode 100644
index 0000000..caf546b
--- /dev/null
+++ b/service/core/src/main/java/org/apache/karaf/service/command/ListServices.java
@@ -0,0 +1,163 @@
+/*
+ * 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.karaf.service.command;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.karaf.shell.api.action.Action;
+import org.apache.karaf.shell.api.action.Argument;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.Completion;
+import org.apache.karaf.shell.api.action.Option;
+import org.apache.karaf.shell.api.action.lifecycle.Reference;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.apache.karaf.shell.support.ShellUtil;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceReference;
+
+@Command(scope = "service", name = "list", description = "Lists OSGi services.")
+@Service
+public class ListServices implements Action {
+
+    @Argument(index = 0, name = "objectClass", description = "Name of service objectClass to filter for", required = false,
+        multiValued = false)
+    @Completion(ObjectClassCompleter.class)
+    String objectClass;
+    
+    @Option(name = "-a", aliases = {}, description = "Shows all services. (By default Karaf commands are hidden)", required = false, multiValued = false)
+    boolean showAll;
+    
+    @Option(name = "-n", aliases = {}, description = "Shows only service class names", required = false, multiValued = false)
+    boolean onlyNames;
+
+    @Reference
+    BundleContext bundleContext;
+
+    @Override
+    public Object execute() throws Exception {
+        if (onlyNames) {
+            listNames();
+            return null;
+        }
+        List<ServiceReference<?>> serviceRefs = new ArrayList<ServiceReference<?>>();
+        Bundle[] bundles = bundleContext.getBundles();
+        for (Bundle bundle : bundles) {
+            ServiceReference<?>[] services = bundle.getRegisteredServices();
+            if (services != null) {
+                for (ServiceReference<?> ref : services) {
+                    String[] objectClasses = (String[])ref.getProperty(Constants.OBJECTCLASS);
+                    if (objectClass == null || ObjectClassMatcher.matchesAtLeastOneName(objectClasses, objectClass)) {
+                        serviceRefs.add(ref);
+                    }
+                } 
+            }
+        }
+        
+        Collections.sort(serviceRefs, new ServiceClassComparator());
+        
+        for (ServiceReference<?> serviceRef : serviceRefs) {
+            if (showAll || !isCommand((String[])serviceRef.getProperty(Constants.OBJECTCLASS))) {
+                printServiceRef(serviceRef);
+            }
+        }
+        return null;
+    }
+    
+    private void listNames() {
+        Map<String, Integer> serviceNames = getServiceNamesMap(bundleContext);
+        ArrayList<String> serviceNamesList = new ArrayList<String>(serviceNames.keySet());
+        Collections.sort(serviceNamesList);
+        for (String name : serviceNamesList) {
+            System.out.println(name + " (" + serviceNames.get(name) + ")");
+        }
+    }
+    
+    public static Map<String, Integer> getServiceNamesMap(BundleContext bundleContext) {
+        Map<String, Integer> serviceNames = new HashMap<String, Integer>();
+        Bundle[] bundles = bundleContext.getBundles();
+        for (Bundle bundle : bundles) {
+            ServiceReference<?>[] services = bundle.getRegisteredServices();
+            if (services != null) {
+                for (ServiceReference<?> serviceReference : services) {
+                    String[] names = (String[])serviceReference.getProperty(Constants.OBJECTCLASS);
+                    for (String name : names) {
+                        int curCount = (serviceNames.containsKey(name)) ? serviceNames.get(name) : 0;
+                        serviceNames.put(name, curCount + 1);
+                    }
+                }
+            }
+        }
+        return serviceNames;
+    }
+
+    private void printServiceRef(ServiceReference<?> serviceRef) {
+        String[] objectClass = (String[]) serviceRef.getProperty(Constants.OBJECTCLASS);
+        String serviceClasses = ShellUtil.getValueString(objectClass);
+        System.out.println(serviceClasses);
+        System.out.println(ShellUtil.getUnderlineString(serviceClasses));
+        
+        printProperties(serviceRef);
+        
+        String bundleName = ShellUtil.getBundleName(serviceRef.getBundle());
+        System.out.println("Provided by : ");
+        System.out.println(" " + bundleName);
+        if (serviceRef.getUsingBundles() != null) {
+        System.out.println("Used by: ");
+            for (Bundle bundle : serviceRef.getUsingBundles()) {
+                System.out.println(" " + ShellUtil.getBundleName(bundle));
+            }
+        }
+        System.out.println();
+    }
+
+    private boolean isCommand(String[] objectClasses) {
+        for (String objectClass : objectClasses) {
+            if (objectClass.equals("org.apache.felix.service.command.Function")) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private void printProperties(ServiceReference<?> serviceRef) {
+        for (String key : serviceRef.getPropertyKeys()) {
+            if (!Constants.OBJECTCLASS.equals(key)) {
+                System.out.println(" " + key + " = " + ShellUtil.getValueString(serviceRef.getProperty(key)));
+            }
+        }
+    }
+
+    public final class ServiceClassComparator implements Comparator<ServiceReference<?>> {
+        @Override
+        public int compare(ServiceReference<?> o1, ServiceReference<?> o2) {
+            String[] classes1 = (String[])o1.getProperty(Constants.OBJECTCLASS);
+            String[] classes2 = (String[])o2.getProperty(Constants.OBJECTCLASS);
+            return classes1[0].compareTo(classes2[0]);
+        }
+    }
+
+    public void setBundleContext(BundleContext bundleContext) {
+        this.bundleContext = bundleContext;
+    }
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/149822e9/service/core/src/main/java/org/apache/karaf/service/command/ObjectClassCompleter.java
----------------------------------------------------------------------
diff --git a/service/core/src/main/java/org/apache/karaf/service/command/ObjectClassCompleter.java b/service/core/src/main/java/org/apache/karaf/service/command/ObjectClassCompleter.java
new file mode 100644
index 0000000..6b62b0c
--- /dev/null
+++ b/service/core/src/main/java/org/apache/karaf/service/command/ObjectClassCompleter.java
@@ -0,0 +1,58 @@
+/*
+ * 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.karaf.service.command;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.karaf.shell.api.action.lifecycle.Reference;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.apache.karaf.shell.api.console.CommandLine;
+import org.apache.karaf.shell.api.console.Completer;
+import org.apache.karaf.shell.api.console.Session;
+import org.apache.karaf.shell.support.completers.StringsCompleter;
+import org.osgi.framework.BundleContext;
+
+@Service
+public class ObjectClassCompleter implements Completer {
+
+    @Reference
+    private BundleContext context;
+
+    public void setContext(BundleContext context) {
+        this.context = context;
+    }
+
+    @SuppressWarnings("rawtypes")
+    @Override
+    public int complete(final Session session, final CommandLine commandLine, final List<String> candidates) {
+        Map<String, Integer> serviceNamesMap = ListServices.getServiceNamesMap(context);
+        Set<String> serviceNames = serviceNamesMap.keySet();
+        List<String> strings = new ArrayList<String>();
+        for (String name : serviceNames) {
+            strings.add(ObjectClassMatcher.getShortName(name));
+        }
+        strings.addAll(serviceNames);
+        return new StringsCompleter(strings).complete(session, commandLine, candidates);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/149822e9/service/core/src/main/java/org/apache/karaf/service/command/ObjectClassMatcher.java
----------------------------------------------------------------------
diff --git a/service/core/src/main/java/org/apache/karaf/service/command/ObjectClassMatcher.java b/service/core/src/main/java/org/apache/karaf/service/command/ObjectClassMatcher.java
new file mode 100644
index 0000000..9068aed
--- /dev/null
+++ b/service/core/src/main/java/org/apache/karaf/service/command/ObjectClassMatcher.java
@@ -0,0 +1,43 @@
+/*
+ * 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.karaf.service.command;
+
+public class ObjectClassMatcher {
+    private ObjectClassMatcher() {
+    }
+    
+    static boolean matchesAtLeastOneName(String[] names, String pattern) {
+        for (String objectClass : names) {
+            if (matchesName(objectClass, pattern)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    static boolean matchesName(String name, String pattern) {
+        return name.equals(pattern) || getShortName(name).equals(pattern);
+    }
+    
+    static String getShortName(String name) {
+        int idx = name.lastIndexOf(".");
+        if (idx + 1 > name.length()) {
+            idx = 0;
+        }
+        return name.substring(idx + 1);
+    }
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/149822e9/service/core/src/main/java/org/apache/karaf/service/command/Wait.java
----------------------------------------------------------------------
diff --git a/service/core/src/main/java/org/apache/karaf/service/command/Wait.java b/service/core/src/main/java/org/apache/karaf/service/command/Wait.java
new file mode 100644
index 0000000..9a0d286
--- /dev/null
+++ b/service/core/src/main/java/org/apache/karaf/service/command/Wait.java
@@ -0,0 +1,86 @@
+/*
+ * 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.karaf.service.command;
+
+import java.util.concurrent.TimeoutException;
+
+import org.apache.karaf.shell.api.action.Action;
+import org.apache.karaf.shell.api.action.Argument;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.Option;
+import org.apache.karaf.shell.api.action.lifecycle.Reference;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.osgi.framework.Filter;
+import org.osgi.framework.FrameworkUtil;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.util.tracker.ServiceTracker;
+
+/**
+ * Command that can be used to wait for an OSGi service.
+ */
+@Command(scope = "service", name = "wait", description = "Wait for a given OSGi service.")
+@Service
+public class Wait implements Action {
+
+    @Option(name = "-e", aliases = { "--exception" }, description = "throw an exception if the service is not found after the timeout")
+    boolean exception;
+
+    @Option(name = "-t", aliases = { "--timeout" }, description = "timeout to wait for the service (in milliseconds, negative to not wait at all, zero to wait forever)")
+    long timeout = 0;
+
+    @Argument(name = "service", description="The service class or filter", required = true, multiValued = false)
+    String service;
+
+    @Reference
+    BundleContext bundleContext;
+
+    @Override
+    public Object execute() throws Exception {
+        ServiceTracker<?,?> tracker = null;
+        try {
+            String filter = service;
+            if (!filter.startsWith("(")) {
+                if (!filter.contains("=")) {
+                    filter = Constants.OBJECTCLASS + "=" + filter;
+                }
+                filter = "(" + filter + ")";
+            }
+            Filter osgiFilter = FrameworkUtil.createFilter(filter);
+            tracker = new ServiceTracker<Object, Object>(bundleContext, osgiFilter, null);
+            tracker.open(true);
+            Object svc = tracker.getService();
+            if (timeout >= 0) {
+                svc = tracker.waitForService(timeout);
+            }
+            if (exception && svc == null) {
+                throw new TimeoutException("Can not find service '" + service + "' in the OSGi registry");
+            }
+            return svc != null;
+        } catch (InvalidSyntaxException e) {
+            throw new IllegalArgumentException("Invalid filter", e);
+        } catch (InterruptedException e) {
+            throw new RuntimeException(e);
+        } finally {
+            if (tracker != null) {
+                tracker.close();
+            }
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/149822e9/service/core/src/test/java/org/apache/karaf/service/command/ListServiceNamesTest.java
----------------------------------------------------------------------
diff --git a/service/core/src/test/java/org/apache/karaf/service/command/ListServiceNamesTest.java b/service/core/src/test/java/org/apache/karaf/service/command/ListServiceNamesTest.java
new file mode 100644
index 0000000..9f42147
--- /dev/null
+++ b/service/core/src/test/java/org/apache/karaf/service/command/ListServiceNamesTest.java
@@ -0,0 +1,34 @@
+/*
+ * 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.karaf.service.command;
+import org.junit.Test;
+
+public class ListServiceNamesTest {
+
+    public ListServiceNamesTest() {
+        
+    }
+    
+    @Test
+    public void listAll() throws Exception {
+        ListServices listServices = new ListServices();
+        listServices.setBundleContext(new TestBundleFactory().createBundleContext());
+        listServices.onlyNames = true;
+        listServices.execute();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/149822e9/service/core/src/test/java/org/apache/karaf/service/command/ListServicesTest.java
----------------------------------------------------------------------
diff --git a/service/core/src/test/java/org/apache/karaf/service/command/ListServicesTest.java b/service/core/src/test/java/org/apache/karaf/service/command/ListServicesTest.java
new file mode 100644
index 0000000..510de6c
--- /dev/null
+++ b/service/core/src/test/java/org/apache/karaf/service/command/ListServicesTest.java
@@ -0,0 +1,35 @@
+/*
+ * 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.karaf.service.command;
+
+import org.junit.Test;
+
+public class ListServicesTest {
+
+    public ListServicesTest() {
+        
+    }
+    
+    @Test
+    public void listAll() throws Exception {
+        ListServices listServices = new ListServices();
+        listServices.setBundleContext(new TestBundleFactory().createBundleContext());
+        listServices.execute();
+    }
+    
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/149822e9/service/core/src/test/java/org/apache/karaf/service/command/ObjectClassMatcherTest.java
----------------------------------------------------------------------
diff --git a/service/core/src/test/java/org/apache/karaf/service/command/ObjectClassMatcherTest.java b/service/core/src/test/java/org/apache/karaf/service/command/ObjectClassMatcherTest.java
new file mode 100644
index 0000000..296b591
--- /dev/null
+++ b/service/core/src/test/java/org/apache/karaf/service/command/ObjectClassMatcherTest.java
@@ -0,0 +1,45 @@
+/*
+ * 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.karaf.service.command;
+
+import junit.framework.Assert;
+
+import org.junit.Test;
+
+public class ObjectClassMatcherTest {
+
+    @Test
+    public void testGetShortName() {
+        Assert.assertEquals("TestClass", ObjectClassMatcher.getShortName("org.apache.TestClass"));
+        Assert.assertEquals("", ObjectClassMatcher.getShortName("test."));
+        Assert.assertEquals("TestClass", ObjectClassMatcher.getShortName("TestClass"));
+    }
+
+    @Test
+    public void testMatchesName() {
+        Assert.assertTrue(ObjectClassMatcher.matchesName("org.apache.TestClass", "TestClass"));
+        Assert.assertTrue(ObjectClassMatcher.matchesName("TestClass", "TestClass"));
+    }
+
+    @Test
+    public void testMatchesAtLeastOneName() {
+        Assert.assertTrue(ObjectClassMatcher.matchesAtLeastOneName(new String[]{"other", "org.apache.TestClass"}, "TestClass"));
+        Assert.assertFalse(ObjectClassMatcher.matchesAtLeastOneName(new String[]{"TestClass2"}, "TestClass"));
+    }
+
+    
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/149822e9/service/core/src/test/java/org/apache/karaf/service/command/TestBundleFactory.java
----------------------------------------------------------------------
diff --git a/service/core/src/test/java/org/apache/karaf/service/command/TestBundleFactory.java b/service/core/src/test/java/org/apache/karaf/service/command/TestBundleFactory.java
new file mode 100644
index 0000000..3d83670
--- /dev/null
+++ b/service/core/src/test/java/org/apache/karaf/service/command/TestBundleFactory.java
@@ -0,0 +1,104 @@
+/*
+ * 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.karaf.service.command;
+
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
+
+import java.util.Collections;
+import java.util.Dictionary;
+import java.util.Hashtable;
+
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceReference;
+
+public class TestBundleFactory {
+    ServiceReference<?> createServiceRef(Object ... keyProp) {
+        ServiceReference<?> serviceRef = createMock(ServiceReference.class);
+        if (keyProp.length % 2 != 0) {
+            throw new IllegalArgumentException("");
+        }
+        Hashtable<String, Object> keyPropMap = new Hashtable<String, Object>();
+        int c = 0;
+        while (c < keyProp.length) {
+            String key = (String)keyProp[c++];
+            Object value = (Object)keyProp[c++];
+            keyPropMap.put(key, value);
+            expect(serviceRef.getProperty(key)).andReturn(value).anyTimes();
+        }
+        expect(serviceRef.getPropertyKeys()).andReturn(Collections.list(keyPropMap.keys()).toArray(new String[]{})).anyTimes();
+        return serviceRef;
+    }
+    
+    Bundle createBundle(long id, String name) {
+        Bundle bundle = createMock(Bundle.class);
+        expect(bundle.getBundleId()).andReturn(id).anyTimes();
+        Dictionary<String, String> headers = new Hashtable<String, String>();
+        headers.put(Constants.BUNDLE_NAME, name);
+        expect(bundle.getHeaders()).andReturn(headers).anyTimes();
+        return bundle;
+    }
+    
+    private Bundle[] createBundles() {
+        Bundle bundle1 = createBundle(1, "Bundle A");
+        Bundle bundle2 = createBundle(2, "Bundle B");
+        Bundle bundle3 = createBundle(3, "Bundle C");
+
+        ServiceReference<?> ref1 = createServiceRef(Constants.OBJECTCLASS, new String[]{"org.example.MyService"},
+            "key1", "value1");
+        ServiceReference<?> ref2 = createServiceRef(Constants.OBJECTCLASS, new String[]{"org.example.OtherService"}, "key2", 1);
+
+        addRegisteredServices(bundle1, ref1, ref2);
+        addRegisteredServices(bundle2, ref2);
+        expect(bundle3.getRegisteredServices()).andReturn(null).anyTimes();
+
+        expect(bundle1.getServicesInUse()).andReturn(null).anyTimes();
+        addUsedServices(bundle2, ref1);
+        addUsedServices(bundle3, ref1, ref2);
+        
+        expect(ref1.getUsingBundles()).andReturn(new Bundle[]{bundle2, bundle3}).anyTimes();
+        expect(ref2.getUsingBundles()).andReturn(new Bundle[]{bundle3}).anyTimes();
+
+        replay(bundle1, bundle2, bundle3, ref1, ref2);
+        return new Bundle[] { bundle1, bundle2, bundle3 };
+    }
+    
+    private void addUsedServices(Bundle bundle, ServiceReference<?> ... refs) {
+        expect(bundle.getServicesInUse()).andReturn(refs).anyTimes();
+    }
+    
+    private void addRegisteredServices(Bundle bundle, ServiceReference<?> ... refs) {
+        expect(bundle.getRegisteredServices()).andReturn(refs).anyTimes();
+        for (ServiceReference<?> ref : refs) {
+            expect(ref.getBundle()).andReturn(bundle);
+        }
+    }
+
+    public BundleContext createBundleContext() {
+        BundleContext bundleContext = createMock(BundleContext.class);
+        Bundle[] bundles = createBundles();
+        expect(bundleContext.getBundles()).andReturn(bundles).anyTimes();
+        expect(bundleContext.getBundle(0)).andReturn(null).anyTimes();
+        expect(bundleContext.getBundle(1)).andReturn(bundles[0]).anyTimes();
+        expect(bundleContext.getBundle(2)).andReturn(bundles[1]).anyTimes();
+        replay(bundleContext);
+        return bundleContext;
+    }
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/149822e9/service/pom.xml
----------------------------------------------------------------------
diff --git a/service/pom.xml b/service/pom.xml
index de16f40..10efab4 100644
--- a/service/pom.xml
+++ b/service/pom.xml
@@ -35,7 +35,6 @@
 
     <modules>
         <module>core</module>
-        <module>command</module>
         <module>guard</module>
     </modules>
 


[38/59] [abbrv] [KARAF-2852] Merge package/core and package/command

Posted by gn...@apache.org.
http://git-wip-us.apache.org/repos/asf/karaf/blob/91232f80/package/src/main/java/org/apache/karaf/packages/core/internal/osgi/Activator.java
----------------------------------------------------------------------
diff --git a/package/src/main/java/org/apache/karaf/packages/core/internal/osgi/Activator.java b/package/src/main/java/org/apache/karaf/packages/core/internal/osgi/Activator.java
new file mode 100644
index 0000000..ea8ce1d
--- /dev/null
+++ b/package/src/main/java/org/apache/karaf/packages/core/internal/osgi/Activator.java
@@ -0,0 +1,34 @@
+/*
+ * 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.karaf.packages.core.internal.osgi;
+
+import org.apache.karaf.packages.core.PackageService;
+import org.apache.karaf.packages.core.internal.PackageServiceImpl;
+import org.apache.karaf.packages.core.internal.PackagesMBeanImpl;
+import org.apache.karaf.util.tracker.BaseActivator;
+
+public class Activator extends BaseActivator {
+
+    @Override
+    protected void doStart() throws Exception {
+        PackageService packageService = new PackageServiceImpl(bundleContext);
+        register(PackageService.class, packageService);
+
+        PackagesMBeanImpl mbean = new PackagesMBeanImpl(packageService);
+        registerMBean(mbean, "type=package");
+    }
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/91232f80/package/src/main/resources/OSGI-INF/bundle.info
----------------------------------------------------------------------
diff --git a/package/src/main/resources/OSGI-INF/bundle.info b/package/src/main/resources/OSGI-INF/bundle.info
new file mode 100644
index 0000000..b5747b7
--- /dev/null
+++ b/package/src/main/resources/OSGI-INF/bundle.info
@@ -0,0 +1,15 @@
+h1. Synopsis
+
+${project.name}
+
+${project.description}
+
+Maven URL:
+   [mvn:${project.groupId}/${project.artifactId}/${project.version}]
+
+h1. Description
+
+Services for handling packages
+
+h1. See also
+

http://git-wip-us.apache.org/repos/asf/karaf/blob/91232f80/package/src/test/java/org/apache/karaf/packages/core/InstallMBeantest.java
----------------------------------------------------------------------
diff --git a/package/src/test/java/org/apache/karaf/packages/core/InstallMBeantest.java b/package/src/test/java/org/apache/karaf/packages/core/InstallMBeantest.java
new file mode 100644
index 0000000..a9ab11b
--- /dev/null
+++ b/package/src/test/java/org/apache/karaf/packages/core/InstallMBeantest.java
@@ -0,0 +1,44 @@
+/*
+ * 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.karaf.packages.core;
+
+import java.lang.management.ManagementFactory;
+
+import javax.management.MBeanServer;
+import javax.management.ObjectName;
+
+import org.apache.karaf.packages.core.internal.PackagesMBeanImpl;
+import org.junit.Test;
+
+/**
+ * Checks that the PackagesMBean is valid and can be installed in the MBeanServer
+ *
+ */
+public class InstallMBeantest {
+
+    @Test
+    public void test() throws Exception {
+        MBeanServer server = ManagementFactory.getPlatformMBeanServer();
+        PackagesMBeanImpl pack = new PackagesMBeanImpl(null);
+        ObjectName oName = new ObjectName("org.apache.karaf:type=package,name=root");
+        server.registerMBean(pack,  oName);
+        server.unregisterMBean(oName);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/91232f80/package/src/test/java/org/apache/karaf/packages/core/PackageRequirementTest.java
----------------------------------------------------------------------
diff --git a/package/src/test/java/org/apache/karaf/packages/core/PackageRequirementTest.java b/package/src/test/java/org/apache/karaf/packages/core/PackageRequirementTest.java
new file mode 100644
index 0000000..2ea1cf8
--- /dev/null
+++ b/package/src/test/java/org/apache/karaf/packages/core/PackageRequirementTest.java
@@ -0,0 +1,32 @@
+/*
+ * 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.karaf.packages.core;
+
+import junit.framework.Assert;
+
+import org.junit.Test;
+
+public class PackageRequirementTest {
+
+    @Test
+    public void testGetPackageName() {
+        PackageRequirement req = new PackageRequirement("(&(osgi.wiring.package=org.osgi.service.useradmin)(version>=1.1.0))", false, null, false);
+        String packageName = req.getPackageName();
+        Assert.assertEquals("org.osgi.service.useradmin", packageName);
+    }
+
+}


[05/59] [abbrv] [KARAF-2852] Merge features/core and features/command

Posted by gn...@apache.org.
http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/src/main/java/org/apache/karaf/features/internal/resolver/ResourceBuilder.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/resolver/ResourceBuilder.java b/features/src/main/java/org/apache/karaf/features/internal/resolver/ResourceBuilder.java
new file mode 100644
index 0000000..cb2c36a
--- /dev/null
+++ b/features/src/main/java/org/apache/karaf/features/internal/resolver/ResourceBuilder.java
@@ -0,0 +1,1129 @@
+/*
+ * 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.karaf.features.internal.resolver;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.felix.utils.version.VersionRange;
+import org.osgi.framework.BundleException;
+import org.osgi.framework.Constants;
+import org.osgi.framework.Version;
+import org.osgi.framework.namespace.IdentityNamespace;
+import org.osgi.framework.wiring.BundleCapability;
+import org.osgi.framework.wiring.BundleRevision;
+import org.osgi.resource.Capability;
+import org.osgi.resource.Requirement;
+import org.osgi.resource.Resource;
+
+public class ResourceBuilder {
+
+    public static final String RESOLUTION_DYNAMIC = "dynamic";
+
+    public static Resource build(String uri, Map<String, String> headerMap)
+            throws BundleException {
+
+        // Verify that only manifest version 2 is specified.
+        String manifestVersion = getManifestVersion(headerMap);
+        if (manifestVersion == null || !manifestVersion.equals("2")) {
+            throw new BundleException("Unsupported 'Bundle-ManifestVersion' value: " + manifestVersion);
+        }
+
+        //
+        // Parse bundle version.
+        //
+
+        Version bundleVersion = Version.emptyVersion;
+        if (headerMap.get(Constants.BUNDLE_VERSION) != null) {
+            bundleVersion = Version.parseVersion(headerMap.get(Constants.BUNDLE_VERSION));
+        }
+
+        //
+        // Parse bundle symbolic name.
+        //
+
+        String bundleSymbolicName = null;
+        ParsedHeaderClause bundleCap = parseBundleSymbolicName(headerMap);
+        if (bundleCap == null) {
+            throw new BundleException("Bundle manifest must include bundle symbolic name");
+        }
+        bundleSymbolicName = (String) bundleCap.attrs.get(BundleRevision.BUNDLE_NAMESPACE);
+
+        // Now that we have symbolic name and version, create the resource
+        String type = headerMap.get(Constants.FRAGMENT_HOST) == null ? IdentityNamespace.TYPE_BUNDLE : IdentityNamespace.TYPE_FRAGMENT;
+        ResourceImpl resource = new ResourceImpl(bundleSymbolicName, type, bundleVersion);
+        if (uri != null) {
+            Map<String, Object> attrs = new HashMap<String, Object>();
+            attrs.put(UriNamespace.URI_NAMESPACE, uri);
+            resource.addCapability(new CapabilityImpl(resource, UriNamespace.URI_NAMESPACE, Collections.<String, String>emptyMap(), attrs));
+        }
+
+        // Add a bundle and host capability to all
+        // non-fragment bundles. A host capability is the same
+        // as a require capability, but with a different capability
+        // namespace. Bundle capabilities resolve required-bundle
+        // dependencies, while host capabilities resolve fragment-host
+        // dependencies.
+        if (headerMap.get(Constants.FRAGMENT_HOST) == null) {
+            // All non-fragment bundles have bundle capability.
+            resource.addCapability(new CapabilityImpl(resource, BundleRevision.BUNDLE_NAMESPACE, bundleCap.dirs, bundleCap.attrs));
+            // A non-fragment bundle can choose to not have a host capability.
+            String attachment = bundleCap.dirs.get(Constants.FRAGMENT_ATTACHMENT_DIRECTIVE);
+            attachment = (attachment == null) ? Constants.FRAGMENT_ATTACHMENT_RESOLVETIME : attachment;
+            if (!attachment.equalsIgnoreCase(Constants.FRAGMENT_ATTACHMENT_NEVER)) {
+                Map<String, Object> hostAttrs = new HashMap<String, Object>(bundleCap.attrs);
+                Object value = hostAttrs.remove(BundleRevision.BUNDLE_NAMESPACE);
+                hostAttrs.put(BundleRevision.HOST_NAMESPACE, value);
+                resource.addCapability(new CapabilityImpl(
+                        resource, BundleRevision.HOST_NAMESPACE,
+                        bundleCap.dirs,
+                        hostAttrs));
+            }
+        }
+
+        //
+        // Parse Fragment-Host.
+        //
+
+        List<RequirementImpl> hostReqs = parseFragmentHost(resource, headerMap);
+
+        //
+        // Parse Require-Bundle
+        //
+
+        List<ParsedHeaderClause> rbClauses = parseStandardHeader(headerMap.get(Constants.REQUIRE_BUNDLE));
+        rbClauses = normalizeRequireClauses(rbClauses);
+        List<Requirement> rbReqs = convertRequires(rbClauses, resource);
+
+        //
+        // Parse Import-Package.
+        //
+
+        List<ParsedHeaderClause> importClauses = parseStandardHeader(headerMap.get(Constants.IMPORT_PACKAGE));
+        importClauses = normalizeImportClauses(importClauses);
+        List<Requirement> importReqs = convertImports(importClauses, resource);
+
+        //
+        // Parse DynamicImport-Package.
+        //
+
+        List<ParsedHeaderClause> dynamicClauses = parseStandardHeader(headerMap.get(Constants.DYNAMICIMPORT_PACKAGE));
+        dynamicClauses = normalizeDynamicImportClauses(dynamicClauses);
+        List<Requirement> dynamicReqs = convertImports(dynamicClauses, resource);
+
+        //
+        // Parse Require-Capability.
+        //
+
+        List<ParsedHeaderClause> requireClauses = parseStandardHeader(headerMap.get(Constants.REQUIRE_CAPABILITY));
+        requireClauses = normalizeRequireCapabilityClauses(requireClauses);
+        List<Requirement> requireReqs = convertRequireCapabilities(requireClauses, resource);
+
+        //
+        // Parse Export-Package.
+        //
+
+        List<ParsedHeaderClause> exportClauses = parseStandardHeader(headerMap.get(Constants.EXPORT_PACKAGE));
+        exportClauses = normalizeExportClauses(exportClauses, bundleSymbolicName, bundleVersion);
+        List<Capability> exportCaps = convertExports(exportClauses, resource);
+
+        //
+        // Parse Provide-Capability.
+        //
+
+        List<ParsedHeaderClause> provideClauses = parseStandardHeader(headerMap.get(Constants.PROVIDE_CAPABILITY));
+        provideClauses = normalizeProvideCapabilityClauses(provideClauses);
+        List<Capability> provideCaps = convertProvideCapabilities(provideClauses, resource);
+
+        //
+        // Parse Import-Service and Export-Service
+        // if Require-Capability and Provide-Capability are not set for services
+        //
+
+        boolean hasServiceReferenceCapability = false;
+        for (Capability cap : exportCaps) {
+            hasServiceReferenceCapability |= ServiceNamespace.SERVICE_NAMESPACE.equals(cap.getNamespace());
+        }
+        if (!hasServiceReferenceCapability) {
+            List<ParsedHeaderClause> exportServices = parseStandardHeader(headerMap.get(Constants.EXPORT_SERVICE));
+            List<Capability> caps = convertExportService(exportServices, resource);
+            provideCaps.addAll(caps);
+        }
+
+        boolean hasServiceReferenceRequirement = false;
+        for (Requirement req : requireReqs) {
+            hasServiceReferenceRequirement |= ServiceNamespace.SERVICE_NAMESPACE.equals(req.getNamespace());
+        }
+        if (!hasServiceReferenceRequirement) {
+            List<ParsedHeaderClause> importServices = parseStandardHeader(headerMap.get(Constants.IMPORT_SERVICE));
+            List<Requirement> reqs = convertImportService(importServices, resource);
+            requireReqs.addAll(reqs);
+        }
+
+        // Combine all capabilities.
+        resource.addCapabilities(exportCaps);
+        resource.addCapabilities(provideCaps);
+
+        // Combine all requirements.
+        resource.addRequirements(hostReqs);
+        resource.addRequirements(importReqs);
+        resource.addRequirements(rbReqs);
+        resource.addRequirements(requireReqs);
+        resource.addRequirements(dynamicReqs);
+
+        return resource;
+    }
+
+    public static List<Requirement> parseImport(Resource resource, String imports) throws BundleException {
+        List<ParsedHeaderClause> importClauses = parseStandardHeader(imports);
+        importClauses = normalizeImportClauses(importClauses);
+        List<Requirement> importReqs = convertImports(importClauses, resource);
+        return importReqs;
+    }
+
+    public static List<Requirement> parseRequirement(Resource resource, String requirement) throws BundleException {
+        List<ParsedHeaderClause> requireClauses = parseStandardHeader(requirement);
+        requireClauses = normalizeRequireCapabilityClauses(requireClauses);
+        List<Requirement> requireReqs = convertRequireCapabilities(requireClauses, resource);
+        return requireReqs;
+    }
+
+    public static List<Capability> parseExport(Resource resource, String bundleSymbolicName, Version bundleVersion, String exports) throws BundleException {
+        List<ParsedHeaderClause> exportClauses = parseStandardHeader(exports);
+        exportClauses = normalizeExportClauses(exportClauses, bundleSymbolicName, bundleVersion);
+        List<Capability> exportCaps = convertExports(exportClauses, resource);
+        return exportCaps;
+    }
+
+    public static List<Capability> parseCapability(Resource resource, String capability) throws BundleException {
+        List<ParsedHeaderClause> provideClauses = parseStandardHeader(capability);
+        provideClauses = normalizeProvideCapabilityClauses(provideClauses);
+        List<Capability> provideCaps = convertProvideCapabilities(provideClauses, resource);
+        return provideCaps;
+    }
+
+    @SuppressWarnings( "deprecation" )
+    private static List<ParsedHeaderClause> normalizeImportClauses(
+            List<ParsedHeaderClause> clauses)
+            throws BundleException {
+        // Verify that the values are equals if the package specifies
+        // both version and specification-version attributes.
+        Set<String> dupeSet = new HashSet<String>();
+        for (ParsedHeaderClause clause : clauses) {
+            // Check for "version" and "specification-version" attributes
+            // and verify they are the same if both are specified.
+            Object v = clause.attrs.get(Constants.VERSION_ATTRIBUTE);
+            Object sv = clause.attrs.get(Constants.PACKAGE_SPECIFICATION_VERSION);
+            if ((v != null) && (sv != null)) {
+                // Verify they are equal.
+                if (!((String) v).trim().equals(((String) sv).trim())) {
+                    throw new IllegalArgumentException(
+                            "Both version and specification-version are specified, but they are not equal.");
+                }
+            }
+
+            // Ensure that only the "version" attribute is used and convert
+            // it to the VersionRange type.
+            if ((v != null) || (sv != null)) {
+                clause.attrs.remove(Constants.PACKAGE_SPECIFICATION_VERSION);
+                v = (v == null) ? sv : v;
+                clause.attrs.put(Constants.VERSION_ATTRIBUTE, VersionRange.parseVersionRange(v.toString()));
+            }
+
+            // If bundle version is specified, then convert its type to VersionRange.
+            v = clause.attrs.get(Constants.BUNDLE_VERSION_ATTRIBUTE);
+            if (v != null) {
+                clause.attrs.put(Constants.BUNDLE_VERSION_ATTRIBUTE, VersionRange.parseVersionRange(v.toString()));
+            }
+
+            // Verify java.* is not imported, nor any duplicate imports.
+            for (String pkgName : clause.paths) {
+                if (!dupeSet.contains(pkgName)) {
+                    // Verify that java.* packages are not imported.
+                    if (pkgName.startsWith("java.")) {
+                        throw new BundleException("Importing java.* packages not allowed: " + pkgName);
+                    }
+                    // The character "." has no meaning in the OSGi spec except
+                    // when placed on the bundle class path. Some people, however,
+                    // mistakenly think it means the default package when imported
+                    // or exported. This is not correct. It is invalid.
+                    else if (pkgName.equals(".")) {
+                        throw new BundleException("Importing '.' is invalid.");
+                    }
+                    // Make sure a package name was specified.
+                    else if (pkgName.length() == 0) {
+                        throw new BundleException(
+                                "Imported package names cannot be zero length.");
+                    }
+                    dupeSet.add(pkgName);
+                } else {
+                    throw new BundleException("Duplicate import: " + pkgName);
+                }
+            }
+        }
+
+        return clauses;
+    }
+
+    private static List<Capability> convertExportService(List<ParsedHeaderClause> clauses, Resource resource) {
+        List<Capability> capList = new ArrayList<Capability>();
+        for (ParsedHeaderClause clause : clauses) {
+            for (String path : clause.paths) {
+                Map<String, String> dirs = new LinkedHashMap<String, String>();
+                dirs.put(ServiceNamespace.CAPABILITY_EFFECTIVE_DIRECTIVE, ServiceNamespace.EFFECTIVE_ACTIVE);
+                Map<String, Object> attrs = new LinkedHashMap<String, Object>();
+                attrs.put(Constants.OBJECTCLASS, path);
+                attrs.putAll(clause.attrs);
+                capList.add(new CapabilityImpl(
+                                resource,
+                                ServiceNamespace.SERVICE_NAMESPACE,
+                                dirs,
+                                attrs));
+            }
+        }
+        return capList;
+    }
+
+    private static List<Requirement> convertImportService(List<ParsedHeaderClause> clauses, Resource resource) throws BundleException {
+        try {
+            List<Requirement> reqList = new ArrayList<Requirement>();
+            for (ParsedHeaderClause clause : clauses) {
+                for (String path : clause.paths) {
+                    String multiple = clause.dirs.get("multiple");
+                    String avail    = clause.dirs.get("availability");
+                    String filter   = (String) clause.attrs.get("filter");
+                    Map<String, String> dirs = new LinkedHashMap<String, String>();
+                    dirs.put(ServiceNamespace.REQUIREMENT_EFFECTIVE_DIRECTIVE, ServiceNamespace.EFFECTIVE_ACTIVE);
+                    if ("optional".equals(avail)) {
+                        dirs.put(ServiceNamespace.REQUIREMENT_RESOLUTION_DIRECTIVE, ServiceNamespace.RESOLUTION_OPTIONAL);
+                    }
+                    if ("true".equals(multiple)) {
+                        dirs.put(ServiceNamespace.REQUIREMENT_CARDINALITY_DIRECTIVE, ServiceNamespace.CARDINALITY_MULTIPLE);
+                    }
+                    if (filter == null) {
+                        filter = "(" + Constants.OBJECTCLASS + "=" + path + ")";
+                    } else if (!filter.startsWith("(") && !filter.endsWith(")")) {
+                        filter = "(&(" + Constants.OBJECTCLASS + "=" + path + ")(" + filter + "))";
+                    } else {
+                        filter = "(&(" + Constants.OBJECTCLASS + "=" + path + ")" + filter + ")";
+                    }
+                    dirs.put(ServiceNamespace.REQUIREMENT_FILTER_DIRECTIVE, filter);
+                    reqList.add(new RequirementImpl(
+                                    resource,
+                                    ServiceNamespace.SERVICE_NAMESPACE,
+                                    dirs,
+                                    Collections.<String, Object>emptyMap(),
+                                    SimpleFilter.parse(filter)));
+                }
+            }
+            return reqList;
+        } catch (Exception ex) {
+            throw new BundleException("Error creating requirement: " + ex, ex);
+        }
+    }
+
+    private static List<Requirement> convertImports(List<ParsedHeaderClause> clauses, Resource resource) {
+        // Now convert generic header clauses into requirements.
+        List<Requirement> reqList = new ArrayList<Requirement>();
+        for (ParsedHeaderClause clause : clauses) {
+            for (String path : clause.paths) {
+                // Prepend the package name to the array of attributes.
+                Map<String, Object> attrs = clause.attrs;
+                // Note that we use a linked hash map here to ensure the
+                // package attribute is first, which will make indexing
+                // more efficient.
+    // TODO: OSGi R4.3 - This is ordering is kind of hacky.
+                // Prepend the package name to the array of attributes.
+                Map<String, Object> newAttrs = new LinkedHashMap<String, Object>(attrs.size() + 1);
+                // We want this first from an indexing perspective.
+                newAttrs.put(BundleRevision.PACKAGE_NAMESPACE, path);
+                newAttrs.putAll(attrs);
+                // But we need to put it again to make sure it wasn't overwritten.
+                newAttrs.put(BundleRevision.PACKAGE_NAMESPACE, path);
+
+                // Create filter now so we can inject filter directive.
+                SimpleFilter sf = SimpleFilter.convert(newAttrs);
+
+                // Inject filter directive.
+    // TODO: OSGi R4.3 - Can we insert this on demand somehow?
+                Map<String, String> dirs = clause.dirs;
+                Map<String, String> newDirs = new HashMap<String, String>(dirs.size() + 1);
+                newDirs.putAll(dirs);
+                newDirs.put(Constants.FILTER_DIRECTIVE, sf.toString());
+
+                // Create package requirement and add to requirement list.
+                reqList.add(
+                        new RequirementImpl(
+                                resource,
+                                BundleRevision.PACKAGE_NAMESPACE,
+                                newDirs,
+                                Collections.<String, Object>emptyMap(),
+                                sf));
+            }
+        }
+
+        return reqList;
+    }
+
+    @SuppressWarnings( "deprecation" )
+    private static List<ParsedHeaderClause> normalizeDynamicImportClauses(
+            List<ParsedHeaderClause> clauses)
+            throws BundleException {
+        // Verify that the values are equals if the package specifies
+        // both version and specification-version attributes.
+        for (ParsedHeaderClause clause : clauses) {
+            // Add the resolution directive to indicate that these are
+            // dynamic imports.
+            clause.dirs.put(Constants.RESOLUTION_DIRECTIVE, RESOLUTION_DYNAMIC);
+
+            // Check for "version" and "specification-version" attributes
+            // and verify they are the same if both are specified.
+            Object v = clause.attrs.get(Constants.VERSION_ATTRIBUTE);
+            Object sv = clause.attrs.get(Constants.PACKAGE_SPECIFICATION_VERSION);
+            if ((v != null) && (sv != null)) {
+                // Verify they are equal.
+                if (!((String) v).trim().equals(((String) sv).trim())) {
+                    throw new IllegalArgumentException(
+                            "Both version and specification-version are specified, but they are not equal.");
+                }
+            }
+
+            // Ensure that only the "version" attribute is used and convert
+            // it to the VersionRange type.
+            if ((v != null) || (sv != null)) {
+                clause.attrs.remove(Constants.PACKAGE_SPECIFICATION_VERSION);
+                v = (v == null) ? sv : v;
+                clause.attrs.put(Constants.VERSION_ATTRIBUTE, VersionRange.parseVersionRange(v.toString()));
+            }
+
+            // If bundle version is specified, then convert its type to VersionRange.
+            v = clause.attrs.get(Constants.BUNDLE_VERSION_ATTRIBUTE);
+            if (v != null) {
+                clause.attrs.put(Constants.BUNDLE_VERSION_ATTRIBUTE, VersionRange.parseVersionRange(v.toString()));
+            }
+
+            // Dynamic imports can have duplicates, so verify that java.*
+            // packages are not imported.
+            for (String pkgName : clause.paths) {
+                if (pkgName.startsWith("java.")) {
+                    throw new BundleException("Dynamically importing java.* packages not allowed: " + pkgName);
+                } else if (!pkgName.equals("*") && pkgName.endsWith("*") && !pkgName.endsWith(".*")) {
+                    throw new BundleException("Partial package name wild carding is not allowed: " + pkgName);
+                }
+            }
+        }
+
+        return clauses;
+    }
+
+    private static List<ParsedHeaderClause> normalizeRequireCapabilityClauses(
+            List<ParsedHeaderClause> clauses)
+            throws BundleException {
+
+        return clauses;
+    }
+
+    private static List<ParsedHeaderClause> normalizeProvideCapabilityClauses(
+            List<ParsedHeaderClause> clauses)
+            throws BundleException
+    {
+
+        // Convert attributes into specified types.
+        for (ParsedHeaderClause clause : clauses)
+        {
+            for (Map.Entry<String, String> entry : clause.types.entrySet())
+            {
+                String type = entry.getValue();
+                if (!type.equals("String"))
+                {
+                    if (type.equals("Double"))
+                    {
+                        clause.attrs.put(
+                                entry.getKey(),
+                                new Double(clause.attrs.get(entry.getKey()).toString().trim()));
+                    }
+                    else if (type.equals("Version"))
+                    {
+                        clause.attrs.put(
+                                entry.getKey(),
+                                new Version(clause.attrs.get(entry.getKey()).toString().trim()));
+                    }
+                    else if (type.equals("Long"))
+                    {
+                        clause.attrs.put(
+                                entry.getKey(),
+                                new Long(clause.attrs.get(entry.getKey()).toString().trim()));
+                    }
+                    else if (type.startsWith("List"))
+                    {
+                        int startIdx = type.indexOf('<');
+                        int endIdx = type.indexOf('>');
+                        if (((startIdx > 0) && (endIdx <= startIdx))
+                                || ((startIdx < 0) && (endIdx > 0)))
+                        {
+                            throw new BundleException(
+                                    "Invalid Provide-Capability attribute list type for '"
+                                            + entry.getKey()
+                                            + "' : "
+                                            + type);
+                        }
+
+                        String listType = "String";
+                        if (endIdx > startIdx)
+                        {
+                            listType = type.substring(startIdx + 1, endIdx).trim();
+                        }
+
+                        List<String> tokens = parseDelimitedString(
+                                clause.attrs.get(entry.getKey()).toString(), ",", false);
+                        List<Object> values = new ArrayList<Object>(tokens.size());
+                        for (String token : tokens)
+                        {
+                            if (listType.equals("String"))
+                            {
+                                values.add(token);
+                            }
+                            else if (listType.equals("Double"))
+                            {
+                                values.add(new Double(token.trim()));
+                            }
+                            else if (listType.equals("Version"))
+                            {
+                                values.add(new Version(token.trim()));
+                            }
+                            else if (listType.equals("Long"))
+                            {
+                                values.add(new Long(token.trim()));
+                            }
+                            else
+                            {
+                                throw new BundleException(
+                                        "Unknown Provide-Capability attribute list type for '"
+                                                + entry.getKey()
+                                                + "' : "
+                                                + type);
+                            }
+                        }
+                        clause.attrs.put(
+                                entry.getKey(),
+                                values);
+                    }
+                    else
+                    {
+                        throw new BundleException(
+                                "Unknown Provide-Capability attribute type for '"
+                                        + entry.getKey()
+                                        + "' : "
+                                        + type);
+                    }
+                }
+            }
+        }
+
+        return clauses;
+    }
+
+    private static List<Requirement> convertRequireCapabilities(
+            List<ParsedHeaderClause> clauses, Resource resource)
+            throws BundleException {
+        // Now convert generic header clauses into requirements.
+        List<Requirement> reqList = new ArrayList<Requirement>();
+        for (ParsedHeaderClause clause : clauses) {
+            try {
+                String filterStr = clause.dirs.get(Constants.FILTER_DIRECTIVE);
+                SimpleFilter sf = (filterStr != null)
+                        ? SimpleFilter.parse(filterStr)
+                        : new SimpleFilter(null, null, SimpleFilter.MATCH_ALL);
+                for (String path : clause.paths) {
+                    // Create requirement and add to requirement list.
+                    reqList.add(new RequirementImpl(
+                                    resource, path, clause.dirs, clause.attrs, sf));
+                }
+            } catch (Exception ex) {
+                throw new BundleException("Error creating requirement: " + ex, ex);
+            }
+        }
+
+        return reqList;
+    }
+
+    private static List<Capability> convertProvideCapabilities(
+            List<ParsedHeaderClause> clauses, Resource resource)
+            throws BundleException {
+        List<Capability> capList = new ArrayList<Capability>();
+        for (ParsedHeaderClause clause : clauses) {
+            for (String path : clause.paths) {
+                if (path.startsWith("osgi.wiring.")) {
+//                    throw new BundleException("Manifest cannot use Provide-Capability for '" + path + "' namespace.");
+                }
+
+                // Create package capability and add to capability list.
+                capList.add(new CapabilityImpl(resource, path, clause.dirs, clause.attrs));
+            }
+        }
+
+        return capList;
+    }
+
+    @SuppressWarnings( "deprecation" )
+    private static List<ParsedHeaderClause> normalizeExportClauses(
+            List<ParsedHeaderClause> clauses,
+            String bsn, Version bv)
+            throws BundleException {
+        // Verify that "java.*" packages are not exported.
+        for (ParsedHeaderClause clause : clauses) {
+            // Verify that the named package has not already been declared.
+            for (String pkgName : clause.paths) {
+                // Verify that java.* packages are not exported.
+                if (pkgName.startsWith("java.")) {
+                    throw new BundleException("Exporting java.* packages not allowed: " + pkgName);
+                }
+                // The character "." has no meaning in the OSGi spec except
+                // when placed on the bundle class path. Some people, however,
+                // mistakenly think it means the default package when imported
+                // or exported. This is not correct. It is invalid.
+                else if (pkgName.equals(".")) {
+                    throw new BundleException("Exporing '.' is invalid.");
+                }
+                // Make sure a package name was specified.
+                else if (pkgName.length() == 0) {
+                    throw new BundleException("Exported package names cannot be zero length.");
+                }
+            }
+
+            // Check for "version" and "specification-version" attributes
+            // and verify they are the same if both are specified.
+            Object v = clause.attrs.get(Constants.VERSION_ATTRIBUTE);
+            Object sv = clause.attrs.get(Constants.PACKAGE_SPECIFICATION_VERSION);
+            if ((v != null) && (sv != null)) {
+                // Verify they are equal.
+                if (!((String) v).trim().equals(((String) sv).trim())) {
+                    throw new IllegalArgumentException("Both version and specification-version are specified, but they are not equal.");
+                }
+            }
+
+            // Always add the default version if not specified.
+            if ((v == null) && (sv == null)) {
+                v = Version.emptyVersion;
+            }
+
+            // Ensure that only the "version" attribute is used and convert
+            // it to the appropriate type.
+            if ((v != null) || (sv != null)) {
+                // Convert version attribute to type Version.
+                clause.attrs.remove(Constants.PACKAGE_SPECIFICATION_VERSION);
+                v = (v == null) ? sv : v;
+                clause.attrs.put(Constants.VERSION_ATTRIBUTE, Version.parseVersion(v.toString()));
+            }
+
+            // Find symbolic name and version attribute, if present.
+            if (clause.attrs.containsKey(Constants.BUNDLE_VERSION_ATTRIBUTE)
+                    || clause.attrs.containsKey(Constants.BUNDLE_SYMBOLICNAME_ATTRIBUTE)) {
+                throw new BundleException("Exports must not specify bundle symbolic name or bundle version.");
+            }
+
+            // Now that we know that there are no bundle symbolic name and version
+            // attributes, add them since the spec says they are there implicitly.
+            clause.attrs.put(Constants.BUNDLE_SYMBOLICNAME_ATTRIBUTE, bsn);
+            clause.attrs.put(Constants.BUNDLE_VERSION_ATTRIBUTE, bv);
+        }
+
+        return clauses;
+    }
+
+    private static List<Capability> convertExports(
+            List<ParsedHeaderClause> clauses, Resource resource) {
+        List<Capability> capList = new ArrayList<Capability>();
+        for (ParsedHeaderClause clause : clauses) {
+            for (String pkgName : clause.paths) {
+                // Prepend the package name to the array of attributes.
+                Map<String, Object> attrs = clause.attrs;
+                Map<String, Object> newAttrs = new HashMap<String, Object>(attrs.size() + 1);
+                newAttrs.putAll(attrs);
+                newAttrs.put(BundleRevision.PACKAGE_NAMESPACE, pkgName);
+
+                // Create package capability and add to capability list.
+                capList.add(new CapabilityImpl(resource, BundleRevision.PACKAGE_NAMESPACE, clause.dirs, newAttrs));
+            }
+        }
+
+        return capList;
+    }
+
+    private static String getManifestVersion(Map<String, String> headerMap) {
+        String manifestVersion = headerMap.get(Constants.BUNDLE_MANIFESTVERSION);
+        return (manifestVersion == null) ? "1" : manifestVersion.trim();
+    }
+
+    private static List<ParsedHeaderClause> calculateImplicitImports(
+            List<BundleCapability> exports, List<ParsedHeaderClause> imports)
+            throws BundleException {
+        List<ParsedHeaderClause> clauseList = new ArrayList<ParsedHeaderClause>();
+
+        // Since all R3 exports imply an import, add a corresponding
+        // requirement for each existing export capability. Do not
+        // duplicate imports.
+        Map<String, String> map = new HashMap<String, String>();
+        // Add existing imports.
+        for (ParsedHeaderClause anImport : imports) {
+            for (int pathIdx = 0; pathIdx < anImport.paths.size(); pathIdx++) {
+                map.put(anImport.paths.get(pathIdx), anImport.paths.get(pathIdx));
+            }
+        }
+        // Add import requirement for each export capability.
+        for (BundleCapability export : exports) {
+            if (map.get(export.getAttributes().get(BundleRevision.PACKAGE_NAMESPACE).toString()) == null) {
+                // Convert Version to VersionRange.
+                Object version = export.getAttributes().get(Constants.VERSION_ATTRIBUTE);
+                ParsedHeaderClause clause = new ParsedHeaderClause();
+                if (version != null) {
+                    clause.attrs.put(Constants.VERSION_ATTRIBUTE, VersionRange.parseVersionRange(version.toString()));
+                }
+                clause.paths.add((String) export.getAttributes().get(BundleRevision.PACKAGE_NAMESPACE));
+                clauseList.add(clause);
+            }
+        }
+
+        return clauseList;
+    }
+
+    private static List<Capability> calculateImplicitUses(
+            List<Capability> exports, List<ParsedHeaderClause> imports)
+            throws BundleException {
+        // Add a "uses" directive onto each export of R3 bundles
+        // that references every other import (which will include
+        // exports, since export implies import); this is
+        // necessary since R3 bundles assumed a single class space,
+        // but R4 allows for multiple class spaces.
+        String usesValue = "";
+        for (ParsedHeaderClause anImport : imports) {
+            for (int pathIdx = 0; pathIdx < anImport.paths.size(); pathIdx++) {
+                usesValue = usesValue
+                        + ((usesValue.length() > 0) ? "," : "")
+                        + anImport.paths.get(pathIdx);
+            }
+        }
+        for (int i = 0; i < exports.size(); i++) {
+            Map<String, String> dirs = new HashMap<String, String>(1);
+            dirs.put(Constants.USES_DIRECTIVE, usesValue);
+            exports.set(i, new CapabilityImpl(
+                    exports.get(i).getResource(),
+                    BundleRevision.PACKAGE_NAMESPACE,
+                    dirs,
+                    exports.get(i).getAttributes()));
+        }
+
+        return exports;
+    }
+
+    private static ParsedHeaderClause parseBundleSymbolicName(Map<String, String> headerMap)
+            throws BundleException {
+        List<ParsedHeaderClause> clauses = parseStandardHeader(headerMap.get(Constants.BUNDLE_SYMBOLICNAME));
+        if (clauses.size() > 0) {
+            if (clauses.size() > 1 || clauses.get(0).paths.size() > 1) {
+                throw new BundleException("Cannot have multiple symbolic names: " + headerMap.get(Constants.BUNDLE_SYMBOLICNAME));
+            }
+
+            // Get bundle version.
+            Version bundleVersion = Version.emptyVersion;
+            if (headerMap.get(Constants.BUNDLE_VERSION) != null) {
+                bundleVersion = Version.parseVersion(headerMap.get(Constants.BUNDLE_VERSION));
+            }
+
+            // Create a require capability and return it.
+            ParsedHeaderClause clause = clauses.get(0);
+            String symName = clause.paths.get(0);
+            clause.attrs.put(BundleRevision.BUNDLE_NAMESPACE, symName);
+            clause.attrs.put(Constants.BUNDLE_VERSION_ATTRIBUTE, bundleVersion);
+            return clause;
+        }
+
+        return null;
+    }
+
+    private static List<RequirementImpl> parseFragmentHost(
+            Resource resource, Map<String, String> headerMap)
+            throws BundleException {
+        List<RequirementImpl> reqs = new ArrayList<RequirementImpl>();
+
+        List<ParsedHeaderClause> clauses = parseStandardHeader(headerMap.get(Constants.FRAGMENT_HOST));
+        if (clauses.size() > 0) {
+            // Make sure that only one fragment host symbolic name is specified.
+            if (clauses.size() > 1 || clauses.get(0).paths.size() > 1) {
+                throw new BundleException("Fragments cannot have multiple hosts: " + headerMap.get(Constants.FRAGMENT_HOST));
+            }
+
+            // If the bundle-version attribute is specified, then convert
+            // it to the proper type.
+            Object value = clauses.get(0).attrs.get(Constants.BUNDLE_VERSION_ATTRIBUTE);
+            value = (value == null) ? "0.0.0" : value;
+            clauses.get(0).attrs.put(Constants.BUNDLE_VERSION_ATTRIBUTE, VersionRange.parseVersionRange(value.toString()));
+
+            // Note that we use a linked hash map here to ensure the
+            // host symbolic name is first, which will make indexing
+            // more efficient.
+    // TODO: OSGi R4.3 - This is ordering is kind of hacky.
+            // Prepend the host symbolic name to the map of attributes.
+            Map<String, Object> attrs = clauses.get(0).attrs;
+            Map<String, Object> newAttrs = new LinkedHashMap<String, Object>(attrs.size() + 1);
+            // We want this first from an indexing perspective.
+            newAttrs.put(BundleRevision.HOST_NAMESPACE, clauses.get(0).paths.get(0));
+            newAttrs.putAll(attrs);
+            // But we need to put it again to make sure it wasn't overwritten.
+            newAttrs.put(BundleRevision.HOST_NAMESPACE, clauses.get(0).paths.get(0));
+
+            // Create filter now so we can inject filter directive.
+            SimpleFilter sf = SimpleFilter.convert(newAttrs);
+
+            // Inject filter directive.
+    // TODO: OSGi R4.3 - Can we insert this on demand somehow?
+            Map<String, String> dirs = clauses.get(0).dirs;
+            Map<String, String> newDirs = new HashMap<String, String>(dirs.size() + 1);
+            newDirs.putAll(dirs);
+            newDirs.put(Constants.FILTER_DIRECTIVE, sf.toString());
+
+            reqs.add(new RequirementImpl(
+                    resource, BundleRevision.HOST_NAMESPACE,
+                    newDirs,
+                    newAttrs));
+        }
+
+        return reqs;
+    }
+
+    private static List<ParsedHeaderClause> normalizeRequireClauses(List<ParsedHeaderClause> clauses) {
+        // Convert bundle version attribute to VersionRange type.
+        for (ParsedHeaderClause clause : clauses) {
+            Object value = clause.attrs.get(Constants.BUNDLE_VERSION_ATTRIBUTE);
+            if (value != null) {
+                clause.attrs.put(Constants.BUNDLE_VERSION_ATTRIBUTE, VersionRange.parseVersionRange(value.toString()));
+            }
+        }
+
+        return clauses;
+    }
+
+    private static List<Requirement> convertRequires(List<ParsedHeaderClause> clauses, Resource resource) {
+        List<Requirement> reqList = new ArrayList<Requirement>();
+        for (ParsedHeaderClause clause : clauses) {
+            for (String path : clause.paths) {
+                // Prepend the bundle symbolic name to the array of attributes.
+                Map<String, Object> attrs = clause.attrs;
+                // Note that we use a linked hash map here to ensure the
+                // symbolic name attribute is first, which will make indexing
+                // more efficient.
+    // TODO: OSGi R4.3 - This is ordering is kind of hacky.
+                // Prepend the symbolic name to the array of attributes.
+                Map<String, Object> newAttrs = new LinkedHashMap<String, Object>(attrs.size() + 1);
+                // We want this first from an indexing perspective.
+                newAttrs.put(BundleRevision.BUNDLE_NAMESPACE, path);
+                newAttrs.putAll(attrs);
+                // But we need to put it again to make sure it wasn't overwritten.
+                newAttrs.put(BundleRevision.BUNDLE_NAMESPACE, path);
+
+                // Create filter now so we can inject filter directive.
+                SimpleFilter sf = SimpleFilter.convert(newAttrs);
+
+                // Inject filter directive.
+    // TODO: OSGi R4.3 - Can we insert this on demand somehow?
+                Map<String, String> dirs = clause.dirs;
+                Map<String, String> newDirs = new HashMap<String, String>(dirs.size() + 1);
+                newDirs.putAll(dirs);
+                newDirs.put(Constants.FILTER_DIRECTIVE, sf.toString());
+
+                // Create package requirement and add to requirement list.
+                reqList.add(new RequirementImpl(resource, BundleRevision.BUNDLE_NAMESPACE, newDirs, newAttrs));
+            }
+        }
+
+        return reqList;
+    }
+
+    private static final char EOF = (char) -1;
+
+    private static char charAt(int pos, String headers, int length)
+    {
+        if (pos >= length)
+        {
+            return EOF;
+        }
+        return headers.charAt(pos);
+    }
+
+    private static final int CLAUSE_START = 0;
+    private static final int PARAMETER_START = 1;
+    private static final int KEY = 2;
+    private static final int DIRECTIVE_OR_TYPEDATTRIBUTE = 4;
+    private static final int ARGUMENT = 8;
+    private static final int VALUE = 16;
+
+    @SuppressWarnings({ "unchecked", "rawtypes" })
+    private static List<ParsedHeaderClause> parseStandardHeader(String header)
+    {
+        List<ParsedHeaderClause> clauses = new ArrayList<ParsedHeaderClause>();
+        if (header == null)
+        {
+            return clauses;
+        }
+        ParsedHeaderClause clause = null;
+        String key = null;
+        Map targetMap = null;
+        int state = CLAUSE_START;
+        int currentPosition = 0;
+        int startPosition = 0;
+        int length = header.length();
+        boolean quoted = false;
+        boolean escaped = false;
+
+        char currentChar = EOF;
+        do
+        {
+            currentChar = charAt(currentPosition, header, length);
+            switch (state)
+            {
+                case CLAUSE_START:
+                    clause = new ParsedHeaderClause();
+                    clauses.add(clause);
+                    state = PARAMETER_START;
+                case PARAMETER_START:
+                    startPosition = currentPosition;
+                    state = KEY;
+                case KEY:
+                    switch (currentChar)
+                    {
+                        case ':':
+                        case '=':
+                            key = header.substring(startPosition, currentPosition).trim();
+                            startPosition = currentPosition + 1;
+                            targetMap = clause.attrs;
+                            state = currentChar == ':' ? DIRECTIVE_OR_TYPEDATTRIBUTE : ARGUMENT;
+                            break;
+                        case EOF:
+                        case ',':
+                        case ';':
+                            clause.paths.add(header.substring(startPosition, currentPosition).trim());
+                            state = currentChar == ',' ? CLAUSE_START : PARAMETER_START;
+                            break;
+                        default:
+                            break;
+                    }
+                    currentPosition++;
+                    break;
+                case DIRECTIVE_OR_TYPEDATTRIBUTE:
+                    switch(currentChar)
+                    {
+                        case '=':
+                            if (startPosition != currentPosition)
+                            {
+                                clause.types.put(key, header.substring(startPosition, currentPosition).trim());
+                            }
+                            else
+                            {
+                                targetMap = clause.dirs;
+                            }
+                            state = ARGUMENT;
+                            startPosition = currentPosition + 1;
+                            break;
+                        default:
+                            break;
+                    }
+                    currentPosition++;
+                    break;
+                case ARGUMENT:
+                    if (currentChar == '\"')
+                    {
+                        quoted = true;
+                        currentPosition++;
+                    }
+                    else
+                    {
+                        quoted = false;
+                    }
+                    if (!Character.isWhitespace(currentChar)) {
+                        state = VALUE;
+                    }
+                    else {
+                        currentPosition++;
+                    }
+                    break;
+                case VALUE:
+                    if (escaped)
+                    {
+                        escaped = false;
+                    }
+                    else
+                    {
+                        if (currentChar == '\\' )
+                        {
+                            escaped = true;
+                        }
+                        else if (quoted && currentChar == '\"')
+                        {
+                            quoted = false;
+                        }
+                        else if (!quoted)
+                        {
+                            String value = null;
+                            switch(currentChar)
+                            {
+                                case EOF:
+                                case ';':
+                                case ',':
+                                    value = header.substring(startPosition, currentPosition).trim();
+                                    if (value.startsWith("\"") && value.endsWith("\""))
+                                    {
+                                        value = value.substring(1, value.length() - 1);
+                                    }
+                                    if (targetMap.put(key, value) != null)
+                                    {
+                                        throw new IllegalArgumentException(
+                                                "Duplicate '" + key + "' in: " + header);
+                                    }
+                                    state = currentChar == ';' ? PARAMETER_START : CLAUSE_START;
+                                    break;
+                                default:
+                                    break;
+                            }
+                        }
+                    }
+                    currentPosition++;
+                    break;
+                default:
+                    break;
+            }
+        } while ( currentChar != EOF);
+
+        if (state > PARAMETER_START)
+        {
+            throw new IllegalArgumentException("Unable to parse header: " + header);
+        }
+        return clauses;
+    }
+
+    public static List<String> parseDelimitedString(String value, String delim)
+    {
+        return parseDelimitedString(value, delim, true);
+    }
+
+    /**
+     * Parses delimited string and returns an array containing the tokens. This
+     * parser obeys quotes, so the delimiter character will be ignored if it is
+     * inside of a quote. This method assumes that the quote character is not
+     * included in the set of delimiter characters.
+     * @param value the delimited string to parse.
+     * @param delim the characters delimiting the tokens.
+     * @return a list of string or an empty list if there are none.
+     **/
+    public static List<String> parseDelimitedString(String value, String delim, boolean trim)
+    {
+        if (value == null)
+        {
+            value = "";
+        }
+
+        List<String> list = new ArrayList();
+
+        int CHAR = 1;
+        int DELIMITER = 2;
+        int STARTQUOTE = 4;
+        int ENDQUOTE = 8;
+
+        StringBuffer sb = new StringBuffer();
+
+        int expecting = (CHAR | DELIMITER | STARTQUOTE);
+
+        boolean isEscaped = false;
+        for (int i = 0; i < value.length(); i++)
+        {
+            char c = value.charAt(i);
+
+            boolean isDelimiter = (delim.indexOf(c) >= 0);
+
+            if (!isEscaped && (c == '\\'))
+            {
+                isEscaped = true;
+                continue;
+            }
+
+            if (isEscaped)
+            {
+                sb.append(c);
+            }
+            else if (isDelimiter && ((expecting & DELIMITER) > 0))
+            {
+                if (trim)
+                {
+                    list.add(sb.toString().trim());
+                }
+                else
+                {
+                    list.add(sb.toString());
+                }
+                sb.delete(0, sb.length());
+                expecting = (CHAR | DELIMITER | STARTQUOTE);
+            }
+            else if ((c == '"') && ((expecting & STARTQUOTE) > 0))
+            {
+                sb.append(c);
+                expecting = CHAR | ENDQUOTE;
+            }
+            else if ((c == '"') && ((expecting & ENDQUOTE) > 0))
+            {
+                sb.append(c);
+                expecting = (CHAR | STARTQUOTE | DELIMITER);
+            }
+            else if ((expecting & CHAR) > 0)
+            {
+                sb.append(c);
+            }
+            else
+            {
+                throw new IllegalArgumentException("Invalid delimited string: " + value);
+            }
+
+            isEscaped = false;
+        }
+
+        if (sb.length() > 0)
+        {
+            if (trim)
+            {
+                list.add(sb.toString().trim());
+            }
+            else
+            {
+                list.add(sb.toString());
+            }
+        }
+
+        return list;
+    }
+
+
+    static class ParsedHeaderClause {
+        public final List<String> paths = new ArrayList<String>();
+        public final Map<String, String> dirs = new LinkedHashMap<String, String>();
+        public final Map<String, Object> attrs = new LinkedHashMap<String, Object>();
+        public final Map<String, String> types = new LinkedHashMap<String, String>();
+    }
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/src/main/java/org/apache/karaf/features/internal/resolver/ResourceImpl.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/resolver/ResourceImpl.java b/features/src/main/java/org/apache/karaf/features/internal/resolver/ResourceImpl.java
new file mode 100644
index 0000000..18e0dc3
--- /dev/null
+++ b/features/src/main/java/org/apache/karaf/features/internal/resolver/ResourceImpl.java
@@ -0,0 +1,110 @@
+/*
+ * 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.karaf.features.internal.resolver;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.osgi.framework.Version;
+import org.osgi.framework.namespace.IdentityNamespace;
+import org.osgi.resource.Capability;
+import org.osgi.resource.Requirement;
+import org.osgi.resource.Resource;
+
+/**
+ */
+public class ResourceImpl implements Resource {
+
+    private final List<Capability> m_caps;
+    private final List<Requirement> m_reqs;
+
+    public ResourceImpl(String name, Version version) {
+        this(name, IdentityNamespace.TYPE_BUNDLE, version);
+    }
+
+    public ResourceImpl(String name, String type, Version version)
+    {
+        m_caps = new ArrayList<Capability>();
+        m_caps.add(0, new IdentityCapability(this, name, type, version));
+        m_reqs = new ArrayList<Requirement>();
+    }
+
+    public void addCapability(Capability capability) {
+        assert capability.getResource() == this;
+        m_caps.add(capability);
+    }
+
+    public void addCapabilities(Iterable<? extends Capability> capabilities) {
+        for (Capability cap : capabilities) {
+            addCapability(cap);
+        }
+    }
+
+    public void addRequirement(Requirement requirement) {
+        assert requirement.getResource() == this;
+        m_reqs.add(requirement);
+    }
+
+    public void addRequirements(Iterable<? extends Requirement> requirements) {
+        for (Requirement req : requirements) {
+            addRequirement(req);
+        }
+    }
+
+    public List<Capability> getCapabilities(String namespace)
+    {
+        List<Capability> result = m_caps;
+        if (namespace != null)
+        {
+            result = new ArrayList<Capability>();
+            for (Capability cap : m_caps)
+            {
+                if (cap.getNamespace().equals(namespace))
+                {
+                    result.add(cap);
+                }
+            }
+        }
+        return result;
+    }
+
+    public List<Requirement> getRequirements(String namespace)
+    {
+        List<Requirement> result = m_reqs;
+        if (namespace != null)
+        {
+            result = new ArrayList<Requirement>();
+            for (Requirement req : m_reqs)
+            {
+                if (req.getNamespace().equals(namespace))
+                {
+                    result.add(req);
+                }
+            }
+        }
+        return result;
+    }
+
+    @Override
+    public String toString()
+    {
+        Capability cap = getCapabilities(IdentityNamespace.IDENTITY_NAMESPACE).get(0);
+        return cap.getAttributes().get(IdentityNamespace.IDENTITY_NAMESPACE) + "/"
+                + cap.getAttributes().get(IdentityNamespace.CAPABILITY_VERSION_ATTRIBUTE);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/src/main/java/org/apache/karaf/features/internal/resolver/ServiceNamespace.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/resolver/ServiceNamespace.java b/features/src/main/java/org/apache/karaf/features/internal/resolver/ServiceNamespace.java
new file mode 100644
index 0000000..4fe3bf8
--- /dev/null
+++ b/features/src/main/java/org/apache/karaf/features/internal/resolver/ServiceNamespace.java
@@ -0,0 +1,30 @@
+/*
+ * 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.karaf.features.internal.resolver;
+
+import org.osgi.resource.Namespace;
+
+/**
+ */
+public final class ServiceNamespace extends Namespace {
+
+    public static final String SERVICE_NAMESPACE = "service-reference";
+
+    private ServiceNamespace() {
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/src/main/java/org/apache/karaf/features/internal/resolver/SimpleFilter.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/resolver/SimpleFilter.java b/features/src/main/java/org/apache/karaf/features/internal/resolver/SimpleFilter.java
new file mode 100644
index 0000000..ae10441
--- /dev/null
+++ b/features/src/main/java/org/apache/karaf/features/internal/resolver/SimpleFilter.java
@@ -0,0 +1,649 @@
+/*
+ * 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.karaf.features.internal.resolver;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import org.apache.felix.utils.version.VersionRange;
+
+public class SimpleFilter
+{
+    public static final int MATCH_ALL = 0;
+    public static final int AND = 1;
+    public static final int OR = 2;
+    public static final int NOT = 3;
+    public static final int EQ = 4;
+    public static final int LTE = 5;
+    public static final int GTE = 6;
+    public static final int SUBSTRING = 7;
+    public static final int PRESENT = 8;
+    public static final int APPROX = 9;
+
+    private final String m_name;
+    private final Object m_value;
+    private final int m_op;
+
+    public SimpleFilter(String attr, Object value, int op)
+    {
+        m_name = attr;
+        m_value = value;
+        m_op = op;
+    }
+
+    public String getName()
+    {
+        return m_name;
+    }
+
+    public Object getValue()
+    {
+        return m_value;
+    }
+
+    public int getOperation()
+    {
+        return m_op;
+    }
+
+    public String toString()
+    {
+        String s = null;
+        switch (m_op)
+        {
+            case AND:
+                s = "(&" + toString((List) m_value) + ")";
+                break;
+            case OR:
+                s = "(|" + toString((List) m_value) + ")";
+                break;
+            case NOT:
+                s = "(!" + toString((List) m_value) + ")";
+                break;
+            case EQ:
+                s = "(" + m_name + "=" + toEncodedString(m_value) + ")";
+                break;
+            case LTE:
+                s = "(" + m_name + "<=" + toEncodedString(m_value) + ")";
+                break;
+            case GTE:
+                s = "(" + m_name + ">=" + toEncodedString(m_value) + ")";
+                break;
+            case SUBSTRING:
+                s = "(" + m_name + "=" + unparseSubstring((List<String>) m_value) + ")";
+                break;
+            case PRESENT:
+                s = "(" + m_name + "=*)";
+                break;
+            case APPROX:
+                s = "(" + m_name + "~=" + toEncodedString(m_value) + ")";
+                break;
+            case MATCH_ALL:
+                s = "(*)";
+                break;
+        }
+        return s;
+    }
+
+    private static String toString(List list)
+    {
+        StringBuffer sb = new StringBuffer();
+        for (int i = 0; i < list.size(); i++)
+        {
+            sb.append(list.get(i).toString());
+        }
+        return sb.toString();
+    }
+
+    private static String toDecodedString(String s, int startIdx, int endIdx)
+    {
+        StringBuffer sb = new StringBuffer(endIdx - startIdx);
+        boolean escaped = false;
+        for (int i = 0; i < (endIdx - startIdx); i++)
+        {
+            char c = s.charAt(startIdx + i);
+            if (!escaped && (c == '\\'))
+            {
+                escaped = true;
+            }
+            else
+            {
+                escaped = false;
+                sb.append(c);
+            }
+        }
+
+        return sb.toString();
+    }
+
+    private static String toEncodedString(Object o)
+    {
+        if (o instanceof String)
+        {
+            String s = (String) o;
+            StringBuffer sb = new StringBuffer();
+            for (int i = 0; i < s.length(); i++)
+            {
+                char c = s.charAt(i);
+                if ((c == '\\') || (c == '(') || (c == ')') || (c == '*'))
+                {
+                    sb.append('\\');
+                }
+                sb.append(c);
+            }
+
+            o = sb.toString();
+        }
+
+        return o.toString();
+    }
+
+    public static SimpleFilter parse(String filter)
+    {
+        int idx = skipWhitespace(filter, 0);
+
+        if ((filter == null) || (filter.length() == 0) || (idx >= filter.length()))
+        {
+            throw new IllegalArgumentException("Null or empty filter.");
+        }
+        else if (filter.charAt(idx) != '(')
+        {
+            throw new IllegalArgumentException("Missing opening parenthesis: " + filter);
+        }
+
+        SimpleFilter sf = null;
+        List stack = new ArrayList();
+        boolean isEscaped = false;
+        while (idx < filter.length())
+        {
+            if (sf != null)
+            {
+                throw new IllegalArgumentException(
+                        "Only one top-level operation allowed: " + filter);
+            }
+
+            if (!isEscaped && (filter.charAt(idx) == '('))
+            {
+                // Skip paren and following whitespace.
+                idx = skipWhitespace(filter, idx + 1);
+
+                if (filter.charAt(idx) == '&')
+                {
+                    int peek = skipWhitespace(filter, idx + 1);
+                    if (filter.charAt(peek) == '(')
+                    {
+                        idx = peek - 1;
+                        stack.add(0, new SimpleFilter(null, new ArrayList(), SimpleFilter.AND));
+                    }
+                    else
+                    {
+                        stack.add(0, new Integer(idx));
+                    }
+                }
+                else if (filter.charAt(idx) == '|')
+                {
+                    int peek = skipWhitespace(filter, idx + 1);
+                    if (filter.charAt(peek) == '(')
+                    {
+                        idx = peek - 1;
+                        stack.add(0, new SimpleFilter(null, new ArrayList(), SimpleFilter.OR));
+                    }
+                    else
+                    {
+                        stack.add(0, new Integer(idx));
+                    }
+                }
+                else if (filter.charAt(idx) == '!')
+                {
+                    int peek = skipWhitespace(filter, idx + 1);
+                    if (filter.charAt(peek) == '(')
+                    {
+                        idx = peek - 1;
+                        stack.add(0, new SimpleFilter(null, new ArrayList(), SimpleFilter.NOT));
+                    }
+                    else
+                    {
+                        stack.add(0, new Integer(idx));
+                    }
+                }
+                else
+                {
+                    stack.add(0, new Integer(idx));
+                }
+            }
+            else if (!isEscaped && (filter.charAt(idx) == ')'))
+            {
+                Object top = stack.remove(0);
+                if (top instanceof SimpleFilter)
+                {
+                    if (!stack.isEmpty() && (stack.get(0) instanceof SimpleFilter))
+                    {
+                        ((List) ((SimpleFilter) stack.get(0)).m_value).add(top);
+                    }
+                    else
+                    {
+                        sf = (SimpleFilter) top;
+                    }
+                }
+                else if (!stack.isEmpty() && (stack.get(0) instanceof SimpleFilter))
+                {
+                    ((List) ((SimpleFilter) stack.get(0)).m_value).add(
+                            SimpleFilter.subfilter(filter, ((Integer) top).intValue(), idx));
+                }
+                else
+                {
+                    sf = SimpleFilter.subfilter(filter, ((Integer) top).intValue(), idx);
+                }
+            }
+            else if (!isEscaped && (filter.charAt(idx) == '\\'))
+            {
+                isEscaped = true;
+            }
+            else
+            {
+                isEscaped = false;
+            }
+
+            idx = skipWhitespace(filter, idx + 1);
+        }
+
+        if (sf == null)
+        {
+            throw new IllegalArgumentException("Missing closing parenthesis: " + filter);
+        }
+
+        return sf;
+    }
+
+    private static SimpleFilter subfilter(String filter, int startIdx, int endIdx)
+    {
+        final String opChars = "=<>~";
+
+        // Determine the ending index of the attribute name.
+        int attrEndIdx = startIdx;
+        for (int i = 0; i < (endIdx - startIdx); i++)
+        {
+            char c = filter.charAt(startIdx + i);
+            if (opChars.indexOf(c) >= 0)
+            {
+                break;
+            }
+            else if (!Character.isWhitespace(c))
+            {
+                attrEndIdx = startIdx + i + 1;
+            }
+        }
+        if (attrEndIdx == startIdx)
+        {
+            throw new IllegalArgumentException(
+                    "Missing attribute name: " + filter.substring(startIdx, endIdx));
+        }
+        String attr = filter.substring(startIdx, attrEndIdx);
+
+        // Skip the attribute name and any following whitespace.
+        startIdx = skipWhitespace(filter, attrEndIdx);
+
+        // Determine the operator type.
+        int op = -1;
+        switch (filter.charAt(startIdx))
+        {
+            case '=':
+                op = EQ;
+                startIdx++;
+                break;
+            case '<':
+                if (filter.charAt(startIdx + 1) != '=')
+                {
+                    throw new IllegalArgumentException(
+                            "Unknown operator: " + filter.substring(startIdx, endIdx));
+                }
+                op = LTE;
+                startIdx += 2;
+                break;
+            case '>':
+                if (filter.charAt(startIdx + 1) != '=')
+                {
+                    throw new IllegalArgumentException(
+                            "Unknown operator: " + filter.substring(startIdx, endIdx));
+                }
+                op = GTE;
+                startIdx += 2;
+                break;
+            case '~':
+                if (filter.charAt(startIdx + 1) != '=')
+                {
+                    throw new IllegalArgumentException(
+                            "Unknown operator: " + filter.substring(startIdx, endIdx));
+                }
+                op = APPROX;
+                startIdx += 2;
+                break;
+            default:
+                throw new IllegalArgumentException(
+                        "Unknown operator: " + filter.substring(startIdx, endIdx));
+        }
+
+        // Parse value.
+        Object value = toDecodedString(filter, startIdx, endIdx);
+
+        // Check if the equality comparison is actually a substring
+        // or present operation.
+        if (op == EQ)
+        {
+            String valueStr = filter.substring(startIdx, endIdx);
+            List<String> values = parseSubstring(valueStr);
+            if ((values.size() == 2)
+                    && (values.get(0).length() == 0)
+                    && (values.get(1).length() == 0))
+            {
+                op = PRESENT;
+            }
+            else if (values.size() > 1)
+            {
+                op = SUBSTRING;
+                value = values;
+            }
+        }
+
+        return new SimpleFilter(attr, value, op);
+    }
+
+    public static List<String> parseSubstring(String value)
+    {
+        List<String> pieces = new ArrayList();
+        StringBuffer ss = new StringBuffer();
+        // int kind = SIMPLE; // assume until proven otherwise
+        boolean wasStar = false; // indicates last piece was a star
+        boolean leftstar = false; // track if the initial piece is a star
+        boolean rightstar = false; // track if the final piece is a star
+
+        int idx = 0;
+
+        // We assume (sub)strings can contain leading and trailing blanks
+        boolean escaped = false;
+        loop:   for (;;)
+        {
+            if (idx >= value.length())
+            {
+                if (wasStar)
+                {
+                    // insert last piece as "" to handle trailing star
+                    rightstar = true;
+                }
+                else
+                {
+                    pieces.add(ss.toString());
+                    // accumulate the last piece
+                    // note that in the case of
+                    // (cn=); this might be
+                    // the string "" (!=null)
+                }
+                ss.setLength(0);
+                break loop;
+            }
+
+            // Read the next character and account for escapes.
+            char c = value.charAt(idx++);
+            if (!escaped && (c == '*'))
+            {
+                // If we have successive '*' characters, then we can
+                // effectively collapse them by ignoring succeeding ones.
+                if (!wasStar)
+                {
+                    if (ss.length() > 0)
+                    {
+                        pieces.add(ss.toString()); // accumulate the pieces
+                        // between '*' occurrences
+                    }
+                    ss.setLength(0);
+                    // if this is a leading star, then track it
+                    if (pieces.isEmpty())
+                    {
+                        leftstar = true;
+                    }
+                    wasStar = true;
+                }
+            }
+            else if (!escaped && (c == '\\'))
+            {
+                escaped = true;
+            }
+            else
+            {
+                escaped = false;
+                wasStar = false;
+                ss.append(c);
+            }
+        }
+        if (leftstar || rightstar || pieces.size() > 1)
+        {
+            // insert leading and/or trailing "" to anchor ends
+            if (rightstar)
+            {
+                pieces.add("");
+            }
+            if (leftstar)
+            {
+                pieces.add(0, "");
+            }
+        }
+        return pieces;
+    }
+
+    public static String unparseSubstring(List<String> pieces)
+    {
+        StringBuffer sb = new StringBuffer();
+        for (int i = 0; i < pieces.size(); i++)
+        {
+            if (i > 0)
+            {
+                sb.append("*");
+            }
+            sb.append(toEncodedString(pieces.get(i)));
+        }
+        return sb.toString();
+    }
+
+    public static boolean compareSubstring(List<String> pieces, String s)
+    {
+        // Walk the pieces to match the string
+        // There are implicit stars between each piece,
+        // and the first and last pieces might be "" to anchor the match.
+        // assert (pieces.length > 1)
+        // minimal case is <string>*<string>
+
+        boolean result = true;
+        int len = pieces.size();
+
+        // Special case, if there is only one piece, then
+        // we must perform an equality test.
+        if (len == 1)
+        {
+            return s.equals(pieces.get(0));
+        }
+
+        // Otherwise, check whether the pieces match
+        // the specified string.
+
+        int index = 0;
+
+        loop:   for (int i = 0; i < len; i++)
+        {
+            String piece = pieces.get(i);
+
+            // If this is the first piece, then make sure the
+            // string starts with it.
+            if (i == 0)
+            {
+                if (!s.startsWith(piece))
+                {
+                    result = false;
+                    break loop;
+                }
+            }
+
+            // If this is the last piece, then make sure the
+            // string ends with it.
+            if (i == (len - 1))
+            {
+                if (s.endsWith(piece) && (s.length() >= (index + piece.length())))
+                {
+                    result = true;
+                }
+                else
+                {
+                    result = false;
+                }
+                break loop;
+            }
+
+            // If this is neither the first or last piece, then
+            // make sure the string contains it.
+            if ((i > 0) && (i < (len - 1)))
+            {
+                index = s.indexOf(piece, index);
+                if (index < 0)
+                {
+                    result = false;
+                    break loop;
+                }
+            }
+
+            // Move string index beyond the matching piece.
+            index += piece.length();
+        }
+
+        return result;
+    }
+
+    private static int skipWhitespace(String s, int startIdx)
+    {
+        int len = s.length();
+        while ((startIdx < len) && Character.isWhitespace(s.charAt(startIdx)))
+        {
+            startIdx++;
+        }
+        return startIdx;
+    }
+
+    /**
+     * Converts a attribute map to a filter. The filter is created by iterating
+     * over the map's entry set. If ordering of attributes is important (e.g.,
+     * for hitting attribute indices), then the map's entry set should iterate
+     * in the desired order. Equality testing is assumed for all attribute types
+     * other than version ranges, which are handled appropriated. If the attribute
+     * map is empty, then a filter that matches anything is returned.
+     * @param attrs Map of attributes to convert to a filter.
+     * @return A filter corresponding to the attributes.
+     */
+    public static SimpleFilter convert(Map<String, Object> attrs)
+    {
+        // Rather than building a filter string to be parsed into a SimpleFilter,
+        // we will just create the parsed SimpleFilter directly.
+
+        List<SimpleFilter> filters = new ArrayList<SimpleFilter>();
+
+        for (Entry<String, Object> entry : attrs.entrySet())
+        {
+            if (entry.getValue() instanceof VersionRange)
+            {
+                VersionRange vr = (VersionRange) entry.getValue();
+                if (!vr.isOpenFloor())
+                {
+                    filters.add(
+                            new SimpleFilter(
+                                    entry.getKey(),
+                                    vr.getFloor().toString(),
+                                    SimpleFilter.GTE));
+                }
+                else
+                {
+                    SimpleFilter not =
+                            new SimpleFilter(null, new ArrayList(), SimpleFilter.NOT);
+                    ((List) not.getValue()).add(
+                            new SimpleFilter(
+                                    entry.getKey(),
+                                    vr.getFloor().toString(),
+                                    SimpleFilter.LTE));
+                    filters.add(not);
+                }
+
+                if (vr.getCeiling() != null)
+                {
+                    if (!vr.isOpenCeiling())
+                    {
+                        filters.add(
+                                new SimpleFilter(
+                                        entry.getKey(),
+                                        vr.getCeiling().toString(),
+                                        SimpleFilter.LTE));
+                    }
+                    else
+                    {
+                        SimpleFilter not =
+                                new SimpleFilter(null, new ArrayList(), SimpleFilter.NOT);
+                        ((List) not.getValue()).add(
+                                new SimpleFilter(
+                                        entry.getKey(),
+                                        vr.getCeiling().toString(),
+                                        SimpleFilter.GTE));
+                        filters.add(not);
+                    }
+                }
+            }
+            else
+            {
+                List<String> values = SimpleFilter.parseSubstring(entry.getValue().toString());
+                if (values.size() > 1)
+                {
+                    filters.add(
+                            new SimpleFilter(
+                                    entry.getKey(),
+                                    values,
+                                    SimpleFilter.SUBSTRING));
+                }
+                else
+                {
+                    filters.add(
+                            new SimpleFilter(
+                                    entry.getKey(),
+                                    values.get(0),
+                                    SimpleFilter.EQ));
+                }
+            }
+        }
+
+        SimpleFilter sf = null;
+
+        if (filters.size() == 1)
+        {
+            sf = filters.get(0);
+        }
+        else if (attrs.size() > 1)
+        {
+            sf = new SimpleFilter(null, filters, SimpleFilter.AND);
+        }
+        else if (filters.isEmpty())
+        {
+            sf = new SimpleFilter(null, null, SimpleFilter.MATCH_ALL);
+        }
+
+        return sf;
+    }
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/src/main/java/org/apache/karaf/features/internal/resolver/Slf4jResolverLog.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/resolver/Slf4jResolverLog.java b/features/src/main/java/org/apache/karaf/features/internal/resolver/Slf4jResolverLog.java
new file mode 100644
index 0000000..2f4a1f3
--- /dev/null
+++ b/features/src/main/java/org/apache/karaf/features/internal/resolver/Slf4jResolverLog.java
@@ -0,0 +1,49 @@
+/*
+ * 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.karaf.features.internal.resolver;
+
+import org.slf4j.Logger;
+
+/**
+ */
+public class Slf4jResolverLog extends org.apache.felix.resolver.Logger {
+
+    private final Logger logger;
+
+    public Slf4jResolverLog(Logger logger) {
+        super(LOG_DEBUG);
+        this.logger = logger;
+    }
+
+    @Override
+    protected void doLog(int level, String msg, Throwable throwable) {
+        switch (level) {
+            case LOG_ERROR:
+                logger.error(msg, throwable);
+                break;
+            case LOG_WARNING:
+                logger.warn(msg, throwable);
+                break;
+            case LOG_INFO:
+                logger.info(msg, throwable);
+                break;
+            case LOG_DEBUG:
+                logger.debug(msg, throwable);
+                break;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/src/main/java/org/apache/karaf/features/internal/resolver/UriNamespace.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/resolver/UriNamespace.java b/features/src/main/java/org/apache/karaf/features/internal/resolver/UriNamespace.java
new file mode 100644
index 0000000..b5158bf
--- /dev/null
+++ b/features/src/main/java/org/apache/karaf/features/internal/resolver/UriNamespace.java
@@ -0,0 +1,47 @@
+/*
+ * 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.karaf.features.internal.resolver;
+
+import java.util.List;
+
+import org.osgi.resource.Capability;
+import org.osgi.resource.Namespace;
+import org.osgi.resource.Resource;
+
+/**
+ */
+public final class UriNamespace extends Namespace {
+
+    public static final String URI_NAMESPACE = "karaf.uri";
+
+    public static String getUri(Resource resource)
+    {
+        List<Capability> caps = resource.getCapabilities(null);
+        for (Capability cap : caps)
+        {
+            if (cap.getNamespace().equals(UriNamespace.URI_NAMESPACE))
+            {
+                return cap.getAttributes().get(UriNamespace.URI_NAMESPACE).toString();
+            }
+        }
+        return null;
+    }
+
+
+    private UriNamespace() {
+    }
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/src/main/java/org/apache/karaf/features/internal/service/Artifact.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/service/Artifact.java b/features/src/main/java/org/apache/karaf/features/internal/service/Artifact.java
new file mode 100644
index 0000000..44e9a7c
--- /dev/null
+++ b/features/src/main/java/org/apache/karaf/features/internal/service/Artifact.java
@@ -0,0 +1,56 @@
+/*
+ * 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.karaf.features.internal.service;
+
+import java.net.URI;
+
+/**
+ * Simple abstraction of a maven artifact to avoid external deps
+ */
+public class Artifact {
+    String groupId;
+    String artifactId;
+    String version;
+    String extension;
+    String classifier;
+    
+    public Artifact(String coords) {
+        String[] coordsAr = coords.split(":");
+        if (coordsAr.length != 5) {
+            throw new IllegalArgumentException("Maven URL " + coords + " is malformed or not complete");
+        }
+        this.groupId = coordsAr[0];
+        this.artifactId = coordsAr[1];
+        this.version = coordsAr[4];
+        this.extension = coordsAr[2];
+        this.classifier = coordsAr[3];
+    }
+    
+    public Artifact(String coords, String version) {
+        this(coords);
+        this.version = version;
+    }
+    
+    public URI getMavenUrl(String version) {
+        String uriSt = "mvn:" + this.groupId + "/" + this.artifactId + "/" + version + "/" + this.extension + "/" + this.classifier;
+        try {
+            return new URI(uriSt);
+        } catch (Exception e) {
+            return null;
+        }
+    }
+}


[36/59] [abbrv] [KARAF-2852] Merge log/core and log/command

Posted by gn...@apache.org.
http://git-wip-us.apache.org/repos/asf/karaf/blob/7f1463c5/log/core/src/main/java/org/apache/karaf/log/core/internal/layout/ISO8601DateFormat.java
----------------------------------------------------------------------
diff --git a/log/core/src/main/java/org/apache/karaf/log/core/internal/layout/ISO8601DateFormat.java b/log/core/src/main/java/org/apache/karaf/log/core/internal/layout/ISO8601DateFormat.java
deleted file mode 100644
index 80155a0..0000000
--- a/log/core/src/main/java/org/apache/karaf/log/core/internal/layout/ISO8601DateFormat.java
+++ /dev/null
@@ -1,152 +0,0 @@
-/*
- * 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.karaf.log.core.internal.layout;
-
-import java.text.FieldPosition;
-import java.text.ParsePosition;
-import java.util.Calendar;
-import java.util.Date;
-import java.util.TimeZone;
-
-/**
- * Copied from log4j
- */
-// Contributors: Arndt Schoenewald <ar...@ibm23093i821.mc.schoenewald.de>
-/**
-   Formats a {@link Date} in the format "yyyy-MM-dd HH:mm:ss,SSS" for example
-   "1999-11-27 15:49:37,459".
-
-   <p>Refer to the <a
-   href=http://www.cl.cam.ac.uk/~mgk25/iso-time.html>summary of the
-   International Standard Date and Time Notation</a> for more
-   information on this format.
-
-   @since 0.7.5
-*/
-public class ISO8601DateFormat extends AbsoluteTimeDateFormat {
-
-  public
-  ISO8601DateFormat() {
-  }
-
-  public
-  ISO8601DateFormat(TimeZone timeZone) {
-    super(timeZone);
-  }
-
-  static private long   lastTime;
-  static private char[] lastTimeString = new char[20];
-
-  /**
-     Appends a date in the format "YYYY-mm-dd HH:mm:ss,SSS"
-     to <code>sbuf</code>. For example: "1999-11-27 15:49:37,459".
-
-     @param sbuf the <code>StringBuffer</code> to write to
-  */
-  public
-  StringBuffer format(Date date, StringBuffer sbuf,
-		      FieldPosition fieldPosition) {
-
-    long now = date.getTime();
-    int millis = (int)(now % 1000);
-
-    if ((now - millis) != lastTime) {
-      // We reach this point at most once per second
-      // across all threads instead of each time format()
-      // is called. This saves considerable CPU time.
-
-      calendar.setTime(date);
-
-      int start = sbuf.length();
-
-      int year =  calendar.get(Calendar.YEAR);
-      sbuf.append(year);
-
-      String month;
-      switch(calendar.get(Calendar.MONTH)) {
-      case Calendar.JANUARY: month = "-01-"; break;
-      case Calendar.FEBRUARY: month = "-02-";  break;
-      case Calendar.MARCH: month = "-03-"; break;
-      case Calendar.APRIL: month = "-04-";  break;
-      case Calendar.MAY: month = "-05-"; break;
-      case Calendar.JUNE: month = "-06-";  break;
-      case Calendar.JULY: month = "-07-"; break;
-      case Calendar.AUGUST: month = "-08-";  break;
-      case Calendar.SEPTEMBER: month = "-09-"; break;
-      case Calendar.OCTOBER: month = "-10-"; break;
-      case Calendar.NOVEMBER: month = "-11-";  break;
-      case Calendar.DECEMBER: month = "-12-";  break;
-      default: month = "-NA-"; break;
-      }
-      sbuf.append(month);
-
-      int day = calendar.get(Calendar.DAY_OF_MONTH);
-      if(day < 10)
-	sbuf.append('0');
-      sbuf.append(day);
-
-      sbuf.append(' ');
-
-      int hour = calendar.get(Calendar.HOUR_OF_DAY);
-      if(hour < 10) {
-	sbuf.append('0');
-      }
-      sbuf.append(hour);
-      sbuf.append(':');
-
-      int mins = calendar.get(Calendar.MINUTE);
-      if(mins < 10) {
-	sbuf.append('0');
-      }
-      sbuf.append(mins);
-      sbuf.append(':');
-
-      int secs = calendar.get(Calendar.SECOND);
-      if(secs < 10) {
-	sbuf.append('0');
-      }
-      sbuf.append(secs);
-
-      sbuf.append(',');
-
-      // store the time string for next time to avoid recomputation
-      sbuf.getChars(start, sbuf.length(), lastTimeString, 0);
-      lastTime = now - millis;
-    }
-    else {
-      sbuf.append(lastTimeString);
-    }
-
-
-    if (millis < 100)
-      sbuf.append('0');
-    if (millis < 10)
-      sbuf.append('0');
-
-    sbuf.append(millis);
-    return sbuf;
-  }
-
-  /**
-    This method does not do anything but return <code>null</code>.
-   */
-  public
-  Date parse(java.lang.String s, ParsePosition pos) {
-    return null;
-  }
-}
-

http://git-wip-us.apache.org/repos/asf/karaf/blob/7f1463c5/log/core/src/main/java/org/apache/karaf/log/core/internal/layout/PatternConverter.java
----------------------------------------------------------------------
diff --git a/log/core/src/main/java/org/apache/karaf/log/core/internal/layout/PatternConverter.java b/log/core/src/main/java/org/apache/karaf/log/core/internal/layout/PatternConverter.java
deleted file mode 100644
index 0d91e8c..0000000
--- a/log/core/src/main/java/org/apache/karaf/log/core/internal/layout/PatternConverter.java
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * 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.karaf.log.core.internal.layout;
-
-import org.ops4j.pax.logging.spi.PaxLoggingEvent;
-
-/**
-   <p>PatternConverter is an abtract class that provides the
-   formatting functionality that derived classes need.
-
-   <p>Conversion specifiers in a conversion patterns are parsed to
-   individual PatternConverters. Each of which is responsible for
-   converting a logging event in a converter specific manner.
-
-   @since 0.8.2
- */
-public abstract class PatternConverter {
-  public PatternConverter next;
-  int min = -1;
-  int max = 0x7FFFFFFF;
-  boolean leftAlign = false;
-
-  protected
-  PatternConverter() {  }
-
-  protected
-  PatternConverter(FormattingInfo fi) {
-    min = fi.min;
-    max = fi.max;
-    leftAlign = fi.leftAlign;
-  }
-
-  /**
-     Derived pattern converters must override this method in order to
-     convert conversion specifiers in the correct way.
-  */
-  abstract
-  protected
-  String convert(PaxLoggingEvent event);
-
-  /**
-     A template method for formatting in a converter specific way.
-   */
-  public
-  void format(StringBuffer sbuf, PaxLoggingEvent e) {
-    String s = convert(e);
-
-    if(s == null) {
-      if(0 < min)
-	spacePad(sbuf, min);
-      return;
-    }
-
-    int len = s.length();
-
-    if(len > max)
-      sbuf.append(s.substring(len-max));
-    else if(len < min) {
-      if(leftAlign) {
-	sbuf.append(s);
-	spacePad(sbuf, min-len);
-      }
-      else {
-	spacePad(sbuf, min-len);
-	sbuf.append(s);
-      }
-    }
-    else
-      sbuf.append(s);
-  }
-
-  static String[] SPACES = {" ", "  ", "    ", "        ", //1,2,4,8 spaces
-			    "                ", // 16 spaces
-			    "                                " }; // 32 spaces
-
-  /**
-     Fast space padding method.
-  */
-  public
-  void spacePad(StringBuffer sbuf, int length) {
-    while(length >= 32) {
-      sbuf.append(SPACES[5]);
-      length -= 32;
-    }
-
-    for(int i = 4; i >= 0; i--) {
-      if((length & (1<<i)) != 0) {
-	sbuf.append(SPACES[i]);
-      }
-    }
-  }
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/7f1463c5/log/core/src/main/java/org/apache/karaf/log/core/internal/layout/PatternParser.java
----------------------------------------------------------------------
diff --git a/log/core/src/main/java/org/apache/karaf/log/core/internal/layout/PatternParser.java b/log/core/src/main/java/org/apache/karaf/log/core/internal/layout/PatternParser.java
deleted file mode 100644
index f61b278..0000000
--- a/log/core/src/main/java/org/apache/karaf/log/core/internal/layout/PatternParser.java
+++ /dev/null
@@ -1,560 +0,0 @@
-/*
- * 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.karaf.log.core.internal.layout;
-
-import java.text.DateFormat;
-import java.text.SimpleDateFormat;
-import java.util.Arrays;
-import java.util.Date;
-import java.util.Map;
-
-import org.apache.log4j.spi.LoggingEvent;
-import org.ops4j.pax.logging.spi.PaxLocationInfo;
-import org.ops4j.pax.logging.spi.PaxLoggingEvent;
-
-/**
- * Copied from log4j
- */
-/**
-   Most of the work of the {@link org.apache.log4j.PatternLayout} class
-   is delegated to the PatternParser class.
-
-   @since 0.8.2
-*/
-public class PatternParser {
-
-  private static final String LINE_SEP = System.getProperty("line.separator");
-
-  private static final char ESCAPE_CHAR = '%';
-
-  private static final int LITERAL_STATE = 0;
-  private static final int CONVERTER_STATE = 1;
-  private static final int MINUS_STATE = 2;
-  private static final int DOT_STATE = 3;
-  private static final int MIN_STATE = 4;
-  private static final int MAX_STATE = 5;
-
-  static final int FULL_LOCATION_CONVERTER = 1000;
-  static final int METHOD_LOCATION_CONVERTER = 1001;
-  static final int CLASS_LOCATION_CONVERTER = 1002;
-  static final int LINE_LOCATION_CONVERTER = 1003;
-  static final int FILE_LOCATION_CONVERTER = 1004;
-
-  static final int RELATIVE_TIME_CONVERTER = 2000;
-  static final int THREAD_CONVERTER = 2001;
-  static final int LEVEL_CONVERTER = 2002;
-  static final int NDC_CONVERTER = 2003;
-  static final int MESSAGE_CONVERTER = 2004;
-
-  int state;
-  protected StringBuffer currentLiteral = new StringBuffer(32);
-  protected int patternLength;
-  protected int i;
-  PatternConverter head;
-  PatternConverter tail;
-  protected FormattingInfo formattingInfo = new FormattingInfo();
-  protected String pattern;
-
-  public
-  PatternParser(String pattern) {
-    this.pattern = pattern;
-    patternLength =  pattern.length();
-    state = LITERAL_STATE;
-  }
-
-  private
-  void  addToList(PatternConverter pc) {
-    if(head == null) {
-      head = tail = pc;
-    } else {
-      tail.next = pc;
-      tail = pc;
-    }
-  }
-
-  protected
-  String extractOption() {
-    if((i < patternLength) && (pattern.charAt(i) == '{')) {
-      int end = pattern.indexOf('}', i);
-      if (end > i) {
-	String r = pattern.substring(i + 1, end);
-	i = end+1;
-	return r;
-      }
-    }
-    return null;
-  }
-
-
-  /**
-     The option is expected to be in decimal and positive. In case of
-     error, zero is returned.  */
-  protected
-  int extractPrecisionOption() {
-    String opt = extractOption();
-    int r = 0;
-    if(opt != null) {
-      try {
-	r = Integer.parseInt(opt);
-	if(r <= 0) {
-	    //LogLog.error("Precision option (" + opt + ") isn't a positive integer.");
-	    r = 0;
-	}
-      }
-      catch (NumberFormatException e) {
-	//LogLog.error("Category option \""+opt+"\" not a decimal integer.", e);
-      }
-    }
-    return r;
-  }
-
-  public
-  PatternConverter parse() {
-    char c;
-    i = 0;
-    while(i < patternLength) {
-      c = pattern.charAt(i++);
-      switch(state) {
-      case LITERAL_STATE:
-        // In literal state, the last char is always a literal.
-        if(i == patternLength) {
-          currentLiteral.append(c);
-          continue;
-        }
-        if(c == ESCAPE_CHAR) {
-          // peek at the next char.
-          switch(pattern.charAt(i)) {
-          case ESCAPE_CHAR:
-            currentLiteral.append(c);
-            i++; // move pointer
-            break;
-          case 'n':
-            currentLiteral.append(LINE_SEP);
-            i++; // move pointer
-            break;
-          default:
-            if(currentLiteral.length() != 0) {
-              addToList(new LiteralPatternConverter(
-                                                  currentLiteral.toString()));
-              //LogLog.debug("Parsed LITERAL converter: \""
-              //           +currentLiteral+"\".");
-            }
-            currentLiteral.setLength(0);
-            currentLiteral.append(c); // append %
-            state = CONVERTER_STATE;
-            formattingInfo.reset();
-          }
-        }
-        else {
-          currentLiteral.append(c);
-        }
-        break;
-      case CONVERTER_STATE:
-	currentLiteral.append(c);
-	switch(c) {
-	case '-':
-	  formattingInfo.leftAlign = true;
-	  break;
-	case '.':
-	  state = DOT_STATE;
-	  break;
-	default:
-	  if(c >= '0' && c <= '9') {
-	    formattingInfo.min = c - '0';
-	    state = MIN_STATE;
-	  }
-	  else
-	    finalizeConverter(c);
-	} // switch
-	break;
-      case MIN_STATE:
-	currentLiteral.append(c);
-	if(c >= '0' && c <= '9')
-	  formattingInfo.min = formattingInfo.min*10 + (c - '0');
-	else if(c == '.')
-	  state = DOT_STATE;
-	else {
-	  finalizeConverter(c);
-	}
-	break;
-      case DOT_STATE:
-	currentLiteral.append(c);
-	if(c >= '0' && c <= '9') {
-	  formattingInfo.max = c - '0';
-	   state = MAX_STATE;
-	}
-	else {
-	  //LogLog.error("Error occured in position "+i+".\n Was expecting digit, instead got char \""+c+"\".");
-	  state = LITERAL_STATE;
-	}
-	break;
-      case MAX_STATE:
-	currentLiteral.append(c);
-	if(c >= '0' && c <= '9')
-	  formattingInfo.max = formattingInfo.max*10 + (c - '0');
-	else {
-	  finalizeConverter(c);
-	  state = LITERAL_STATE;
-	}
-	break;
-      } // switch
-    } // while
-    if(currentLiteral.length() != 0) {
-      addToList(new LiteralPatternConverter(currentLiteral.toString()));
-      //LogLog.debug("Parsed LITERAL converter: \""+currentLiteral+"\".");
-    }
-    return head;
-  }
-
-  protected
-  void finalizeConverter(char c) {
-    PatternConverter pc = null;
-    switch(c) {
-    case 'c':
-      pc = new CategoryPatternConverter(formattingInfo,
-					extractPrecisionOption());
-      //LogLog.debug("CATEGORY converter.");
-      //formattingInfo.dump();
-      currentLiteral.setLength(0);
-      break;
-    case 'C':
-      pc = new ClassNamePatternConverter(formattingInfo,
-					 extractPrecisionOption());
-      //LogLog.debug("CLASS_NAME converter.");
-      //formattingInfo.dump();
-      currentLiteral.setLength(0);
-      break;
-    case 'd':
-      String dateFormatStr = AbsoluteTimeDateFormat.ISO8601_DATE_FORMAT;
-      DateFormat df;
-      String dOpt = extractOption();
-      if(dOpt != null)
-	dateFormatStr = dOpt;
-
-      if(dateFormatStr.equalsIgnoreCase(
-                                    AbsoluteTimeDateFormat.ISO8601_DATE_FORMAT))
-	df = new  ISO8601DateFormat();
-      else if(dateFormatStr.equalsIgnoreCase(
-                                   AbsoluteTimeDateFormat.ABS_TIME_DATE_FORMAT))
-	df = new AbsoluteTimeDateFormat();
-      else if(dateFormatStr.equalsIgnoreCase(
-                              AbsoluteTimeDateFormat.DATE_AND_TIME_DATE_FORMAT))
-	df = new DateTimeDateFormat();
-      else {
-	try {
-	  df = new SimpleDateFormat(dateFormatStr);
-	}
-	catch (IllegalArgumentException e) {
-	  //LogLog.error("Could not instantiate SimpleDateFormat with " + dateFormatStr, e);
-	  df = new ISO8601DateFormat();
-	}
-      }
-      pc = new DatePatternConverter(formattingInfo, df);
-      //LogLog.debug("DATE converter {"+dateFormatStr+"}.");
-      //formattingInfo.dump();
-      currentLiteral.setLength(0);
-      break;
-    case 'F':
-      pc = new LocationPatternConverter(formattingInfo,
-					FILE_LOCATION_CONVERTER);
-      //LogLog.debug("File name converter.");
-      //formattingInfo.dump();
-      currentLiteral.setLength(0);
-      break;
-    /*case 'l':
-      pc = new LocationPatternConverter(formattingInfo,
-					FULL_LOCATION_CONVERTER);
-      //LogLog.debug("Location converter.");
-      //formattingInfo.dump();
-      currentLiteral.setLength(0);
-      break;*/
-    case 'L':
-      pc = new LocationPatternConverter(formattingInfo,
-					LINE_LOCATION_CONVERTER);
-      //LogLog.debug("LINE NUMBER converter.");
-      //formattingInfo.dump();
-      currentLiteral.setLength(0);
-      break;
-    case 'm':
-      pc = new BasicPatternConverter(formattingInfo, MESSAGE_CONVERTER);
-      //LogLog.debug("MESSAGE converter.");
-      //formattingInfo.dump();
-      currentLiteral.setLength(0);
-      break;
-    case 'M':
-      pc = new LocationPatternConverter(formattingInfo,
-					METHOD_LOCATION_CONVERTER);
-      //LogLog.debug("METHOD converter.");
-      //formattingInfo.dump();
-      currentLiteral.setLength(0);
-      break;
-    case 'p':
-      pc = new BasicPatternConverter(formattingInfo, LEVEL_CONVERTER);
-      //LogLog.debug("LEVEL converter.");
-      //formattingInfo.dump();
-      currentLiteral.setLength(0);
-      break;
-    case 'r':
-      pc = new BasicPatternConverter(formattingInfo,
-					 RELATIVE_TIME_CONVERTER);
-      //LogLog.debug("RELATIVE time converter.");
-      //formattingInfo.dump();
-      currentLiteral.setLength(0);
-      break;
-    case 't':
-      pc = new BasicPatternConverter(formattingInfo, THREAD_CONVERTER);
-      //LogLog.debug("THREAD converter.");
-      //formattingInfo.dump();
-      currentLiteral.setLength(0);
-      break;
-      /*case 'u':
-      if(i < patternLength) {
-	char cNext = pattern.charAt(i);
-	if(cNext >= '0' && cNext <= '9') {
-	  pc = new UserFieldPatternConverter(formattingInfo, cNext - '0');
-	  LogLog.debug("USER converter ["+cNext+"].");
-	  formattingInfo.dump();
-	  currentLiteral.setLength(0);
-	  i++;
-	}
-	else
-	  LogLog.error("Unexpected char" +cNext+" at position "+i);
-      }
-      break;*/
-    /*case 'x':
-      pc = new BasicPatternConverter(formattingInfo, NDC_CONVERTER);
-      //LogLog.debug("NDC converter.");
-      currentLiteral.setLength(0);
-      break;*/
-    case 'X':
-      String xOpt = extractOption();
-      pc = new MDCPatternConverter(formattingInfo, xOpt);
-      currentLiteral.setLength(0);
-      break;
-    default:
-      //LogLog.error("Unexpected char [" +c+"] at position "+i+" in conversion patterrn.");
-      pc = new LiteralPatternConverter(currentLiteral.toString());
-      currentLiteral.setLength(0);
-    }
-
-    addConverter(pc);
-  }
-
-  protected
-  void addConverter(PatternConverter pc) {
-    currentLiteral.setLength(0);
-    // Add the pattern converter to the list.
-    addToList(pc);
-    // Next pattern is assumed to be a literal.
-    state = LITERAL_STATE;
-    // Reset formatting info
-    formattingInfo.reset();
-  }
-
-  // ---------------------------------------------------------------------
-  //                      PatternConverters
-  // ---------------------------------------------------------------------
-
-  private static class BasicPatternConverter extends PatternConverter {
-    int type;
-
-    BasicPatternConverter(FormattingInfo formattingInfo, int type) {
-      super(formattingInfo);
-      this.type = type;
-    }
-
-    public
-    String convert(PaxLoggingEvent event) {
-      switch(type) {
-      case RELATIVE_TIME_CONVERTER:
-	return (Long.toString(event.getTimeStamp() - LoggingEvent.getStartTime()));
-      case THREAD_CONVERTER:
-	return event.getThreadName();
-      case LEVEL_CONVERTER:
-	return event.getLevel().toString();
-    //  case NDC_CONVERTER:
-	//return event.getNDC();
-      case MESSAGE_CONVERTER: {
-	return event.getRenderedMessage();
-      }
-      default: return null;
-      }
-    }
-  }
-
-  private static class LiteralPatternConverter extends PatternConverter {
-    private String literal;
-
-    LiteralPatternConverter(String value) {
-      literal = value;
-    }
-
-    public
-    final
-    void format(StringBuffer sbuf, LoggingEvent event) {
-      sbuf.append(literal);
-    }
-
-    public
-    String convert(PaxLoggingEvent event) {
-      return literal;
-    }
-  }
-
-  private static class DatePatternConverter extends PatternConverter {
-    private DateFormat df;
-    private Date date;
-
-    DatePatternConverter(FormattingInfo formattingInfo, DateFormat df) {
-      super(formattingInfo);
-      date = new Date();
-      this.df = df;
-    }
-
-    public
-    String convert(PaxLoggingEvent event) {
-      date.setTime(event.getTimeStamp());
-      String converted = null;
-      try {
-        converted = df.format(date);
-      }
-      catch (Exception ex) {
-        //LogLog.error("Error occured while converting date.", ex);
-      }
-      return converted;
-    }
-  }
-
-  private class LocationPatternConverter extends PatternConverter {
-    int type;
-
-    LocationPatternConverter(FormattingInfo formattingInfo, int type) {
-      super(formattingInfo);
-      this.type = type;
-    }
-
-    public
-    String convert(PaxLoggingEvent event) {
-      PaxLocationInfo locationInfo = event.getLocationInformation();
-      switch(type) {
-      /*case FULL_LOCATION_CONVERTER:
-	return locationInfo.fullInfo;*/
-      case METHOD_LOCATION_CONVERTER:
-	return locationInfo.getMethodName();
-      case LINE_LOCATION_CONVERTER:
-	return locationInfo.getLineNumber();
-      case FILE_LOCATION_CONVERTER:
-	return locationInfo.getFileName();
-      default: return null;
-      }
-    }
-  }
-
-  private static abstract class NamedPatternConverter extends PatternConverter {
-    int precision;
-
-    NamedPatternConverter(FormattingInfo formattingInfo, int precision) {
-      super(formattingInfo);
-      this.precision =  precision;
-    }
-
-    abstract
-    String getFullyQualifiedName(PaxLoggingEvent event);
-
-    public
-    String convert(PaxLoggingEvent event) {
-      String n = getFullyQualifiedName(event);
-      if(precision <= 0)
-	return n;
-      else {
-	int len = n.length();
-
-	// We substract 1 from 'len' when assigning to 'end' to avoid out of
-	// bounds exception in return r.substring(end+1, len). This can happen if
-	// precision is 1 and the category name ends with a dot.
-	int end = len -1 ;
-	for(int i = precision; i > 0; i--) {
-	  end = n.lastIndexOf('.', end-1);
-	  if(end == -1)
-	    return n;
-	}
-	return n.substring(end+1, len);
-      }
-    }
-  }
-
-  private class ClassNamePatternConverter extends NamedPatternConverter {
-
-    ClassNamePatternConverter(FormattingInfo formattingInfo, int precision) {
-      super(formattingInfo, precision);
-    }
-
-    String getFullyQualifiedName(PaxLoggingEvent event) {
-      return event.getLocationInformation().getClassName();
-    }
-  }
-
-  private class CategoryPatternConverter extends NamedPatternConverter {
-
-    CategoryPatternConverter(FormattingInfo formattingInfo, int precision) {
-      super(formattingInfo, precision);
-    }
-
-    String getFullyQualifiedName(PaxLoggingEvent event) {
-      return event.getLoggerName();
-    }
-  }
-
-  private class MDCPatternConverter extends PatternConverter {
-    String key;
-
-    MDCPatternConverter(FormattingInfo formattingInfo, String key) {
-      super(formattingInfo);
-      this.key = key;
-    }
-
-    public
-    String convert(PaxLoggingEvent event) {
-        if (key == null) {
-            StringBuffer buf = new StringBuffer("{");
-            Map properties = event.getProperties();
-            if (properties.size() > 0) {
-              Object[] keys = properties.keySet().toArray();
-              Arrays.sort(keys);
-              for (int i = 0; i < keys.length; i++) {
-                  buf.append('{');
-                  buf.append(keys[i]);
-                  buf.append(',');
-                  buf.append(properties.get(keys[i]));
-                  buf.append('}');
-              }
-            }
-            buf.append('}');
-            return buf.toString();
-        } else {
-          Object val = event.getProperties().get(key);
-          if(val == null) {
-              return null;
-          } else {
-              return val.toString();
-          }
-        }
-    }
-
-  }
-}
-

http://git-wip-us.apache.org/repos/asf/karaf/blob/7f1463c5/log/core/src/main/java/org/apache/karaf/log/core/internal/osgi/Activator.java
----------------------------------------------------------------------
diff --git a/log/core/src/main/java/org/apache/karaf/log/core/internal/osgi/Activator.java b/log/core/src/main/java/org/apache/karaf/log/core/internal/osgi/Activator.java
deleted file mode 100644
index 2e8c4d8..0000000
--- a/log/core/src/main/java/org/apache/karaf/log/core/internal/osgi/Activator.java
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * 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.karaf.log.core.internal.osgi;
-
-import java.util.Hashtable;
-
-import org.apache.karaf.log.core.LogEventFormatter;
-import org.apache.karaf.log.core.LogService;
-import org.apache.karaf.log.core.internal.LogEventFormatterImpl;
-import org.apache.karaf.log.core.internal.LogMBeanImpl;
-import org.apache.karaf.log.core.internal.LogServiceImpl;
-import org.apache.karaf.log.core.internal.LruList;
-import org.apache.karaf.util.tracker.BaseActivator;
-import org.ops4j.pax.logging.spi.PaxAppender;
-import org.osgi.service.cm.ConfigurationAdmin;
-import org.osgi.service.cm.ManagedService;
-
-public class Activator extends BaseActivator implements ManagedService {
-
-    @Override
-    protected void doOpen() throws Exception {
-        manage("org.apache.karaf.log");
-        trackService(ConfigurationAdmin.class);
-    }
-
-    protected void doStart() throws Exception {
-        ConfigurationAdmin configurationAdmin = getTrackedService(ConfigurationAdmin.class);
-        if (configurationAdmin == null) {
-            return;
-        }
-
-        int size = getInt("size", 500);
-        String pattern = getString("pattern", "%d{ABSOLUTE} | %-5.5p | %-16.16t | %-32.32c{1} | %-32.32C %4L | %m%n");
-        String fatalColor = getString("fatalColor", "31");
-        String errorColor = getString("errorColor", "31");
-        String warnColor = getString("warnColor", "35");
-        String infoColor = getString("infoColor", "36");
-        String debugColor = getString("debugColor", "39");
-        String traceColor = getString("traceColor", "39");
-
-        LruList events = new LruList(size);
-        Hashtable<String, Object> props = new Hashtable<String, Object>();
-        props.put("org.ops4j.pax.logging.appender.name", "VmLogAppender");
-        register(PaxAppender.class, events, props);
-
-        LogEventFormatterImpl formatter = new LogEventFormatterImpl();
-        formatter.setPattern(pattern);
-        formatter.setFatalColor(fatalColor);
-        formatter.setErrorColor(errorColor);
-        formatter.setWarnColor(warnColor);
-        formatter.setInfoColor(infoColor);
-        formatter.setDebugColor(debugColor);
-        formatter.setTraceColor(traceColor);
-        register(LogEventFormatter.class, formatter);
-
-        LogServiceImpl logService = new LogServiceImpl(configurationAdmin, events);
-        register(LogService.class, logService);
-
-        LogMBeanImpl securityMBean = new LogMBeanImpl(logService);
-        registerMBean(securityMBean, "type=log");
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/7f1463c5/log/core/src/main/resources/OSGI-INF/bundle.info
----------------------------------------------------------------------
diff --git a/log/core/src/main/resources/OSGI-INF/bundle.info b/log/core/src/main/resources/OSGI-INF/bundle.info
deleted file mode 100644
index 2bd45bd..0000000
--- a/log/core/src/main/resources/OSGI-INF/bundle.info
+++ /dev/null
@@ -1,24 +0,0 @@
-h1. Synopsis
-
-${project.name}
-
-${project.description}
-
-Maven URL:
-[mvn:${project.groupId}/${project.artifactId}/${project.version}]
-
-h1. Description
-
-The log mbean management bundle exposes a Log MBean that can be used with any JMX client (for instance JConsole).
-
-The Log MBean allows quite the same actions that can be performed using log:* commands:
-  * display()
-  * display(logger)
-  * get()
-  * get(logger)
-  * set(level)
-  * list(level, logger)
-
-h1. See also
-
-  * Monitoring and Administration using JMX - section of the Karaf User Guide

http://git-wip-us.apache.org/repos/asf/karaf/blob/7f1463c5/log/core/src/test/java/org/apache/karaf/log/core/internal/SetLogLevelTest.java
----------------------------------------------------------------------
diff --git a/log/core/src/test/java/org/apache/karaf/log/core/internal/SetLogLevelTest.java b/log/core/src/test/java/org/apache/karaf/log/core/internal/SetLogLevelTest.java
deleted file mode 100644
index 73459d3..0000000
--- a/log/core/src/test/java/org/apache/karaf/log/core/internal/SetLogLevelTest.java
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * 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.karaf.log.core.internal;
-
-import java.util.Hashtable;
-
-import junit.framework.TestCase;
-
-import org.apache.karaf.log.core.LogMBean;
-import org.apache.karaf.log.core.LogService;
-import org.easymock.EasyMock;
-import org.osgi.service.cm.Configuration;
-import org.osgi.service.cm.ConfigurationAdmin;
-
-/**
- * Test cases for {@link SetLogLevel}
- */
-@SuppressWarnings("unchecked")
-public class SetLogLevelTest extends TestCase {
-    
-    private static final String ROOT_LOGGER = "log4j.rootLogger";
-    private static final String PACKAGE_LOGGER = "log4j.logger.org.apache.karaf.test";
-    
-    private LogService logService;
-    private LogMBean logMBean;
-    @SuppressWarnings("rawtypes")
-    private Hashtable properties;
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-
-        properties = new Hashtable<String, String>();
-        final Configuration configuration = EasyMock.createMock(Configuration.class);
-        EasyMock.expect(configuration.getProperties()).andReturn(properties);
-        configuration.update(properties);        
-        ConfigurationAdmin configAdmin = EasyMock.createMock(ConfigurationAdmin.class);
-        EasyMock.expect(configAdmin.getConfiguration(LogServiceImpl.CONFIGURATION_PID, null)).andReturn(configuration);
-        logService = new LogServiceImpl(configAdmin, new LruList(100));
-        logMBean = new LogMBeanImpl(logService);
-        EasyMock.replay(configAdmin);
-        EasyMock.replay(configuration);
-    }
-    
-    @Override
-    protected void tearDown() throws Exception {
-        super.tearDown();
-    }
-    
-    public void testInvalidLogLevel() throws Exception {
-        try {
-            logMBean.setLevel("INVALID");
-            fail("Exception expected");
-        } catch(IllegalArgumentException e) {
-            // Expected
-        }
-    }
-    
-    public void testSetLogLevel() throws Exception {
-        logMBean.setLevel("org.apache.karaf.test", "INFO");
-        assertEquals("INFO", properties.get(PACKAGE_LOGGER));
-    }
-    
-    public void testSetRootLogLevel() throws Exception {
-        logMBean.setLevel("INFO");
-        assertEquals("INFO", properties.get(ROOT_LOGGER));
-    }
-    
-    public void testSetLogLevelLowerCase() throws Exception {
-        logMBean.setLevel("org.apache.karaf.test", "info");
-        assertEquals("INFO", properties.get(PACKAGE_LOGGER));
-    }
-    
-    public void testSetRootLogLevelLowerCase() throws Exception {
-        logMBean.setLevel("info");
-        assertEquals("INFO", properties.get(ROOT_LOGGER));
-    }
-    
-    public void testChangeLogLevel() throws Exception {
-        properties.put(PACKAGE_LOGGER, "DEBUG");
-        logMBean.setLevel("org.apache.karaf.test", "INFO");
-        assertEquals("INFO", properties.get(PACKAGE_LOGGER));
-    }
-    
-    public void testChangeRootLogLevel() throws Exception {
-        properties.put(ROOT_LOGGER, "DEBUG");
-        logMBean.setLevel("INFO");
-        assertEquals("INFO", properties.get(ROOT_LOGGER));
-    }
-    
-    public void testChangeLogLevelWithAppender() throws Exception {
-        properties.put(PACKAGE_LOGGER, "DEBUG, APPENDER1");
-        logMBean.setLevel("org.apache.karaf.test", "INFO");
-        assertEquals("INFO, APPENDER1", properties.get(PACKAGE_LOGGER));
-    }
-    
-    public void testChangeRootLogLevelWithAppender() throws Exception {
-        properties.put(ROOT_LOGGER, "DEBUG, APPENDER1");
-        logMBean.setLevel("INFO");
-        assertEquals("INFO, APPENDER1", properties.get(ROOT_LOGGER));
-    }
-
-    public void testUnsetLogLevel() throws Exception {
-        properties.put(PACKAGE_LOGGER, "DEBUG");
-        logMBean.setLevel("org.apache.karaf.test", "DEFAULT");
-        assertFalse("Configuration for logger org.apache.karaf.test has been removed", properties.containsKey(PACKAGE_LOGGER));
-    }
-
-    public void testUnsetRootLogLevel() throws Exception {
-        properties.put(ROOT_LOGGER, "INFO");
-        logMBean.setLevel("org.apache.karaf.test", "DEFAULT");
-        assertEquals("Configuration for root logger should not be removed", "INFO", properties.get(ROOT_LOGGER));
-    }
-    
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/7f1463c5/log/pom.xml
----------------------------------------------------------------------
diff --git a/log/pom.xml b/log/pom.xml
index 9106544..5dec97a 100644
--- a/log/pom.xml
+++ b/log/pom.xml
@@ -29,13 +29,94 @@
     </parent>
 
     <groupId>org.apache.karaf.log</groupId>
-    <artifactId>log</artifactId>
-    <packaging>pom</packaging>
-    <name>Apache Karaf :: Log</name>
+    <artifactId>org.apache.karaf.log.core</artifactId>
+    <packaging>bundle</packaging>
+    <name>Apache Karaf :: Log :: Core</name>
+    <description>Core Seervices and JMX MBean to manipulate the Karaf log layer</description>
 
-    <modules>
-        <module>core</module>
-        <module>command</module>
-    </modules>
+    <properties>
+        <appendedResourcesDirectory>${basedir}/../../../etc/appended-resources/</appendedResourcesDirectory>
+    </properties>
 
-</project>
\ No newline at end of file
+    <dependencies>
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>org.osgi.core</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>org.osgi.compendium</artifactId>
+            <scope>provided</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.ops4j.pax.logging</groupId>
+            <artifactId>pax-logging-service</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.ops4j.pax.logging</groupId>
+            <artifactId>pax-logging-api</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.karaf</groupId>
+            <artifactId>org.apache.karaf.util</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.karaf.shell</groupId>
+            <artifactId>org.apache.karaf.shell.core</artifactId>
+            <optional>true</optional>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <resources>
+            <resource>
+                <directory>src/main/resources</directory>
+                <includes>
+                    <include>**/*</include>
+                </includes>
+            </resource>
+            <resource>
+                <directory>src/main/resources</directory>
+                <filtering>true</filtering>
+                <includes>
+                    <include>**/*.info</include>
+                </includes>
+            </resource>
+        </resources>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+                <configuration>
+                    <instructions>
+                        <Export-Package>
+                            org.apache.karaf.log.core
+                        </Export-Package>
+                        <Import-Package>
+                            *
+                        </Import-Package>
+                        <Private-Package>
+                            org.apache.karaf.log.command,
+                            org.apache.karaf.log.core.internal,
+                            org.apache.karaf.log.core.internal.layout,
+                            org.apache.karaf.log.core.internal.osgi,
+                            org.apache.karaf.util.tracker
+                        </Private-Package>
+                        <Bundle-Activator>
+                            org.apache.karaf.log.core.internal.osgi.Activator
+                        </Bundle-Activator>
+                        <Karaf-Commands>
+                            org.apache.karaf.log.command*
+                        </Karaf-Commands>
+                    </instructions>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>

http://git-wip-us.apache.org/repos/asf/karaf/blob/7f1463c5/log/src/main/java/org/apache/karaf/log/command/ClearLog.java
----------------------------------------------------------------------
diff --git a/log/src/main/java/org/apache/karaf/log/command/ClearLog.java b/log/src/main/java/org/apache/karaf/log/command/ClearLog.java
new file mode 100644
index 0000000..75a48d6
--- /dev/null
+++ b/log/src/main/java/org/apache/karaf/log/command/ClearLog.java
@@ -0,0 +1,41 @@
+/*
+ * 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.karaf.log.command;
+
+import org.apache.karaf.log.core.LogService;
+import org.apache.karaf.shell.api.action.Action;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.lifecycle.Reference;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+
+/**
+ * Clear the last log entries.
+ */
+@Command(scope = "log", name = "clear", description = "Clear log entries.")
+@Service
+public class ClearLog implements Action {
+
+    @Reference
+    LogService logService;
+
+    @Override
+    public Object execute() throws Exception {
+        logService.clearEvents();
+        return null;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/7f1463c5/log/src/main/java/org/apache/karaf/log/command/DisplayException.java
----------------------------------------------------------------------
diff --git a/log/src/main/java/org/apache/karaf/log/command/DisplayException.java b/log/src/main/java/org/apache/karaf/log/command/DisplayException.java
new file mode 100644
index 0000000..52a2661
--- /dev/null
+++ b/log/src/main/java/org/apache/karaf/log/command/DisplayException.java
@@ -0,0 +1,49 @@
+/*
+ * 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.karaf.log.command;
+
+import org.apache.karaf.log.core.LogService;
+import org.apache.karaf.shell.api.action.Action;
+import org.apache.karaf.shell.api.action.Argument;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.lifecycle.Reference;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.ops4j.pax.logging.spi.PaxLoggingEvent;
+
+@Command(scope = "log", name = "exception-display", description = "Displays the last occurred exception from the log.")
+@Service
+public class DisplayException implements Action {
+
+    @Argument(index = 0, name = "logger", description = "The name of the logger. This can be ROOT, ALL, or the name of a logger specified in the org.ops4j.pax.logger.cfg file.", required = false, multiValued = false)
+    String logger;
+
+    @Reference
+    LogService logService;
+
+    @Override
+    public Object execute() throws Exception {
+        PaxLoggingEvent throwableEvent = logService.getLastException(logger);
+        if (throwableEvent != null) {
+            for (String r : throwableEvent.getThrowableStrRep()) {
+                System.out.println(r);
+            }
+            System.out.println();
+        }
+        return null;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/7f1463c5/log/src/main/java/org/apache/karaf/log/command/DisplayLog.java
----------------------------------------------------------------------
diff --git a/log/src/main/java/org/apache/karaf/log/command/DisplayLog.java b/log/src/main/java/org/apache/karaf/log/command/DisplayLog.java
new file mode 100644
index 0000000..813eea5
--- /dev/null
+++ b/log/src/main/java/org/apache/karaf/log/command/DisplayLog.java
@@ -0,0 +1,83 @@
+/*
+ * 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.karaf.log.command;
+
+import java.io.PrintStream;
+
+import org.apache.karaf.log.core.LogEventFormatter;
+import org.apache.karaf.log.core.LogService;
+import org.apache.karaf.shell.api.action.Action;
+import org.apache.karaf.shell.api.action.Argument;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.Option;
+import org.apache.karaf.shell.api.action.lifecycle.Reference;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.ops4j.pax.logging.spi.PaxLoggingEvent;
+
+/**
+ * Displays the last log entries
+ */
+@Command(scope = "log", name = "display", description = "Displays log entries.")
+@Service
+public class DisplayLog implements Action {
+
+    @Option(name = "-n", aliases = {}, description="Number of entries to display", required = false, multiValued = false)
+    int entries;
+
+    @Option(name = "-p", aliases = {}, description="Pattern for formatting the output", required = false, multiValued = false)
+    String overridenPattern;
+
+    @Option(name = "--no-color", description="Disable syntax coloring of log events", required = false, multiValued = false)
+    boolean noColor;
+
+    @Argument(index = 0, name = "logger", description = "The name of the logger. This can be ROOT, ALL, or the name of a logger specified in the org.ops4j.pax.logger.cfg file.", required = false, multiValued = false)
+    String logger;
+
+    @Reference
+    LogService logService;
+
+    @Reference
+    LogEventFormatter formatter;
+
+    @Override
+    public Object execute() throws Exception {
+        
+        final PrintStream out = System.out;
+
+        Iterable<PaxLoggingEvent> le = logService.getEvents(entries == 0 ? Integer.MAX_VALUE : entries);
+        for (PaxLoggingEvent event : le) {
+            printEvent(out, event);
+        }
+        out.println();
+        return null;
+    }
+        
+    protected boolean checkIfFromRequestedLog(PaxLoggingEvent event) {
+    	return (event.getLoggerName().lastIndexOf(logger)>=0) ? true : false;
+    }
+
+    protected void printEvent(final PrintStream out, PaxLoggingEvent event) {
+        if ((logger != null) && 
+            (event != null)&&
+            (checkIfFromRequestedLog(event))) {
+                out.append(formatter.format(event, overridenPattern, noColor));
+            }
+            else if ((event != null)&&(logger == null)){
+                out.append(formatter.format(event, overridenPattern, noColor));
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/7f1463c5/log/src/main/java/org/apache/karaf/log/command/GetLogLevel.java
----------------------------------------------------------------------
diff --git a/log/src/main/java/org/apache/karaf/log/command/GetLogLevel.java b/log/src/main/java/org/apache/karaf/log/command/GetLogLevel.java
new file mode 100644
index 0000000..83e5003
--- /dev/null
+++ b/log/src/main/java/org/apache/karaf/log/command/GetLogLevel.java
@@ -0,0 +1,63 @@
+/*
+ * 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.karaf.log.command;
+
+import java.util.Map;
+
+import org.apache.karaf.log.core.LogService;
+import org.apache.karaf.shell.api.action.Action;
+import org.apache.karaf.shell.api.action.Argument;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.Option;
+import org.apache.karaf.shell.api.action.lifecycle.Reference;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.apache.karaf.shell.support.table.ShellTable;
+
+/**
+ * Get the log level
+ */
+@Command(scope = "log", name = "get", description = "Shows the currently set log level.")
+@Service
+public class GetLogLevel implements Action {
+
+    @Argument(index = 0, name = "logger", description = "The name of the logger, ALL or ROOT (default)", required = false, multiValued = false)
+    String logger;
+
+    @Option(name = "--no-format", description = "Disable table rendered output", required = false, multiValued = false)
+    boolean noFormat;
+
+    @Reference
+    LogService logService;
+
+    @Override
+    public Object execute() throws Exception {
+        Map<String, String> loggers = logService.getLevel(logger);
+
+        ShellTable table = new ShellTable();
+        table.column("Logger");
+        table.column("Level");
+
+        for (String logger : loggers.keySet()) {
+            table.addRow().addContent(logger, loggers.get(logger));
+        }
+
+        table.print(System.out, !noFormat);
+
+        return null;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/7f1463c5/log/src/main/java/org/apache/karaf/log/command/LogEntry.java
----------------------------------------------------------------------
diff --git a/log/src/main/java/org/apache/karaf/log/command/LogEntry.java b/log/src/main/java/org/apache/karaf/log/command/LogEntry.java
new file mode 100644
index 0000000..d7c17a9
--- /dev/null
+++ b/log/src/main/java/org/apache/karaf/log/command/LogEntry.java
@@ -0,0 +1,69 @@
+/*
+ * 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.karaf.log.command;
+
+import org.apache.karaf.shell.api.action.Action;
+import org.apache.karaf.shell.api.action.Argument;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.Completion;
+import org.apache.karaf.shell.api.action.Option;
+import org.apache.karaf.shell.api.action.lifecycle.Reference;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.apache.karaf.shell.support.completers.StringsCompleter;
+import org.osgi.service.log.LogService;
+
+import java.util.HashMap;
+import java.util.Map;
+
+@Command(scope = "log", name = "log", description = "Log a message.")
+@Service
+public class LogEntry implements Action {
+
+    @Argument(index = 0, name = "message", description = "The message to log", required = true, multiValued = false)
+    private String message;
+
+    @Option(name = "--level", aliases = {"-l"}, description = "The level the message will be logged at", required = false, multiValued = false)
+    @Completion(value = StringsCompleter.class, values = { "DEBUG", "INFO", "WARNING", "ERROR" })
+    private String level = "INFO";
+
+    @Reference
+    LogService logService;
+
+    private final Map<String,Integer> mappings = new HashMap<String,Integer>();
+
+    public LogEntry() {
+        mappings.put("ERROR", 1);
+        mappings.put("WARNING", 2);
+        mappings.put("INFO", 3);
+        mappings.put("DEBUG", 4);
+    }
+
+    @Override
+    public Object execute() throws Exception {
+        logService.log(toLevel(level.toUpperCase()), message);
+        return null;
+    }
+
+    private int toLevel(String logLevel) {
+        Integer level =  mappings.get(logLevel);
+        if(level == null) {
+            level = 3;
+        }
+        return level;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/7f1463c5/log/src/main/java/org/apache/karaf/log/command/LogTail.java
----------------------------------------------------------------------
diff --git a/log/src/main/java/org/apache/karaf/log/command/LogTail.java b/log/src/main/java/org/apache/karaf/log/command/LogTail.java
new file mode 100644
index 0000000..bf2801e
--- /dev/null
+++ b/log/src/main/java/org/apache/karaf/log/command/LogTail.java
@@ -0,0 +1,129 @@
+/*
+ * 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.karaf.log.command;
+
+import java.io.IOException;
+import java.io.PrintStream;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.LinkedBlockingQueue;
+
+import org.apache.karaf.log.core.LogService;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.lifecycle.Reference;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.apache.karaf.shell.api.console.Session;
+import org.ops4j.pax.logging.spi.PaxAppender;
+import org.ops4j.pax.logging.spi.PaxLoggingEvent;
+
+@Command(scope = "log", name = "tail", description = "Continuously display log entries. Use ctrl-c to quit this command")
+@Service
+public class LogTail extends DisplayLog {
+
+    @Reference
+    Session session;
+
+    @Reference
+    LogService logService;
+
+    private ExecutorService executorService = Executors.newSingleThreadExecutor();
+
+    @Override
+    public Object execute() throws Exception {
+        PrintEventThread printThread = new PrintEventThread();
+        executorService.execute(printThread);
+        new Thread(new ReadKeyBoardThread(this, Thread.currentThread())).start();
+        while (!Thread.currentThread().isInterrupted()) {
+            try {
+                Thread.sleep(200);
+            } catch (java.lang.InterruptedException e) {
+                break;
+            }
+        }
+        printThread.abort();
+        executorService.shutdownNow();  
+        return null;      
+    }
+   
+    class ReadKeyBoardThread implements Runnable {
+        private LogTail logTail;
+        private Thread sessionThread;
+        public ReadKeyBoardThread(LogTail logtail, Thread thread) {
+            this.logTail = logtail;
+            this.sessionThread = thread;
+        }
+        public void run() {
+            for (;;) {
+                try {
+                    int c = this.logTail.session.getKeyboard().read();
+                    if (c < 0) {
+                        this.sessionThread.interrupt();
+                        break;
+                    }
+                } catch (IOException e) {
+                    break;
+                }
+                
+            }
+        }
+    } 
+    
+    class PrintEventThread implements Runnable {
+
+        PrintStream out = System.out;
+        boolean doDisplay = true;
+
+        public void run() {
+            Iterable<PaxLoggingEvent> le = logService.getEvents(entries == 0 ? Integer.MAX_VALUE : entries);
+            for (PaxLoggingEvent event : le) {
+                if (event != null) {
+                    printEvent(out, event);
+                }
+            }
+            // Tail
+            final BlockingQueue<PaxLoggingEvent> queue = new LinkedBlockingQueue<PaxLoggingEvent>();
+            PaxAppender appender = new PaxAppender() {
+                public void doAppend(PaxLoggingEvent event) {
+                        queue.add(event);
+                }
+            };
+            try {
+                logService.addAppender(appender);
+                
+                while (doDisplay) {
+                    PaxLoggingEvent event = queue.take();
+                    if (event != null) {
+                        printEvent(out, event);
+                    }
+                }
+            } catch (InterruptedException e) {
+                // Ignore
+            } finally {
+                logService.removeAppender(appender);
+            }
+            out.println();
+            
+        }
+
+        public void abort() {
+            doDisplay = false;
+        }
+
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/7f1463c5/log/src/main/java/org/apache/karaf/log/command/SetLogLevel.java
----------------------------------------------------------------------
diff --git a/log/src/main/java/org/apache/karaf/log/command/SetLogLevel.java b/log/src/main/java/org/apache/karaf/log/command/SetLogLevel.java
new file mode 100644
index 0000000..b1145b4
--- /dev/null
+++ b/log/src/main/java/org/apache/karaf/log/command/SetLogLevel.java
@@ -0,0 +1,52 @@
+/*
+ * 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.karaf.log.command;
+
+
+import org.apache.karaf.log.core.LogService;
+import org.apache.karaf.shell.api.action.Action;
+import org.apache.karaf.shell.api.action.Argument;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.Completion;
+import org.apache.karaf.shell.api.action.lifecycle.Reference;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.apache.karaf.shell.support.completers.StringsCompleter;
+
+/**
+ * Set the log level for a given logger
+ */
+@Command(scope = "log", name = "set", description = "Sets the log level.")
+@Service
+public class SetLogLevel implements Action {
+    
+    @Argument(index = 0, name = "level", description = "The log level to set (TRACE, DEBUG, INFO, WARN, ERROR) or DEFAULT to unset", required = true, multiValued = false)
+    @Completion(value = StringsCompleter.class, values = { "TRACE", "DEBUG", "INFO", "WARN", "ERROR", "DEFAULT" })
+    String level;
+
+    @Argument(index = 1, name = "logger", description = "Logger name or ROOT (default)", required = false, multiValued = false)
+    String logger;
+
+    @Reference
+    LogService logService;
+
+    @Override
+    public Object execute() throws Exception {
+        logService.setLevel(logger, level);
+        return null;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/7f1463c5/log/src/main/java/org/apache/karaf/log/core/Level.java
----------------------------------------------------------------------
diff --git a/log/src/main/java/org/apache/karaf/log/core/Level.java b/log/src/main/java/org/apache/karaf/log/core/Level.java
new file mode 100644
index 0000000..a83396f
--- /dev/null
+++ b/log/src/main/java/org/apache/karaf/log/core/Level.java
@@ -0,0 +1,54 @@
+/*
+ * 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.karaf.log.core;
+
+/**
+ * Enumeration of available log levels for the log:set command and
+ * the command completer
+ */
+public enum Level {
+
+    TRACE,
+    DEBUG,
+    INFO,
+    WARN,
+    ERROR,
+    DEFAULT;
+    
+    /**
+     * Convert the list of values into a String array
+     * 
+     * @return all the values as a String array
+     */
+    public static String[] strings() {
+        String[] values = new String[values().length];
+        for (int i = 0 ; i < values.length ; i++) {
+            values[i] = values()[i].name();
+        }
+        return values;
+    }
+    
+    /**
+     * Check if the string value represents the default level
+     * 
+     * @param level the level value
+     * @return <code>true</code> if the value represents the {@link #DEFAULT} level
+     */
+    public static boolean isDefault(String level) {
+        return valueOf(level).equals(DEFAULT);
+    }
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/7f1463c5/log/src/main/java/org/apache/karaf/log/core/LogEventFormatter.java
----------------------------------------------------------------------
diff --git a/log/src/main/java/org/apache/karaf/log/core/LogEventFormatter.java b/log/src/main/java/org/apache/karaf/log/core/LogEventFormatter.java
new file mode 100644
index 0000000..71fe275
--- /dev/null
+++ b/log/src/main/java/org/apache/karaf/log/core/LogEventFormatter.java
@@ -0,0 +1,25 @@
+/*
+ * 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.karaf.log.core;
+
+import org.ops4j.pax.logging.spi.PaxLoggingEvent;
+
+public interface LogEventFormatter {
+
+    public abstract String format(PaxLoggingEvent event, String overridenPattern, boolean noColor);
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/7f1463c5/log/src/main/java/org/apache/karaf/log/core/LogMBean.java
----------------------------------------------------------------------
diff --git a/log/src/main/java/org/apache/karaf/log/core/LogMBean.java b/log/src/main/java/org/apache/karaf/log/core/LogMBean.java
new file mode 100644
index 0000000..ad5006f
--- /dev/null
+++ b/log/src/main/java/org/apache/karaf/log/core/LogMBean.java
@@ -0,0 +1,32 @@
+/*
+ * 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.karaf.log.core;
+
+import java.util.Map;
+
+/**
+ * Log MBean.
+ */
+public interface LogMBean {
+
+    String getLevel();
+    Map<String, String> getLevel(String logger);
+
+    void setLevel(String level);
+    void setLevel(String logger, String level);
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/7f1463c5/log/src/main/java/org/apache/karaf/log/core/LogService.java
----------------------------------------------------------------------
diff --git a/log/src/main/java/org/apache/karaf/log/core/LogService.java b/log/src/main/java/org/apache/karaf/log/core/LogService.java
new file mode 100644
index 0000000..ae9f678
--- /dev/null
+++ b/log/src/main/java/org/apache/karaf/log/core/LogService.java
@@ -0,0 +1,38 @@
+/*
+ * 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.karaf.log.core;
+
+import org.ops4j.pax.logging.spi.PaxAppender;
+import org.ops4j.pax.logging.spi.PaxLoggingEvent;
+
+import java.util.Map;
+
+public interface LogService {
+
+    String getLevel();
+    void setLevel(String level);
+
+    Map<String, String> getLevel(String logger);
+    void setLevel(String logger, String level);
+    
+    void clearEvents();
+    Iterable<PaxLoggingEvent> getEvents();
+    Iterable<PaxLoggingEvent> getEvents(int maxNum);
+    PaxLoggingEvent getLastException(String logger);
+    void addAppender(PaxAppender appender);
+    void removeAppender(PaxAppender appender);
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/7f1463c5/log/src/main/java/org/apache/karaf/log/core/internal/LogEventFormatterImpl.java
----------------------------------------------------------------------
diff --git a/log/src/main/java/org/apache/karaf/log/core/internal/LogEventFormatterImpl.java b/log/src/main/java/org/apache/karaf/log/core/internal/LogEventFormatterImpl.java
new file mode 100644
index 0000000..0ba1f3e
--- /dev/null
+++ b/log/src/main/java/org/apache/karaf/log/core/internal/LogEventFormatterImpl.java
@@ -0,0 +1,157 @@
+/*
+ * 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.karaf.log.core.internal;
+
+import org.apache.karaf.log.core.LogEventFormatter;
+import org.apache.karaf.log.core.internal.layout.PatternConverter;
+import org.apache.karaf.log.core.internal.layout.PatternParser;
+import org.ops4j.pax.logging.spi.PaxLoggingEvent;
+
+public class LogEventFormatterImpl implements LogEventFormatter {
+
+    protected String pattern;
+    protected String fatalColor;
+    protected String errorColor;
+    protected String warnColor;
+    protected String infoColor;
+    protected String debugColor;
+    protected String traceColor;
+
+    private static final String FATAL = "fatal";
+    private static final String ERROR = "error";
+    private static final String WARN = "warn";
+    private static final String INFO = "info";
+    private static final String DEBUG = "debug";
+    private static final String TRACE = "trace";
+
+    private static final char FIRST_ESC_CHAR = 27;
+    private static final char SECOND_ESC_CHAR = '[';
+    private static final char COMMAND_CHAR = 'm';
+
+    public String getPattern() {
+        return pattern;
+    }
+
+    public void setPattern(String pattern) {
+        this.pattern = pattern;
+    }
+
+    public String getFatalColor() {
+        return fatalColor;
+    }
+
+    public void setFatalColor(String fatalColor) {
+        this.fatalColor = fatalColor;
+    }
+
+    public String getErrorColor() {
+        return errorColor;
+    }
+
+    public void setErrorColor(String errorColor) {
+        this.errorColor = errorColor;
+    }
+
+    public String getWarnColor() {
+        return warnColor;
+    }
+
+    public void setWarnColor(String warnColor) {
+        this.warnColor = warnColor;
+    }
+
+    public String getInfoColor() {
+        return infoColor;
+    }
+
+    public void setInfoColor(String infoColor) {
+        this.infoColor = infoColor;
+    }
+
+    public String getDebugColor() {
+        return debugColor;
+    }
+
+    public void setDebugColor(String debugColor) {
+        this.debugColor = debugColor;
+    }
+
+    public String getTraceColor() {
+        return traceColor;
+    }
+
+    public void setTraceColor(String traceColor) {
+        this.traceColor = traceColor;
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.karaf.log.core.internal.LogEventFormatter#format(org.ops4j.pax.logging.spi.PaxLoggingEvent, java.lang.String, boolean)
+     */
+    @Override
+    public String format(PaxLoggingEvent event, String overridenPattern, boolean noColor) {
+        final PatternConverter cnv = new PatternParser(overridenPattern != null ? overridenPattern : pattern).parse();
+        String color = getColor(event, noColor);
+        StringBuffer sb = new StringBuffer();
+        sb.setLength(0);
+        if (color != null) {
+            sb.append(FIRST_ESC_CHAR);
+            sb.append(SECOND_ESC_CHAR);
+            sb.append(color);
+            sb.append(COMMAND_CHAR);
+        }
+        for (PatternConverter pc = cnv; pc != null; pc = pc.next) {
+            pc.format(sb, event);
+        }
+        if (event.getThrowableStrRep() != null) {
+            for (String r : event.getThrowableStrRep()) {
+                sb.append(r).append('\n');
+            }
+        }
+        if (color != null) {
+            sb.append(FIRST_ESC_CHAR);
+            sb.append(SECOND_ESC_CHAR);
+            sb.append("0");
+            sb.append(COMMAND_CHAR);
+        }
+        return sb.toString();
+    }
+
+    private String getColor(PaxLoggingEvent event, boolean noColor) {
+        String color = null;
+        if (!noColor && event != null && event.getLevel() != null && event.getLevel().toString() != null) {
+            String lvl = event.getLevel().toString().toLowerCase();
+            if (FATAL.equals(lvl)) {
+                color = fatalColor;
+            } else if (ERROR.equals(lvl)) {
+                color = errorColor;
+            } else if (WARN.equals(lvl)) {
+                color = warnColor;
+            } else if (INFO.equals(lvl)) {
+                color = infoColor;
+            } else if (DEBUG.equals(lvl)) {
+                color = debugColor;
+            } else if (TRACE.equals(lvl)) {
+                color = traceColor;
+            }
+            if (color != null && color.length() == 0) {
+                color = null;
+            }
+        }
+        return color;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/7f1463c5/log/src/main/java/org/apache/karaf/log/core/internal/LogMBeanImpl.java
----------------------------------------------------------------------
diff --git a/log/src/main/java/org/apache/karaf/log/core/internal/LogMBeanImpl.java b/log/src/main/java/org/apache/karaf/log/core/internal/LogMBeanImpl.java
new file mode 100644
index 0000000..49ccbf6
--- /dev/null
+++ b/log/src/main/java/org/apache/karaf/log/core/internal/LogMBeanImpl.java
@@ -0,0 +1,59 @@
+/*
+ * 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.karaf.log.core.internal;
+
+import javax.management.NotCompliantMBeanException;
+import javax.management.StandardMBean;
+
+import org.apache.karaf.log.core.LogMBean;
+import org.apache.karaf.log.core.LogService;
+
+import java.util.Map;
+
+/**
+ * Implementation of the LogMBean.
+ */
+public class LogMBeanImpl extends StandardMBean implements LogMBean {
+
+    private final LogService logService;
+
+    public LogMBeanImpl(LogService logService) throws NotCompliantMBeanException {
+        super(LogMBean.class);
+        this.logService = logService;
+    }
+
+    @Override
+    public String getLevel() {
+        return logService.getLevel();
+    }
+
+    @Override
+    public Map<String, String> getLevel(String logger) {
+        return logService.getLevel(logger);
+    }
+
+    @Override
+    public void setLevel(String level) {
+        this.logService.setLevel(level);
+    }
+
+    @Override
+    public void setLevel(String logger, String level) {
+        this.logService.setLevel(logger, level);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/7f1463c5/log/src/main/java/org/apache/karaf/log/core/internal/LogServiceImpl.java
----------------------------------------------------------------------
diff --git a/log/src/main/java/org/apache/karaf/log/core/internal/LogServiceImpl.java b/log/src/main/java/org/apache/karaf/log/core/internal/LogServiceImpl.java
new file mode 100644
index 0000000..4751873
--- /dev/null
+++ b/log/src/main/java/org/apache/karaf/log/core/internal/LogServiceImpl.java
@@ -0,0 +1,261 @@
+/*
+ * 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.karaf.log.core.internal;
+
+import java.io.IOException;
+import java.util.Dictionary;
+import java.util.Enumeration;
+import java.util.Map;
+import java.util.TreeMap;
+
+import org.apache.karaf.log.core.Level;
+import org.apache.karaf.log.core.LogService;
+import org.ops4j.pax.logging.spi.PaxAppender;
+import org.ops4j.pax.logging.spi.PaxLoggingEvent;
+import org.osgi.service.cm.Configuration;
+import org.osgi.service.cm.ConfigurationAdmin;
+
+public class LogServiceImpl implements LogService {
+
+    static final String CONFIGURATION_PID = "org.ops4j.pax.logging";
+    static final String ROOT_LOGGER_PREFIX = "log4j.rootLogger";
+    static final String LOGGER_PREFIX = "log4j.logger.";
+    static final String ALL_LOGGER = "ALL";
+    static final String ROOT_LOGGER = "ROOT";
+    
+    private final ConfigurationAdmin configAdmin;
+    private final LruList events;
+
+    public LogServiceImpl(ConfigurationAdmin configAdmin, LruList events) {
+        this.configAdmin = configAdmin;
+        this.events = events;
+    }
+
+    public String getLevel() {
+        return getLevel(null).get(ROOT_LOGGER);
+    }
+
+    public Map<String, String> getLevel(String logger) {
+        Configuration cfg;
+        try {
+            cfg = configAdmin.getConfiguration(CONFIGURATION_PID, null);
+        } catch (IOException e) {
+            throw new RuntimeException("Error retrieving Log information from config admin", e);
+        }
+        @SuppressWarnings("rawtypes")
+        Dictionary props = cfg.getProperties();
+
+        if (ROOT_LOGGER.equalsIgnoreCase(logger)) {
+            logger = null;
+        }
+
+        Map<String, String> loggers = new TreeMap<String, String>();
+
+        if (ALL_LOGGER.equalsIgnoreCase(logger)) {
+            String root = getLevelFromProperty((String) props.get(ROOT_LOGGER_PREFIX));
+            loggers.put("ROOT", root);
+            for (Enumeration e = props.keys(); e.hasMoreElements(); ) {
+                String prop = (String) e.nextElement();
+                if (prop.startsWith(LOGGER_PREFIX)) {
+                    String val = getLevelFromProperty((String) props.get(prop));
+                    loggers.put(prop.substring(LOGGER_PREFIX.length()), val);
+                }
+            }
+            return loggers;
+        }
+
+        String l = logger;
+        String val;
+        for (;;) {
+            String prop;
+            if (l == null) {
+                prop = ROOT_LOGGER_PREFIX;
+            } else {
+                prop = LOGGER_PREFIX + l;
+            }
+            val = (String) props.get(prop);
+            val = getLevelFromProperty(val);
+            if (val != null || l == null) {
+                break;
+            }
+            int idx = l.lastIndexOf('.');
+            if (idx < 0) {
+                l = null;
+            } else {
+                l = l.substring(0, idx);
+            }
+        }
+
+        if (logger == null)
+            logger = ROOT_LOGGER;
+
+        loggers.put(logger, val);
+
+        return loggers;
+    }
+
+    public void setLevel(String level) {
+        setLevel(null, level);
+    }
+
+    @SuppressWarnings("unchecked")
+    public void setLevel(String logger, String level) {
+        if (ROOT_LOGGER.equalsIgnoreCase(logger)) {
+            logger = null;
+        }
+
+        // make sure both uppercase and lowercase levels are supported
+        level = level.toUpperCase();
+
+        // check if the level is valid
+        Level.valueOf(level);
+
+        if (Level.isDefault(level) && logger == null) {
+            throw new IllegalStateException("Can not unset the ROOT logger");
+        }
+
+        Configuration cfg = getConfiguration();
+        Dictionary props = cfg.getProperties();
+
+        String val;
+        String prop;
+        if (logger == null) {
+            prop = ROOT_LOGGER_PREFIX;
+        } else {
+            prop = LOGGER_PREFIX + logger;
+        }
+
+        val = (String) props.get(prop);
+        if (Level.isDefault(level)) {
+            if (val != null) {
+                val = val.trim();
+                int idx = val.indexOf(",");
+                if (idx < 0) {
+                    val = null;
+                } else {
+                    val = val.substring(idx);
+                }
+            }
+        } else {
+            if (val == null) {
+                val = level;
+            } else {
+                val = val.trim();
+                int idx = val.indexOf(",");
+                if (idx < 0) {
+                    val = level;
+                } else {
+                    val = level + val.substring(idx);
+                }
+            }
+        }
+        if (val == null) {
+            props.remove(prop);
+        } else {
+            props.put(prop, val);
+        }
+        try {
+            cfg.update(props);
+        } catch (IOException e) {
+            throw new RuntimeException("Error writing log config to config admin", e);
+        }
+    }
+
+    private boolean checkIfFromRequestedLog(PaxLoggingEvent event, String logger) {
+        return (event.getLoggerName().lastIndexOf(logger) >= 0) ? true : false;
+    }
+
+    private String getLevelFromProperty(String prop) {
+        if (prop == null) {
+            return null;
+        } else {
+            String val = prop.trim();
+            int idx = val.indexOf(",");
+            if (idx == 0) {
+                val = null;
+            } else if (idx > 0) {
+                val = val.substring(0, idx);
+            }
+            return val;
+        }
+    }
+
+    private Configuration getConfiguration() {
+        try {
+            return configAdmin.getConfiguration(CONFIGURATION_PID, null);
+        } catch (IOException e) {
+            throw new RuntimeException("Error retrieving Log information from config admin", e);
+        }
+    }
+
+    @Override
+    public Iterable<PaxLoggingEvent> getEvents() {
+        return events.getElements();
+    }
+
+    @Override
+    public Iterable<PaxLoggingEvent> getEvents(int maxNum) {
+        return events.getElements(maxNum);
+    }
+
+    @Override
+    public void clearEvents() {
+        events.clear();
+    }
+    
+    @Override
+    public PaxLoggingEvent getLastException(String logger) {
+        PaxLoggingEvent throwableEvent = null;
+        Iterable<PaxLoggingEvent> le = getEvents();
+        for (PaxLoggingEvent event : le) {
+            // if this is an exception, and the log is the same as the requested log,
+            // then save this exception and continue iterating from oldest to newest
+            if ((event.getThrowableStrRep() != null)
+                    &&(logger != null)
+                    &&(checkIfFromRequestedLog(event, logger))) {
+                throwableEvent = event;
+              // Do not break, as we iterate from the oldest to the newest event
+            } else if ((event.getThrowableStrRep() != null)&&(logger == null)) {
+                // now check if there has been no log passed in, and if this is an exception
+                // then save this exception and continue iterating from oldest to newest
+                throwableEvent = event;             
+            }
+        }
+
+        return throwableEvent;
+    }
+
+    @Override
+    public void addAppender(PaxAppender appender) {
+        events.addAppender(appender);
+    }
+
+    @Override
+    public void removeAppender(PaxAppender appender) {
+        events.removeAppender(appender);
+    }
+
+    public Level convertToLevel(String level) {
+        level = level.toUpperCase();
+        Level res = Level.valueOf(level);
+        if (res == null) {
+            throw new IllegalArgumentException("level must be set to TRACE, DEBUG, INFO, WARN or ERROR (or DEFAULT to unset it)");
+        }
+        return res;
+    }
+
+}


[11/59] [abbrv] [KARAF-2852] Merge features/core and features/command

Posted by gn...@apache.org.
http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/core/src/main/java/org/apache/karaf/features/internal/service/Overrides.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/service/Overrides.java b/features/core/src/main/java/org/apache/karaf/features/internal/service/Overrides.java
deleted file mode 100644
index 233a8a2..0000000
--- a/features/core/src/main/java/org/apache/karaf/features/internal/service/Overrides.java
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * 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.karaf.features.internal.service;
-
-import java.io.BufferedReader;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.net.URL;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-
-import org.apache.felix.utils.manifest.Clause;
-import org.apache.felix.utils.manifest.Parser;
-import org.apache.felix.utils.version.VersionRange;
-import org.osgi.framework.Version;
-import org.osgi.resource.Resource;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import static org.apache.felix.resolver.Util.getSymbolicName;
-import static org.apache.felix.resolver.Util.getVersion;
-
-/**
- * Helper class to deal with overriden bundles at feature installation time.
- */
-public class Overrides {
-
-    private static final Logger LOGGER = LoggerFactory.getLogger(Overrides.class);
-
-    protected static final String OVERRIDE_RANGE = "range";
-
-    /**
-     * Compute a list of bundles to install, taking into account overrides.
-     *
-     * The file containing the overrides will be loaded from the given url.
-     * Blank lines and lines starting with a '#' will be ignored, all other lines
-     * are considered as urls to override bundles.
-     *
-     * The list of resources to resolve will be scanned and for each bundle,
-     * if a bundle override matches that resource, it will be used instead.
-     *
-     * Matching is done on bundle symbolic name (they have to be the same)
-     * and version (the bundle override version needs to be greater than the
-     * resource to be resolved, and less than the next minor version.  A range
-     * directive can be added to the override url in which case, the matching
-     * will succeed if the resource to be resolved is within the given range.
-     *
-     * @param resources the list of resources to resolve
-     * @param overrides list of bundle overrides
-     */
-    public static void override(Map<String, Resource> resources, Collection<String> overrides) {
-        // Do override replacement
-        for (Clause override : Parser.parseClauses(overrides.toArray(new String[overrides.size()]))) {
-            String url = override.getName();
-            String vr  = override.getAttribute(OVERRIDE_RANGE);
-            Resource over = resources.get(url);
-            if (over == null) {
-                // Ignore invalid overrides
-                continue;
-            }
-            for (String uri : new ArrayList<String>(resources.keySet())) {
-                Resource res = resources.get(uri);
-                if (getSymbolicName(res).equals(getSymbolicName(over))) {
-                    VersionRange range;
-                    if (vr == null) {
-                        // default to micro version compatibility
-                        Version v1 = getVersion(res);
-                        Version v2 = new Version(v1.getMajor(), v1.getMinor() + 1, 0);
-                        range = new VersionRange(false, v1, v2, true);
-                    } else {
-                        range = VersionRange.parseVersionRange(vr);
-                    }
-                    // The resource matches, so replace it with the overridden resource
-                    // if the override is actually a newer version than what we currently have
-                    if (range.contains(getVersion(over)) && getVersion(res).compareTo(getVersion(over)) < 0) {
-                        resources.put(uri, over);
-                    }
-                }
-            }
-        }
-    }
-
-    public static Set<String> loadOverrides(String overridesUrl) {
-        Set<String> overrides = new HashSet<String>();
-        try {
-            if (overridesUrl != null) {
-                InputStream is = new URL(overridesUrl).openStream();
-                try {
-                    BufferedReader reader = new BufferedReader(new InputStreamReader(is));
-                    String line;
-                    while ((line = reader.readLine()) != null) {
-                        line = line.trim();
-                        if (!line.isEmpty() && !line.startsWith("#")) {
-                            overrides.add(line);
-                        }
-                    }
-                } finally {
-                    is.close();
-                }
-            }
-        } catch (Exception e) {
-            LOGGER.debug("Unable to load overrides bundles list", e);
-        }
-        return overrides;
-    }
-
-    public static String extractUrl(String override) {
-        Clause[] cs = Parser.parseClauses(new String[] { override });
-        if (cs.length != 1) {
-            throw new IllegalStateException("Override contains more than one clause: " + override);
-        }
-        return cs[0].getName();
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/core/src/main/java/org/apache/karaf/features/internal/service/RepositoryImpl.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/service/RepositoryImpl.java b/features/core/src/main/java/org/apache/karaf/features/internal/service/RepositoryImpl.java
deleted file mode 100644
index 4bf1502..0000000
--- a/features/core/src/main/java/org/apache/karaf/features/internal/service/RepositoryImpl.java
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * 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.karaf.features.internal.service;
-
-import java.io.FilterInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InterruptedIOException;
-import java.net.URI;
-
-import org.apache.karaf.features.Repository;
-import org.apache.karaf.features.internal.model.Features;
-import org.apache.karaf.features.internal.model.JaxbUtil;
-
-/**
- * The repository implementation.
- */
-public class RepositoryImpl implements Repository {
-
-    private final URI uri;
-    private Features features;
-
-    public RepositoryImpl(URI uri) {
-        this.uri = uri;
-    }
-
-    public URI getURI() {
-        return uri;
-    }
-
-    public String getName() {
-        // TODO: catching this exception is ugly
-        try {
-            load();
-        } catch (IOException e) {
-            throw new RuntimeException("Unable to load repository", e);
-        }
-        return features.getName();
-    }
-
-    public URI[] getRepositories() throws Exception {
-        load();
-        URI[] result = new URI[features.getRepository().size()];
-        for (int i = 0; i < features.getRepository().size(); i++) {
-            String uri = features.getRepository().get(i);
-            uri = uri.trim();
-            result[i] = URI.create(uri);
-        }
-        return result;
-    }
-
-    public org.apache.karaf.features.Feature[] getFeatures() throws Exception {
-        load();
-        return features.getFeature().toArray(new org.apache.karaf.features.Feature[features.getFeature().size()]);
-    }
-
-
-    public void load() throws IOException {
-        if (features == null) {
-            try {
-                InputStream inputStream = uri.toURL().openStream();
-                inputStream = new FilterInputStream(inputStream) {
-    				@Override
-    				public int read(byte[] b, int off, int len) throws IOException {
-    					if (Thread.currentThread().isInterrupted()) {
-    						throw new InterruptedIOException();
-    					}
-    					return super.read(b, off, len);
-    				}
-    			};
-                try {
-                    features = JaxbUtil.unmarshal(inputStream, false);
-                } finally {
-                    inputStream.close();
-                }
-            } catch (IllegalArgumentException e) {
-                throw (IOException) new IOException(e.getMessage() + " : " + uri).initCause(e);
-            } catch (Exception e) {
-                throw (IOException) new IOException(e.getMessage() + " : " + uri).initCause(e);
-            }
-        }
-    }
-
-    @Override
-    public boolean isValid() {
-        throw new UnsupportedOperationException();
-    }
-}
-

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/core/src/main/java/org/apache/karaf/features/internal/service/RequirementSort.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/service/RequirementSort.java b/features/core/src/main/java/org/apache/karaf/features/internal/service/RequirementSort.java
deleted file mode 100644
index e9ecece..0000000
--- a/features/core/src/main/java/org/apache/karaf/features/internal/service/RequirementSort.java
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * 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.karaf.features.internal.service;
-
-
-import org.apache.karaf.features.internal.resolver.RequirementImpl;
-import org.apache.karaf.features.internal.resolver.SimpleFilter;
-import org.osgi.framework.Constants;
-import org.osgi.resource.Capability;
-import org.osgi.resource.Requirement;
-import org.osgi.resource.Resource;
-
-import java.util.Collection;
-import java.util.LinkedHashSet;
-import java.util.List;
-import java.util.Set;
-
-public class RequirementSort  {
-
-    /**
-     * Sorts {@link Resource} based on their {@link Requirement}s and {@link Capability}s.
-     * @param resources
-     * @return
-     */
-    public static <T extends Resource> Collection<T> sort(Collection<T> resources) {
-        Set<T> sorted = new LinkedHashSet<T>();
-        Set<T> visited = new LinkedHashSet<T>();
-        for (T r : resources) {
-            visit(r, resources, visited, sorted);
-        }
-        return sorted;
-    }
-
-
-    private static <T extends Resource> void visit(T resource, Collection<T> resources, Set<T> visited, Set<T> sorted) {
-        if (visited.contains(resource)) {
-            return;
-        }
-        visited.add(resource);
-        for (T r : collectDependencies(resource, resources)) {
-            visit(r, resources, visited, sorted);
-        }
-        sorted.add(resource);
-    }
-
-    /**
-     * Finds the dependencies of the current resource.
-     * @param resource
-     * @param allResources
-     * @return
-     */
-    private static <T extends Resource> Set<T> collectDependencies(T resource, Collection<T> allResources) {
-        Set<T> result = new LinkedHashSet<T>();
-        List<Requirement> requirements = resource.getRequirements(null);
-        for (Requirement requirement : requirements) {
-            boolean isSatisfied = false;
-            for (Resource r : result) {
-                for (Capability capability : r.getCapabilities(null)) {
-                    if (isSatisfied(requirement, capability)) {
-                        isSatisfied = true;
-                        break;
-                    }
-                }
-            }
-
-            for (T r : allResources) {
-                if (!isSatisfied) {
-                    for (Capability capability : r.getCapabilities(null)) {
-                        if (isSatisfied(requirement, capability)) {
-                            result.add(r);
-                            break;
-                        }
-                    }
-                }
-            }
-        }
-        return result;
-    }
-
-    private static boolean isSatisfied(Requirement requirement, Capability capability) {
-        RequirementImpl br;
-        if (requirement instanceof RequirementImpl) {
-            br = (RequirementImpl) requirement;
-        } else {
-            String filter = requirement.getDirectives().get(Constants.FILTER_DIRECTIVE);
-            SimpleFilter sf = (filter != null)
-                    ? SimpleFilter.parse(filter)
-                    : new SimpleFilter(null, null, SimpleFilter.MATCH_ALL);
-            br = new RequirementImpl(null, requirement.getNamespace(), requirement.getDirectives(), requirement.getAttributes(), sf);
-        }
-        return br.matches(capability);
-    }
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/core/src/main/java/org/apache/karaf/features/internal/service/SimpleDownloader.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/service/SimpleDownloader.java b/features/core/src/main/java/org/apache/karaf/features/internal/service/SimpleDownloader.java
deleted file mode 100644
index d1f16b9..0000000
--- a/features/core/src/main/java/org/apache/karaf/features/internal/service/SimpleDownloader.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * 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.karaf.features.internal.service;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.MalformedURLException;
-import java.net.URL;
-
-import org.apache.karaf.features.internal.deployment.Downloader;
-import org.apache.karaf.features.internal.deployment.StreamProvider;
-import org.apache.karaf.features.internal.util.MultiException;
-
-public class SimpleDownloader implements Downloader {
-
-    private final MultiException exception = new MultiException("Error");
-
-    @Override
-    public void await() throws InterruptedException, MultiException {
-        exception.throwIfExceptions();
-    }
-
-    @Override
-    public void download(final String location, final DownloadCallback downloadCallback) throws MalformedURLException {
-        final URL url = new URL(location);
-        try {
-            downloadCallback.downloaded(new StreamProvider() {
-                @Override
-                public InputStream open() throws IOException {
-                    return url.openStream();
-                }
-            });
-        } catch (Exception e) {
-            exception.addException(e);
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/core/src/main/java/org/apache/karaf/features/internal/service/State.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/service/State.java b/features/core/src/main/java/org/apache/karaf/features/internal/service/State.java
deleted file mode 100644
index c84f4e0..0000000
--- a/features/core/src/main/java/org/apache/karaf/features/internal/service/State.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * 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.karaf.features.internal.service;
-
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Set;
-import java.util.TreeSet;
-import java.util.concurrent.atomic.AtomicBoolean;
-
-public class State {
-
-    public final AtomicBoolean bootDone = new AtomicBoolean();
-    public final Set<String> repositories = new TreeSet<String>();
-    public final Set<String> features = new TreeSet<String>();
-    public final Set<String> installedFeatures = new TreeSet<String>();
-    public final Set<Long> managedBundles = new TreeSet<Long>();
-    public final Map<String, Long> bundleChecksums = new HashMap<String, Long>();
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/core/src/main/java/org/apache/karaf/features/internal/service/StateStorage.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/service/StateStorage.java b/features/core/src/main/java/org/apache/karaf/features/internal/service/StateStorage.java
deleted file mode 100644
index ac54ab0..0000000
--- a/features/core/src/main/java/org/apache/karaf/features/internal/service/StateStorage.java
+++ /dev/null
@@ -1,175 +0,0 @@
-/*
- * 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.karaf.features.internal.service;
-
-import java.io.Closeable;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.util.ArrayList;
-import java.util.Enumeration;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Properties;
-import java.util.Set;
-import java.util.TreeSet;
-
-import org.apache.karaf.features.Feature;
-
-public abstract class StateStorage {
-
-    public void load(State state) throws IOException {
-        state.repositories.clear();
-        state.features.clear();
-        state.installedFeatures.clear();
-        state.managedBundles.clear();
-        InputStream is = getInputStream();
-        if (is != null) {
-            try {
-                Properties props = new Properties();
-                props.load(is);
-                state.bootDone.set(loadBool(props, "bootDone"));
-                state.repositories.addAll(loadSet(props, "repositories."));
-                state.features.addAll(loadSet(props, "features."));
-                state.installedFeatures.addAll(loadSet(props, "installed."));
-                state.managedBundles.addAll(toLongSet(loadSet(props, "managed.")));
-                state.bundleChecksums.putAll(toStringLongMap(loadMap(props, "checksums.")));
-            } finally {
-                close(is);
-            }
-        }
-    }
-
-    public void save(State state) throws IOException {
-        OutputStream os = getOutputStream();
-        if (os != null) {
-            try {
-                Properties props = new Properties();
-                saveBool(props, "bootDone", state.bootDone.get());
-                saveSet(props, "repositories.", state.repositories);
-                saveSet(props, "features.", state.features);
-                saveSet(props, "installed.", state.installedFeatures);
-                saveSet(props, "managed.", toStringSet(state.managedBundles));
-                saveMap(props, "checksums.", toStringStringMap(state.bundleChecksums));
-                props.store(os, "FeaturesService State");
-            } finally {
-                close(os);
-            }
-        }
-    }
-
-    protected abstract InputStream getInputStream() throws IOException;
-    protected abstract OutputStream getOutputStream() throws IOException;
-
-    protected boolean loadBool(Properties props, String key) {
-        return Boolean.parseBoolean(props.getProperty(key));
-    }
-
-    protected void saveBool(Properties props, String key, boolean val) {
-        props.setProperty(key, Boolean.toString(val));
-    }
-
-    protected Set<String> toStringSet(Set<Long> set) {
-        Set<String> ns = new TreeSet<String>();
-        for (long l : set) {
-            ns.add(Long.toString(l));
-        }
-        return ns;
-    }
-
-    protected Set<Long> toLongSet(Set<String> set) {
-        Set<Long> ns = new TreeSet<Long>();
-        for (String s : set) {
-            ns.add(Long.parseLong(s));
-        }
-        return ns;
-    }
-
-    protected void saveSet(Properties props, String prefix, Set<String> set) {
-        List<String> l = new ArrayList<String>(set);
-        props.put(prefix + "count", Integer.toString(l.size()));
-        for (int i = 0; i < l.size(); i++) {
-            props.put(prefix + "item." + i, l.get(i));
-        }
-    }
-
-    protected Set<String> loadSet(Properties props, String prefix) {
-        Set<String> l = new HashSet<String>();
-        String countStr = (String) props.get(prefix + "count");
-        if (countStr != null) {
-            int count = Integer.parseInt(countStr);
-            for (int i = 0; i < count; i++) {
-                l.add((String) props.get(prefix + "item." + i));
-            }
-        }
-        return l;
-    }
-
-    protected Map<String, String> toStringStringMap(Map<String, Long> map) {
-        Map<String, String> nm = new HashMap<String, String>();
-        for (Map.Entry<String, Long> entry : map.entrySet()) {
-            nm.put(entry.getKey(), Long.toString(entry.getValue()));
-        }
-        return nm;
-    }
-
-    protected Map<String, Long> toStringLongMap(Map<String, String> map) {
-        Map<String, Long> nm = new HashMap<String, Long>();
-        for (Map.Entry<String, String> entry : map.entrySet()) {
-            nm.put(entry.getKey(), Long.parseLong(entry.getValue()));
-        }
-        return nm;
-    }
-
-
-    protected void saveMap(Properties props, String prefix, Map<String, String> map) {
-        List<Map.Entry<String, String>> l = new ArrayList<Map.Entry<String, String>>(map.entrySet());
-        props.put(prefix + "count", Integer.toString(l.size()));
-        for (int i = 0; i < l.size(); i++) {
-            props.put(prefix + "key." + i, l.get(i).getKey());
-            props.put(prefix + "val." + i, l.get(i).getValue());
-        }
-    }
-
-    protected Map<String, String> loadMap(Properties props, String prefix) {
-        Map<String, String> l = new HashMap<String, String>();
-        String countStr = (String) props.get(prefix + "count");
-        if (countStr != null) {
-            int count = Integer.parseInt(countStr);
-            for (int i = 0; i < count; i++) {
-                String key = (String) props.get(prefix + "key." + i);
-                String val = (String) props.get(prefix + "val." + i);
-                l.put(key, val);
-            }
-        }
-        return l;
-    }
-
-
-    protected void close(Closeable closeable) {
-        if (closeable != null) {
-            try {
-                closeable.close();
-            } catch (IOException e) {
-                // Ignore
-            }
-        }
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/core/src/main/java/org/apache/karaf/features/internal/util/ChecksumUtils.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/util/ChecksumUtils.java b/features/core/src/main/java/org/apache/karaf/features/internal/util/ChecksumUtils.java
deleted file mode 100644
index 19fc706..0000000
--- a/features/core/src/main/java/org/apache/karaf/features/internal/util/ChecksumUtils.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * 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.karaf.features.internal.util;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.zip.CRC32;
-
-public class ChecksumUtils {
-
-    private ChecksumUtils() {
-    }
-
-    /**
-     * Compute a cheksum for the file or directory that consists of the name, length and the last modified date
-     * for a file and its children in case of a directory
-     *
-     * @param is the input stream
-     * @return a checksum identifying any change
-     */
-    public static long checksum(InputStream is) throws IOException
-    {
-        try {
-            CRC32 crc = new CRC32();
-            byte[] buffer = new byte[8192];
-            int l;
-            while ((l = is.read(buffer)) > 0) {
-                crc.update(buffer, 0, l);
-            }
-            return crc.getValue();
-        } finally {
-            if (is != null) {
-                try {
-                    is.close();
-                } catch (IOException e) {
-                    // Ignore
-                }
-            }
-        }
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/core/src/main/java/org/apache/karaf/features/internal/util/JsonReader.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/util/JsonReader.java b/features/core/src/main/java/org/apache/karaf/features/internal/util/JsonReader.java
deleted file mode 100644
index a53d8a5..0000000
--- a/features/core/src/main/java/org/apache/karaf/features/internal/util/JsonReader.java
+++ /dev/null
@@ -1,349 +0,0 @@
-/*
- * 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.karaf.features.internal.util;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.Reader;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- */
-public class JsonReader {
-
-    public static Object read(Reader reader) throws IOException {
-        return new JsonReader(reader).parse();
-    }
-
-    public static Object read(InputStream is) throws IOException {
-        return new JsonReader(new InputStreamReader(is)).parse();
-    }
-
-    //
-    // Implementation
-    //
-
-    private final Reader reader;
-    private final StringBuilder recorder;
-    private int current;
-    private int line = 1;
-    private int column = 0;
-
-    JsonReader(Reader reader) {
-        this.reader = reader;
-        recorder = new StringBuilder();
-    }
-
-    public Object parse() throws IOException {
-        read();
-        skipWhiteSpace();
-        Object result = readValue();
-        skipWhiteSpace();
-        if (!endOfText()) {
-            throw error("Unexpected character");
-        }
-        return result;
-    }
-
-    private Object readValue() throws IOException {
-        switch (current) {
-            case 'n':
-                return readNull();
-            case 't':
-                return readTrue();
-            case 'f':
-                return readFalse();
-            case '"':
-                return readString();
-            case '[':
-                return readArray();
-            case '{':
-                return readObject();
-            case '-':
-            case '0':
-            case '1':
-            case '2':
-            case '3':
-            case '4':
-            case '5':
-            case '6':
-            case '7':
-            case '8':
-            case '9':
-                return readNumber();
-            default:
-                throw expected("value");
-        }
-    }
-
-    private Collection<?> readArray() throws IOException {
-        read();
-        Collection<Object> array = new ArrayList<Object>();
-        skipWhiteSpace();
-        if (readChar(']')) {
-            return array;
-        }
-        do {
-            skipWhiteSpace();
-            array.add(readValue());
-            skipWhiteSpace();
-        } while (readChar(','));
-        if (!readChar(']')) {
-            throw expected("',' or ']'");
-        }
-        return array;
-    }
-
-    private Map<String, Object> readObject() throws IOException {
-        read();
-        Map<String, Object> object = new HashMap<String, Object>();
-        skipWhiteSpace();
-        if (readChar('}')) {
-            return object;
-        }
-        do {
-            skipWhiteSpace();
-            String name = readName();
-            skipWhiteSpace();
-            if (!readChar(':')) {
-                throw expected("':'");
-            }
-            skipWhiteSpace();
-            object.put(name, readValue());
-            skipWhiteSpace();
-        } while (readChar(','));
-        if (!readChar('}')) {
-            throw expected("',' or '}'");
-        }
-        return object;
-    }
-
-    private Object readNull() throws IOException {
-        read();
-        readRequiredChar('u');
-        readRequiredChar('l');
-        readRequiredChar('l');
-        return null;
-    }
-
-    private Boolean readTrue() throws IOException {
-        read();
-        readRequiredChar('r');
-        readRequiredChar('u');
-        readRequiredChar('e');
-        return Boolean.TRUE;
-    }
-
-    private Boolean readFalse() throws IOException {
-        read();
-        readRequiredChar('a');
-        readRequiredChar('l');
-        readRequiredChar('s');
-        readRequiredChar('e');
-        return Boolean.FALSE;
-    }
-
-    private void readRequiredChar(char ch) throws IOException {
-        if (!readChar(ch)) {
-            throw expected("'" + ch + "'");
-        }
-    }
-
-    private String readString() throws IOException {
-        read();
-        recorder.setLength(0);
-        while (current != '"') {
-            if (current == '\\') {
-                readEscape();
-            } else if (current < 0x20) {
-                throw expected("valid string character");
-            } else {
-                recorder.append((char) current);
-                read();
-            }
-        }
-        read();
-        return recorder.toString();
-    }
-
-    private void readEscape() throws IOException {
-        read();
-        switch (current) {
-            case '"':
-            case '/':
-            case '\\':
-                recorder.append((char) current);
-                break;
-            case 'b':
-                recorder.append('\b');
-                break;
-            case 'f':
-                recorder.append('\f');
-                break;
-            case 'n':
-                recorder.append('\n');
-                break;
-            case 'r':
-                recorder.append('\r');
-                break;
-            case 't':
-                recorder.append('\t');
-                break;
-            case 'u':
-                char[] hexChars = new char[4];
-                for (int i = 0; i < 4; i++) {
-                    read();
-                    if (!isHexDigit(current)) {
-                        throw expected("hexadecimal digit");
-                    }
-                    hexChars[i] = (char) current;
-                }
-                recorder.append((char) Integer.parseInt(String.valueOf(hexChars), 16));
-                break;
-            default:
-                throw expected("valid escape sequence");
-        }
-        read();
-    }
-
-    private Number readNumber() throws IOException {
-        recorder.setLength(0);
-        readAndAppendChar('-');
-        int firstDigit = current;
-        if (!readAndAppendDigit()) {
-            throw expected("digit");
-        }
-        if (firstDigit != '0') {
-            while (readAndAppendDigit()) {
-            }
-        }
-        readFraction();
-        readExponent();
-        return Double.parseDouble(recorder.toString());
-    }
-
-    private boolean readFraction() throws IOException {
-        if (!readAndAppendChar('.')) {
-            return false;
-        }
-        if (!readAndAppendDigit()) {
-            throw expected("digit");
-        }
-        while (readAndAppendDigit()) {
-        }
-        return true;
-    }
-
-    private boolean readExponent() throws IOException {
-        if (!readAndAppendChar('e') && !readAndAppendChar('E')) {
-            return false;
-        }
-        if (!readAndAppendChar('+')) {
-            readAndAppendChar('-');
-        }
-        if (!readAndAppendDigit()) {
-            throw expected("digit");
-        }
-        while (readAndAppendDigit()) {
-        }
-        return true;
-    }
-
-    private String readName() throws IOException {
-        if (current != '"') {
-            throw expected("name");
-        }
-        readString();
-        return recorder.toString();
-    }
-
-    private boolean readAndAppendChar(char ch) throws IOException {
-        if (current != ch) {
-            return false;
-        }
-        recorder.append(ch);
-        read();
-        return true;
-    }
-
-    private boolean readChar(char ch) throws IOException {
-        if (current != ch) {
-            return false;
-        }
-        read();
-        return true;
-    }
-
-    private boolean readAndAppendDigit() throws IOException {
-        if (!isDigit(current)) {
-            return false;
-        }
-        recorder.append((char) current);
-        read();
-        return true;
-    }
-
-    private void skipWhiteSpace() throws IOException {
-        while (isWhiteSpace(current) && !endOfText()) {
-            read();
-        }
-    }
-
-    private void read() throws IOException {
-        if (endOfText()) {
-            throw error("Unexpected end of input");
-        }
-        column++;
-        if (current == '\n') {
-            line++;
-            column = 0;
-        }
-        current = reader.read();
-    }
-
-    private boolean endOfText() {
-        return current == -1;
-    }
-
-    private IOException expected(String expected) {
-        if (endOfText()) {
-            return error("Unexpected end of input");
-        }
-        return error("Expected " + expected);
-    }
-
-    private IOException error(String message) {
-        return new IOException(message + " at " + line + ":" + column);
-    }
-
-    private static boolean isWhiteSpace(int ch) {
-        return ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r';
-    }
-
-    private static boolean isDigit(int ch) {
-        return ch >= '0' && ch <= '9';
-    }
-
-    private static boolean isHexDigit(int ch) {
-        return ch >= '0' && ch <= '9' || ch >= 'a' && ch <= 'f' || ch >= 'A' && ch <= 'F';
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/core/src/main/java/org/apache/karaf/features/internal/util/JsonWriter.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/util/JsonWriter.java b/features/core/src/main/java/org/apache/karaf/features/internal/util/JsonWriter.java
deleted file mode 100644
index cba27fb..0000000
--- a/features/core/src/main/java/org/apache/karaf/features/internal/util/JsonWriter.java
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * 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.karaf.features.internal.util;
-
-import java.io.IOException;
-import java.io.Writer;
-import java.util.Collection;
-import java.util.Map;
-
-/**
- */
-public class JsonWriter {
-
-    public static void write(Writer writer, Object value) throws IOException {
-        if (value instanceof Map) {
-            writeObject(writer, (Map) value);
-        } else if (value instanceof Collection) {
-            writeArray(writer, (Collection) value);
-        } else if (value instanceof Number) {
-            writeNumber(writer, (Number) value);
-        } else if (value instanceof String) {
-            writeString(writer, (String) value);
-        } else if (value instanceof Boolean) {
-            writeBoolean(writer, (Boolean) value);
-        } else if (value == null) {
-            writeNull(writer);
-        } else {
-            throw new IllegalArgumentException("Unsupported value: " + value);
-        }
-    }
-
-    private static void writeObject(Writer writer, Map<?, ?> value) throws IOException {
-        writer.append('{');
-        boolean first = true;
-        for (Map.Entry entry : value.entrySet()) {
-            if (!first) {
-                writer.append(',');
-            } else {
-                first = false;
-            }
-            writeString(writer, (String) entry.getKey());
-            writer.append(':');
-            write(writer, entry.getValue());
-        }
-        writer.append('}');
-    }
-
-    private static void writeString(Writer writer, String value) throws IOException {
-        writer.append('"');
-        for (int i = 0; i < value.length(); i++) {
-            char c = value.charAt(i);
-            switch (c) {
-                case '\"':
-                case '\\':
-                case '\b':
-                case '\f':
-                case '\n':
-                case '\r':
-                case '\t':
-                    writer.append('\\');
-                    writer.append(c);
-                    break;
-                default:
-                    if (c < ' ' || (c >= '\u0080' && c < '\u00a0') || (c >= '\u2000' && c < '\u2100')) {
-                        String s = Integer.toHexString(c);
-                        writer.append('\\');
-                        writer.append('u');
-                        for (int j = s.length(); j < 4; j++) {
-                            writer.append('0');
-                        }
-                        writer.append(s);
-                    } else {
-                        writer.append(c);
-                    }
-                    break;
-            }
-        }
-        writer.append('"');
-    }
-
-    private static void writeNumber(Writer writer, Number value) throws IOException {
-        writer.append(value.toString());
-    }
-
-    private static void writeBoolean(Writer writer, Boolean value) throws IOException {
-        writer.append(Boolean.toString(value));
-    }
-
-    private static void writeArray(Writer writer, Collection<?> value) throws IOException {
-        writer.append('[');
-        boolean first = true;
-        for (Object obj : value) {
-            if (!first) {
-                writer.append(',');
-            } else {
-                first = false;
-            }
-            write(writer, obj);
-        }
-        writer.append(']');
-    }
-
-    private static void writeNull(Writer writer) throws IOException {
-        writer.append("null");
-    }
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/core/src/main/java/org/apache/karaf/features/internal/util/Macro.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/util/Macro.java b/features/core/src/main/java/org/apache/karaf/features/internal/util/Macro.java
deleted file mode 100644
index d30b7b5..0000000
--- a/features/core/src/main/java/org/apache/karaf/features/internal/util/Macro.java
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * 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.karaf.features.internal.util;
-
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import org.apache.felix.utils.version.VersionTable;
-import org.osgi.framework.Version;
-
-public class Macro {
-
-    public static String transform(String macro, String value) {
-        if (macro.startsWith("${") && macro.endsWith("}")) {
-            String[] args = macro.substring(2, macro.length() - 1).split(";");
-            if ("version".equals(args[0])) {
-                if (args.length != 2) {
-                    throw new IllegalArgumentException("Invalid syntax for macro: " + macro);
-                }
-                return version(args[1], VersionTable.getVersion(value));
-            } else if ("range".equals(args[0])) {
-                if (args.length != 2) {
-                    throw new IllegalArgumentException("Invalid syntax for macro: " + macro);
-                }
-                return range(args[1], VersionTable.getVersion(value));
-            } else {
-                throw new IllegalArgumentException("Unknown macro: " + macro);
-            }
-        }
-        return value;
-    }
-
-    /**
-     * Modify a version to set a version policy. Thed policy is a mask that is
-     * mapped to a version.
-     *
-     * <pre>
-     * +           increment
-     * -           decrement
-     * =           maintain
-     * &tilde;           discard
-     *
-     * ==+      = maintain major, minor, increment micro, discard qualifier
-     * &tilde;&tilde;&tilde;=     = just get the qualifier
-     * version=&quot;[${version;==;${@}},${version;=+;${@}})&quot;
-	 * </pre>
-	 *
-	 * @param args
-     * @return
-     */
-    final static String	MASK_STRING			= "[\\-+=~0123456789]{0,3}[=~]?";
-
-    static String version(String mask, Version version) {
-        StringBuilder sb = new StringBuilder();
-        String del = "";
-
-        for (int i = 0; i < mask.length(); i++) {
-            char c = mask.charAt(i);
-            String result = null;
-            if (c != '~') {
-                if (i > 3) {
-                    throw new IllegalArgumentException("Version mask can only specify 3 digits");
-                } else if (i == 3) {
-                    result = version.getQualifier();
-                    if (result.isEmpty()) {
-                        result = null;
-                    }
-                } else if (Character.isDigit(c)) {
-                    // Handle masks like +00, =+0
-                    result = String.valueOf(c);
-                } else {
-                    int x = 0;
-                    switch (i) {
-                        case 0: x = version.getMajor(); break;
-                        case 1: x = version.getMinor(); break;
-                        case 2: x = version.getMicro(); break;
-                    }
-                    switch (c) {
-                        case '+' :
-                            x++;
-                            break;
-                        case '-' :
-                            x--;
-                            break;
-                        case '=' :
-                            break;
-                    }
-                    result = Integer.toString(x);
-                }
-                if (result != null) {
-                    sb.append(del);
-                    del = ".";
-                    sb.append(result);
-                }
-            }
-        }
-        return sb.toString();
-    }
-
-    /**
-     * Schortcut for version policy
-     *
-     * <pre>
-     * -provide-policy : ${policy;[==,=+)}
-     * -consume-policy : ${policy;[==,+)}
-     * </pre>
-     *
-     * @param args
-     * @return
-     */
-
-    static Pattern	RANGE_MASK		= Pattern.compile("(\\[|\\()(" + MASK_STRING + "),(" + MASK_STRING + ")(\\]|\\))");
-
-    static String range(String spec, Version version) {
-        Matcher m = RANGE_MASK.matcher(spec);
-        m.matches();
-        String floor = m.group(1);
-        String floorMask = m.group(2);
-        String ceilingMask = m.group(3);
-        String ceiling = m.group(4);
-
-        String left = version(floorMask, version);
-        String right = version(ceilingMask, version);
-
-        return floor + left + "," + right + ceiling;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/core/src/main/java/org/apache/karaf/features/internal/util/MultiException.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/util/MultiException.java b/features/core/src/main/java/org/apache/karaf/features/internal/util/MultiException.java
deleted file mode 100644
index 36af452..0000000
--- a/features/core/src/main/java/org/apache/karaf/features/internal/util/MultiException.java
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * 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.karaf.features.internal.util;
-
-import java.io.PrintStream;
-import java.io.PrintWriter;
-import java.util.ArrayList;
-import java.util.List;
-
-@SuppressWarnings("serial")
-public class MultiException extends Exception {
-
-    private List<Exception> exceptions = new ArrayList<Exception>();
-
-    public MultiException(String message) {
-        super(message);
-    }
-
-    public MultiException(String message, List<Exception> exceptions) {
-        super(message);
-        this.exceptions = exceptions;
-    }
-
-    public void addException(Exception e) {
-        exceptions.add(e);
-    }
-
-    public void throwIfExceptions() throws MultiException {
-        if (!exceptions.isEmpty()) {
-            throw this;
-        }
-    }
-    
-    public Throwable[] getCauses() {
-        return exceptions.toArray(new Throwable[exceptions.size()]);
-    }
-
-    @Override
-    public void printStackTrace()
-    {
-        super.printStackTrace();
-        for (Exception e : exceptions) {
-            e.printStackTrace();
-        }
-    }
-
-
-    /* ------------------------------------------------------------------------------- */
-    /**
-     * @see Throwable#printStackTrace(java.io.PrintStream)
-     */
-    @Override
-    public void printStackTrace(PrintStream out)
-    {
-        super.printStackTrace(out);
-        for (Exception e : exceptions) {
-            e.printStackTrace(out);
-        }
-    }
-
-    @Override
-    public void printStackTrace(PrintWriter out)
-    {
-        super.printStackTrace(out);
-        for (Exception e : exceptions) {
-            e.printStackTrace(out);
-        }
-    }
-
-    public static void throwIf(String message, List<Exception> exceptions) throws MultiException {
-        if (exceptions != null && !exceptions.isEmpty()) {
-            StringBuilder sb = new StringBuilder(message);
-            sb.append(":");
-            for (Exception e : exceptions) {
-                sb.append("\n\t");
-                sb.append(e.getMessage());
-            }
-            throw new MultiException(sb.toString(), exceptions);
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/core/src/main/java/org/apache/karaf/features/management/FeaturesServiceMBean.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/management/FeaturesServiceMBean.java b/features/core/src/main/java/org/apache/karaf/features/management/FeaturesServiceMBean.java
deleted file mode 100644
index 6afbbed..0000000
--- a/features/core/src/main/java/org/apache/karaf/features/management/FeaturesServiceMBean.java
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * 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.karaf.features.management;
-
-import javax.management.openmbean.TabularData;
-
-public interface FeaturesServiceMBean {
-
-    TabularData getFeatures() throws Exception;
-
-    TabularData getRepositories() throws Exception;
-
-    void addRepository(String url) throws Exception;
-
-    void addRepository(String url, boolean install) throws Exception;
-
-    void removeRepository(String url) throws Exception;
-
-    void removeRepository(String url, boolean uninstall) throws Exception;
-
-    void installFeature(String name) throws Exception;
-
-    void installFeature(String name, boolean noRefresh) throws Exception;
-
-    void installFeature(String name, boolean noRefresh, boolean noStart) throws Exception;
-
-    void installFeature(String name, String version) throws Exception;
-
-    void installFeature(String name, String version, boolean noRefresh) throws Exception;
-
-    void installFeature(String name, String version, boolean noRefresh, boolean noStart) throws Exception;
-
-    TabularData infoFeature(String name) throws Exception;
-
-    TabularData infoFeature(String name, String version) throws Exception;
-
-    void uninstallFeature(String name) throws Exception;
-
-    void uninstallFeature(String name, boolean noRefresh) throws Exception;
-
-    void uninstallFeature(String name, String version) throws Exception;
-
-    void uninstallFeature(String name, String version, boolean noRefresh) throws Exception;
-
-    String FEATURE_NAME = "Name";
-
-    String FEATURE_VERSION = "Version";
-
-    String FEATURE_DEPENDENCIES = "Dependencies";
-
-    String FEATURE_BUNDLES = "Bundles";
-
-    String FEATURE_CONFIGURATIONS = "Configurations";
-    
-    String FEATURE_CONFIGURATIONFILES = "Configuration Files";
-
-    String FEATURE_INSTALLED = "Installed";
-
-    String FEATURE_CONFIG_PID = "Pid";
-    String FEATURE_CONFIG_ELEMENTS = "Elements";
-    String FEATURE_CONFIG_ELEMENT_KEY = "Key";
-    String FEATURE_CONFIG_ELEMENT_VALUE = "Value";
-    
-    String FEATURE_CONFIG_FILES_ELEMENTS = "Files";
-
-    /**
-     * The type of the event which is emitted for features events
-     */
-    String FEATURE_EVENT_TYPE = "org.apache.karaf.features.featureEvent";
-
-    String FEATURE_EVENT_EVENT_TYPE = "Type";
-
-    String FEATURE_EVENT_EVENT_TYPE_INSTALLED = "Installed";
-
-    String FEATURE_EVENT_EVENT_TYPE_UNINSTALLED = "Uninstalled";
-
-    /**
-     * The item names in the CompositeData representing a feature
-     */
-    String[] FEATURE = { FEATURE_NAME, FEATURE_VERSION, FEATURE_DEPENDENCIES, FEATURE_BUNDLES,
-                         FEATURE_CONFIGURATIONS, FEATURE_CONFIGURATIONFILES, FEATURE_INSTALLED };
-
-    String[] FEATURE_IDENTIFIER = { FEATURE_NAME, FEATURE_VERSION };
-
-    String[] FEATURE_CONFIG = { FEATURE_CONFIG_PID, FEATURE_CONFIG_ELEMENTS };
-    
-    String[] FEATURE_CONFIG_FILES = { FEATURE_CONFIG_FILES_ELEMENTS };
-
-    String[] FEATURE_CONFIG_ELEMENT = { FEATURE_CONFIG_ELEMENT_KEY, FEATURE_CONFIG_ELEMENT_VALUE };
-
-    /**
-     * The item names in the CompositeData representing the event raised for
-     * feature events within the OSGi container by this bean
-     */
-    String[] FEATURE_EVENT = { FEATURE_NAME, FEATURE_VERSION, FEATURE_EVENT_EVENT_TYPE };
-
-
-    String REPOSITORY_NAME = "Name";
-
-    String REPOSITORY_URI = "Uri";
-
-    String REPOSITORY_REPOSITORIES = "Repositories";
-
-    String REPOSITORY_FEATURES = "Features";
-
-    /**
-     * The type of the event which is emitted for repositories events
-     */
-    String REPOSITORY_EVENT_TYPE = "org.apache.karaf.features.repositoryEvent";
-
-    String REPOSITORY_EVENT_EVENT_TYPE = "Type";
-
-    String REPOSITORY_EVENT_EVENT_TYPE_ADDED = "Added";
-
-    String REPOSITORY_EVENT_EVENT_TYPE_REMOVED = "Removed";
-
-    /**
-     * The item names in the CompositeData representing a feature
-     */
-    String[] REPOSITORY = { REPOSITORY_NAME, REPOSITORY_URI,  REPOSITORY_REPOSITORIES, REPOSITORY_FEATURES };
-
-    /**
-     * The item names in the CompositeData representing the event raised for
-     * feature events within the OSGi container by this bean
-     */
-    String[] REPOSITORY_EVENT = { REPOSITORY_URI, REPOSITORY_EVENT_EVENT_TYPE };
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/core/src/main/java/org/apache/karaf/features/management/codec/JmxFeature.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/management/codec/JmxFeature.java b/features/core/src/main/java/org/apache/karaf/features/management/codec/JmxFeature.java
deleted file mode 100644
index 54fa3c0..0000000
--- a/features/core/src/main/java/org/apache/karaf/features/management/codec/JmxFeature.java
+++ /dev/null
@@ -1,323 +0,0 @@
-/*
- * 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.karaf.features.management.codec;
-
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import javax.management.openmbean.TabularData;
-import javax.management.openmbean.TabularType;
-import javax.management.openmbean.OpenDataException;
-import javax.management.openmbean.CompositeType;
-import javax.management.openmbean.OpenType;
-import javax.management.openmbean.SimpleType;
-import javax.management.openmbean.ArrayType;
-import javax.management.openmbean.CompositeData;
-import javax.management.openmbean.CompositeDataSupport;
-import javax.management.openmbean.TabularDataSupport;
-
-import org.apache.karaf.features.BundleInfo;
-import org.apache.karaf.features.ConfigFileInfo;
-import org.apache.karaf.features.Dependency;
-import org.apache.karaf.features.Feature;
-import org.apache.karaf.features.management.FeaturesServiceMBean;
-
-public class JmxFeature {
-
-    /**
-     * The CompositeType which represents a single feature
-     */
-    public final static CompositeType FEATURE;
-
-    /**
-     * The TabularType which represents a list of features
-     */
-    public final static TabularType FEATURE_TABLE;
-
-    public final static CompositeType FEATURE_IDENTIFIER;
-
-    public final static TabularType FEATURE_IDENTIFIER_TABLE;
-
-    public final static CompositeType FEATURE_CONFIG_ELEMENT;
-
-    public final static TabularType FEATURE_CONFIG_ELEMENT_TABLE;
-
-    public final static CompositeType FEATURE_CONFIG;
-
-    public final static TabularType FEATURE_CONFIG_TABLE;
-
-    public final static CompositeType FEATURE_CONFIG_FILES;
-    
-    public final static TabularType FEATURE_CONFIG_FILES_TABLE;
-    
-    private final CompositeData data;
-
-    public JmxFeature(Feature feature, boolean installed) {
-        try {
-            String[] itemNames = FeaturesServiceMBean.FEATURE;
-            Object[] itemValues = new Object[itemNames.length];
-            itemValues[0] = feature.getName();
-            itemValues[1] = feature.getVersion();
-            itemValues[2] = getDependencyIdentifierTable(feature.getDependencies());
-            itemValues[3] = getBundleUris(feature.getBundles());
-            itemValues[4] = getConfigTable(feature.getConfigurations());
-            itemValues[5] = getConfigFileList(feature.getConfigurationFiles());
-            itemValues[6] = installed;
-            data = new CompositeDataSupport(FEATURE, itemNames, itemValues);
-        } catch (OpenDataException e) {
-            throw new IllegalStateException("Cannot form feature open data", e);
-        }
-    }
-
-    public CompositeData asCompositeData() {
-        return data;
-    }
-
-    public static TabularData tableFrom(Collection<JmxFeature> features) {
-        TabularDataSupport table = new TabularDataSupport(FEATURE_TABLE);
-        for (JmxFeature feature : features) {
-            table.put(feature.asCompositeData());
-        }
-        return table;
-    }
-
-     private static TabularData getDependencyIdentifierTable(List<Dependency> features) throws OpenDataException {
-        TabularDataSupport table = new TabularDataSupport(FEATURE_IDENTIFIER_TABLE);
-        Set<String> featureSet = new HashSet<String>();
-        for (Dependency feature : features) {
-            if (featureSet.contains(feature.getName() + feature.getVersion())) {
-                continue;
-            } else {
-                featureSet.add(feature.getName() + feature.getVersion());
-            }
-            String[] itemNames = new String[] { FeaturesServiceMBean.FEATURE_NAME, FeaturesServiceMBean.FEATURE_VERSION };
-            Object[] itemValues = new Object[] { feature.getName(), feature.getVersion() };
-            CompositeData ident = new CompositeDataSupport(FEATURE_IDENTIFIER, itemNames, itemValues);
-            table.put(ident);
-        }
-        return table;
-    }
-
-    static String[] getBundleUris(List<BundleInfo> infos) {
-        String[] array = new String[infos.size()];
-        for (int i = 0; i < array.length; i++) {
-            array[i] = infos.get(i).getLocation();
-        }
-        return array;
-    }
-
-    static TabularData getConfigTable(Map<String, Map<String, String>> configs) throws OpenDataException {
-        TabularDataSupport table = new TabularDataSupport(FEATURE_CONFIG_TABLE);
-        for (Map.Entry<String, Map<String, String>> entry : configs.entrySet()) {
-            String[] itemNames = FeaturesServiceMBean.FEATURE_CONFIG;
-            Object[] itemValues = new Object[2];
-            itemValues[0] = entry.getKey();
-            itemValues[1] = getConfigElementTable(entry.getValue());
-            CompositeData config = new CompositeDataSupport(FEATURE_CONFIG, itemNames, itemValues);
-            table.put(config);
-        }
-        return table;
-    }
-    
-    static TabularData getConfigFileList(List<ConfigFileInfo> configFiles) throws OpenDataException {
-        TabularDataSupport table = new TabularDataSupport(FEATURE_CONFIG_FILES_TABLE);
-        for (ConfigFileInfo configFile : configFiles) {
-            String[] itemNames = FeaturesServiceMBean.FEATURE_CONFIG_FILES;
-            Object[] itemValues = { configFile.getFinalname() };
-            CompositeData config = new CompositeDataSupport(FEATURE_CONFIG_FILES, itemNames, itemValues);
-            table.put(config);
-        }
-        return table;
-    }
-
-    static TabularData getConfigElementTable(Map<String, String> config) throws OpenDataException {
-        TabularDataSupport table = new TabularDataSupport(FEATURE_CONFIG_ELEMENT_TABLE);
-        for (Map.Entry<String, String> entry : config.entrySet()) {
-            String[] itemNames = FeaturesServiceMBean.FEATURE_CONFIG_ELEMENT;
-            Object[] itemValues = { entry.getKey(), entry.getValue() };
-            CompositeData element = new CompositeDataSupport(FEATURE_CONFIG_ELEMENT, itemNames, itemValues);
-            table.put(element);
-        }
-        return table;
-    }
-
-
-    static {
-        FEATURE_IDENTIFIER = createFeatureIdentifierType();
-        FEATURE_IDENTIFIER_TABLE = createFeatureIdentifierTableType();
-        FEATURE_CONFIG_ELEMENT = createFeatureConfigElementType();
-        FEATURE_CONFIG_ELEMENT_TABLE = createFeatureConfigElementTableType();
-        FEATURE_CONFIG = createFeatureConfigType();
-        FEATURE_CONFIG_TABLE = createFeatureConfigTableType();
-        FEATURE_CONFIG_FILES =  createFeatureConfigFilesType();
-        FEATURE_CONFIG_FILES_TABLE = createFeatureConfigFilesTableType();
-        FEATURE = createFeatureType();
-        FEATURE_TABLE = createFeatureTableType();
-    }
-
-    private static CompositeType createFeatureIdentifierType() {
-        try {
-            String description = "This type identify a Karaf features";
-            String[] itemNames = FeaturesServiceMBean.FEATURE_IDENTIFIER;
-            OpenType[] itemTypes = new OpenType[itemNames.length];
-            String[] itemDescriptions = new String[itemNames.length];
-            itemTypes[0] = SimpleType.STRING;
-            itemTypes[1] = SimpleType.STRING;
-
-            itemDescriptions[0] = "The id of the feature";
-            itemDescriptions[1] = "The version of the feature";
-
-            return new CompositeType("FeatureIdentifier", description, itemNames,
-                    itemDescriptions, itemTypes);
-        } catch (OpenDataException e) {
-            throw new IllegalStateException("Unable to build featureIdentifier type", e);
-        }
-    }
-
-    private static TabularType createFeatureIdentifierTableType() {
-        try {
-            return new TabularType("Features", "The table of featureIdentifiers",
-                    FEATURE_IDENTIFIER, new String[] { FeaturesServiceMBean.FEATURE_NAME, FeaturesServiceMBean.FEATURE_VERSION });
-        } catch (OpenDataException e) {
-            throw new IllegalStateException("Unable to build featureIdentifier table type", e);
-        }
-    }
-
-    private static CompositeType createFeatureConfigElementType() {
-        try {
-            String description = "This type encapsulates Karaf feature config element";
-            String[] itemNames = FeaturesServiceMBean.FEATURE_CONFIG_ELEMENT;
-            OpenType[] itemTypes = new OpenType[itemNames.length];
-            String[] itemDescriptions = new String[itemNames.length];
-            itemTypes[0] = SimpleType.STRING;
-            itemTypes[1] = SimpleType.STRING;
-
-            itemDescriptions[0] = "The key";
-            itemDescriptions[1] = "The value";
-
-            return new CompositeType("ConfigElement", description, itemNames,
-                    itemDescriptions, itemTypes);
-        } catch (OpenDataException e) {
-            throw new IllegalStateException("Unable to build configElement type", e);
-        }
-    }
-
-    private static TabularType createFeatureConfigElementTableType() {
-        try {
-            return new TabularType("ConfigElement", "The table of configurations elements",
-                    FEATURE_CONFIG_ELEMENT, new String[] { FeaturesServiceMBean.FEATURE_CONFIG_ELEMENT_KEY});
-        } catch (OpenDataException e) {
-            throw new IllegalStateException("Unable to build feature table type", e);
-        }
-    }
-
-    private static CompositeType createFeatureConfigType() {
-        try {
-            String description = "This type encapsulates Karaf feature config";
-            String[] itemNames = FeaturesServiceMBean.FEATURE_CONFIG;
-            OpenType[] itemTypes = new OpenType[itemNames.length];
-            String[] itemDescriptions = new String[itemNames.length];
-            itemTypes[0] = SimpleType.STRING;
-            itemTypes[1] = FEATURE_CONFIG_ELEMENT_TABLE;
-
-            itemDescriptions[0] = "The PID of the config";
-            itemDescriptions[1] = "The configuration elements";
-
-            return new CompositeType("Config", description, itemNames,
-                    itemDescriptions, itemTypes);
-        } catch (OpenDataException e) {
-            throw new IllegalStateException("Unable to build configElement type", e);
-        }
-    }
-    
-    private static CompositeType createFeatureConfigFilesType() {
-        try {
-            String description = "This type encapsulates Karaf feature config files";
-            String[] itemNames = FeaturesServiceMBean.FEATURE_CONFIG_FILES;
-            OpenType[] itemTypes = new OpenType[itemNames.length];
-            String[] itemDescriptions = new String[itemNames.length];
-            itemTypes[0] = SimpleType.STRING;
-
-            itemDescriptions[0] = "The configuration file";
-
-            return new CompositeType("Config", description, itemNames,
-                    itemDescriptions, itemTypes);
-        } catch (OpenDataException e) {
-            throw new IllegalStateException("Unable to build configElement type", e);
-        }
-    }
-
-    private static TabularType createFeatureConfigTableType() {
-        try {
-            return new TabularType("Features", "The table of configurations",
-                    FEATURE_CONFIG, new String[] { FeaturesServiceMBean.FEATURE_CONFIG_PID});
-        } catch (OpenDataException e) {
-            throw new IllegalStateException("Unable to build feature table type", e);
-        }
-    }
-    
-    private static TabularType createFeatureConfigFilesTableType() {
-        try {
-            return new TabularType("Features", "The table of configuration files",
-            		FEATURE_CONFIG_FILES, new String[] { FeaturesServiceMBean.FEATURE_CONFIG_FILES_ELEMENTS });
-        } catch (OpenDataException e) {
-            throw new IllegalStateException("Unable to build feature table type", e);
-        }
-    }
-
-    private static CompositeType createFeatureType() {
-        try {
-            String description = "This type encapsulates Karaf features";
-            String[] itemNames = FeaturesServiceMBean.FEATURE;
-            OpenType[] itemTypes = new OpenType[itemNames.length];
-            String[] itemDescriptions = new String[itemNames.length];
-            itemTypes[0] = SimpleType.STRING;
-            itemTypes[1] = SimpleType.STRING;
-            itemTypes[2] = FEATURE_IDENTIFIER_TABLE;
-            itemTypes[3] = new ArrayType(1, SimpleType.STRING);
-            itemTypes[4] = FEATURE_CONFIG_TABLE;
-            itemTypes[5] = FEATURE_CONFIG_FILES_TABLE;
-            itemTypes[6] = SimpleType.BOOLEAN;
-
-            itemDescriptions[0] = "The name of the feature";
-            itemDescriptions[1] = "The version of the feature";
-            itemDescriptions[2] = "The feature dependencies";
-            itemDescriptions[3] = "The feature bundles";
-            itemDescriptions[4] = "The feature configurations";
-            itemDescriptions[5] = "The feature configuration files";
-            itemDescriptions[6] = "Whether the feature is installed";
-
-            return new CompositeType("Feature", description, itemNames,
-                    itemDescriptions, itemTypes);
-        } catch (OpenDataException e) {
-            throw new IllegalStateException("Unable to build feature type", e);
-        }
-    }
-
-    private static TabularType createFeatureTableType() {
-        try {
-            return new TabularType("Features", "The table of all features",
-                    FEATURE, new String[] { FeaturesServiceMBean.FEATURE_NAME, FeaturesServiceMBean.FEATURE_VERSION });
-        } catch (OpenDataException e) {
-            throw new IllegalStateException("Unable to build feature table type", e);
-        }
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/core/src/main/java/org/apache/karaf/features/management/codec/JmxFeatureEvent.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/management/codec/JmxFeatureEvent.java b/features/core/src/main/java/org/apache/karaf/features/management/codec/JmxFeatureEvent.java
deleted file mode 100644
index 81f446b..0000000
--- a/features/core/src/main/java/org/apache/karaf/features/management/codec/JmxFeatureEvent.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * 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.karaf.features.management.codec;
-
-import javax.management.openmbean.CompositeData;
-import javax.management.openmbean.CompositeDataSupport;
-import javax.management.openmbean.OpenDataException;
-import javax.management.openmbean.CompositeType;
-import javax.management.openmbean.OpenType;
-import javax.management.openmbean.SimpleType;
-
-import org.apache.karaf.features.FeatureEvent;
-import org.apache.karaf.features.management.FeaturesServiceMBean;
-
-public class JmxFeatureEvent {
-
-    public static final CompositeType FEATURE_EVENT;
-
-    private final CompositeData data;
-
-    public JmxFeatureEvent(FeatureEvent event) {
-        try {
-            String[] itemNames = FeaturesServiceMBean.FEATURE_EVENT;
-            Object[] itemValues = new Object[itemNames.length];
-            itemValues[0] = event.getFeature().getName();
-            itemValues[1] = event.getFeature().getVersion();
-            switch (event.getType()) {
-                case FeatureInstalled:   itemValues[2] = FeaturesServiceMBean.FEATURE_EVENT_EVENT_TYPE_INSTALLED; break;
-                case FeatureUninstalled: itemValues[2] = FeaturesServiceMBean.FEATURE_EVENT_EVENT_TYPE_UNINSTALLED; break;
-                default: throw new IllegalStateException("Unsupported event type: " + event.getType());
-            }
-            data = new CompositeDataSupport(FEATURE_EVENT, itemNames, itemValues);
-        } catch (OpenDataException e) {
-            throw new IllegalStateException("Cannot form feature event open data", e);
-        }
-    }
-
-    public CompositeData asCompositeData() {
-        return data;
-    }
-
-    static {
-        FEATURE_EVENT = createFeatureEventType();
-    }
-
-    private static CompositeType createFeatureEventType() {
-        try {
-            String description = "This type identify a Karaf feature event";
-            String[] itemNames = FeaturesServiceMBean.FEATURE_EVENT;
-            OpenType[] itemTypes = new OpenType[itemNames.length];
-            String[] itemDescriptions = new String[itemNames.length];
-            itemTypes[0] = SimpleType.STRING;
-            itemTypes[1] = SimpleType.STRING;
-            itemTypes[2] = SimpleType.STRING;
-
-            itemDescriptions[0] = "The id of the feature";
-            itemDescriptions[1] = "The version of the feature";
-            itemDescriptions[2] = "The type of the event";
-
-            return new CompositeType("FeatureEvent", description, itemNames,
-                    itemDescriptions, itemTypes);
-        } catch (OpenDataException e) {
-            throw new IllegalStateException("Unable to build featureEvent type", e);
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/core/src/main/java/org/apache/karaf/features/management/codec/JmxRepository.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/management/codec/JmxRepository.java b/features/core/src/main/java/org/apache/karaf/features/management/codec/JmxRepository.java
deleted file mode 100644
index fee1ab2..0000000
--- a/features/core/src/main/java/org/apache/karaf/features/management/codec/JmxRepository.java
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * 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.karaf.features.management.codec;
-
-import java.util.Collection;
-import java.util.Arrays;
-import java.net.URI;
-import java.util.List;
-
-import javax.management.openmbean.TabularData;
-import javax.management.openmbean.CompositeType;
-import javax.management.openmbean.TabularType;
-import javax.management.openmbean.OpenType;
-import javax.management.openmbean.SimpleType;
-import javax.management.openmbean.OpenDataException;
-import javax.management.openmbean.ArrayType;
-import javax.management.openmbean.CompositeData;
-import javax.management.openmbean.TabularDataSupport;
-import javax.management.openmbean.CompositeDataSupport;
-
-import org.apache.karaf.features.Feature;
-import org.apache.karaf.features.Repository;
-import org.apache.karaf.features.management.FeaturesServiceMBean;
-
-public class JmxRepository {
-
-    public final static CompositeType REPOSITORY;
-
-    public final static TabularType REPOSITORY_TABLE;
-
-    private final CompositeData data;
-
-    public JmxRepository(Repository repository) {
-        try {
-            String[] itemNames = FeaturesServiceMBean.REPOSITORY;
-            Object[] itemValues = new Object[itemNames.length];
-            itemValues[0] = repository.getName();
-            itemValues[1] = repository.getURI().toString();
-            itemValues[2] = toStringArray(repository.getRepositories());
-            itemValues[3] = getFeatureIdentifierTable(Arrays.asList(repository.getFeatures()));
-            data = new CompositeDataSupport(REPOSITORY, itemNames, itemValues);
-        } catch (Exception e) {
-            throw new IllegalStateException("Cannot form repository open data", e);
-        }
-    }
-
-    public CompositeData asCompositeData() {
-        return data;
-    }
-
-    public static TabularData tableFrom(Collection<JmxRepository> repositories) {
-        TabularDataSupport table = new TabularDataSupport(REPOSITORY_TABLE);
-        for (JmxRepository repository : repositories) {
-            table.put(repository.asCompositeData());
-        }
-        return table;
-    }
-
-    private static String[] toStringArray(URI[] uris) {
-        if (uris == null) {
-            return null;
-        }
-        String[] res = new String[uris.length];
-        for (int i = 0; i < res.length; i++) {
-            res[i] = uris[i].toString();
-        }
-        return res;
-    }
-
-    static TabularData getFeatureIdentifierTable(List<Feature> features) throws OpenDataException {
-        TabularDataSupport table = new TabularDataSupport(JmxFeature.FEATURE_IDENTIFIER_TABLE);
-        for (Feature feature : features) {
-            String[] itemNames = new String[] { FeaturesServiceMBean.FEATURE_NAME, FeaturesServiceMBean.FEATURE_VERSION };
-            Object[] itemValues = new Object[] { feature.getName(), feature.getVersion() };
-            CompositeData ident = new CompositeDataSupport(JmxFeature.FEATURE_IDENTIFIER, itemNames, itemValues);
-            table.put(ident);
-        }
-        return table;
-    }
-
-    static {
-        REPOSITORY = createRepositoryType();
-        REPOSITORY_TABLE = createRepositoryTableType();
-    }
-
-    private static CompositeType createRepositoryType() {
-        try {
-            String description = "This type identify a Karaf repository";
-            String[] itemNames = FeaturesServiceMBean.REPOSITORY;
-            OpenType[] itemTypes = new OpenType[itemNames.length];
-            String[] itemDescriptions = new String[itemNames.length];
-            itemTypes[0] = SimpleType.STRING;
-            itemTypes[1] = SimpleType.STRING;
-            itemTypes[2] = new ArrayType(1, SimpleType.STRING);
-            itemTypes[3] = JmxFeature.FEATURE_IDENTIFIER_TABLE;
-
-            itemDescriptions[0] = "The name of the repository";
-            itemDescriptions[1] = "The uri of the repository";
-            itemDescriptions[2] = "The dependent repositories";
-            itemDescriptions[3] = "The list of included features";
-
-            return new CompositeType("Repository", description, itemNames,
-                    itemDescriptions, itemTypes);
-        } catch (OpenDataException e) {
-            throw new IllegalStateException("Unable to build repository type", e);
-        }
-    }
-
-    private static TabularType createRepositoryTableType() {
-        try {
-            return new TabularType("Features", "The table of repositories",
-                    REPOSITORY, new String[] { FeaturesServiceMBean.REPOSITORY_URI });
-        } catch (OpenDataException e) {
-            throw new IllegalStateException("Unable to build repository table type", e);
-        }
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/core/src/main/java/org/apache/karaf/features/management/codec/JmxRepositoryEvent.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/management/codec/JmxRepositoryEvent.java b/features/core/src/main/java/org/apache/karaf/features/management/codec/JmxRepositoryEvent.java
deleted file mode 100644
index e00e85d..0000000
--- a/features/core/src/main/java/org/apache/karaf/features/management/codec/JmxRepositoryEvent.java
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * 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.karaf.features.management.codec;
-
-import javax.management.openmbean.CompositeData;
-import javax.management.openmbean.CompositeType;
-import javax.management.openmbean.CompositeDataSupport;
-import javax.management.openmbean.OpenDataException;
-import javax.management.openmbean.OpenType;
-import javax.management.openmbean.SimpleType;
-
-import org.apache.karaf.features.RepositoryEvent;
-import org.apache.karaf.features.management.FeaturesServiceMBean;
-
-public class JmxRepositoryEvent {
-
-    public static final CompositeType REPOSITORY_EVENT;
-
-    private final CompositeData data;
-
-    public JmxRepositoryEvent(RepositoryEvent event) {
-        try {
-            String[] itemNames = FeaturesServiceMBean.REPOSITORY_EVENT;
-            Object[] itemValues = new Object[itemNames.length];
-            itemValues[0] = event.getRepository().getURI().toString();
-            switch (event.getType()) {
-                case RepositoryAdded:   itemValues[1] = FeaturesServiceMBean.REPOSITORY_EVENT_EVENT_TYPE_ADDED; break;
-                case RepositoryRemoved: itemValues[1] = FeaturesServiceMBean.REPOSITORY_EVENT_EVENT_TYPE_REMOVED; break;
-                default: throw new IllegalStateException("Unsupported event type: " + event.getType());
-            }
-            data = new CompositeDataSupport(REPOSITORY_EVENT, itemNames, itemValues);
-        } catch (OpenDataException e) {
-            throw new IllegalStateException("Cannot form repository event open data", e);
-        }
-    }
-
-    public CompositeData asCompositeData() {
-        return data;
-    }
-
-    static {
-        REPOSITORY_EVENT = createRepositoryEventType();
-    }
-
-    private static CompositeType createRepositoryEventType() {
-        try {
-            String description = "This type identify a Karaf repository event";
-            String[] itemNames = FeaturesServiceMBean.REPOSITORY_EVENT;
-            OpenType[] itemTypes = new OpenType[itemNames.length];
-            String[] itemDescriptions = new String[itemNames.length];
-            itemTypes[0] = SimpleType.STRING;
-            itemTypes[1] = SimpleType.STRING;
-
-            itemDescriptions[0] = "The uri of the repository";
-            itemDescriptions[1] = "The type of event";
-
-            return new CompositeType("RepositoryEvent", description, itemNames,
-                    itemDescriptions, itemTypes);
-        } catch (OpenDataException e) {
-            throw new IllegalStateException("Unable to build repositoryEvent type", e);
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/core/src/main/resources/OSGI-INF/bundle.info
----------------------------------------------------------------------
diff --git a/features/core/src/main/resources/OSGI-INF/bundle.info b/features/core/src/main/resources/OSGI-INF/bundle.info
deleted file mode 100644
index d5b4180..0000000
--- a/features/core/src/main/resources/OSGI-INF/bundle.info
+++ /dev/null
@@ -1,20 +0,0 @@
-h1. Synopsis
-
-${project.name}
-
-${project.description}
-
-Maven URL:
-[mvn:${project.groupId}/${project.artifactId}/${project.version}]
-
-h1. Description
-
-This bundle is the core implementation of the Karaf features support.
-
-Karaf provides a simple, yet flexible, way to provision applications or "features". Such a mechanism is mainly
-provided by a set of commands available in the features shell. The provisioning system uses xml "repositories"
-that define a set of features.
-
-h1. See also
-
-Provisioning - section of the Karaf User Guide


[47/59] [abbrv] [KARAF-2852] Merge wrapper/core and wrapper/command

Posted by gn...@apache.org.
http://git-wip-us.apache.org/repos/asf/karaf/blob/4182735c/wrapper/src/main/java/org/apache/karaf/wrapper/internal/PumpStreamHandler.java
----------------------------------------------------------------------
diff --git a/wrapper/src/main/java/org/apache/karaf/wrapper/internal/PumpStreamHandler.java b/wrapper/src/main/java/org/apache/karaf/wrapper/internal/PumpStreamHandler.java
new file mode 100644
index 0000000..8737547
--- /dev/null
+++ b/wrapper/src/main/java/org/apache/karaf/wrapper/internal/PumpStreamHandler.java
@@ -0,0 +1,246 @@
+/*
+ * 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.karaf.wrapper.internal;
+
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.IOException;
+
+//
+// Based on Apache Ant 1.6.5
+//
+
+/**
+ * Copies standard output and error of children streams to standard output and error of the parent.
+ */
+public class PumpStreamHandler {
+
+    private final InputStream in;
+
+    private final OutputStream out;
+
+    private final OutputStream err;
+
+    private final String name;
+
+    private StreamPumper outputPump;
+
+    private StreamPumper errorPump;
+
+    private StreamPumper inputPump;
+
+    //
+    // NOTE: May want to use a ThreadPool here, 3 threads per/pair seems kinda expensive :-(
+    //
+
+    public PumpStreamHandler(final InputStream in, final OutputStream out, final OutputStream err, String name) {
+        assert in != null;
+        assert out != null;
+        assert err != null;
+        assert name != null;
+
+        this.in = in;
+        this.out = out;
+        this.err = err;
+        this.name = name;
+    }
+
+    public PumpStreamHandler(final InputStream in, final OutputStream out, final OutputStream err) {
+        this(in, out, err, "<unknown>");
+    }
+
+    public PumpStreamHandler(final OutputStream out, final OutputStream err) {
+        this(null, out, err);
+    }
+
+    public PumpStreamHandler(final OutputStream outAndErr) {
+        this(outAndErr, outAndErr);
+    }
+
+    /**
+     * Set the input stream from which to read the standard output of the child.
+     */
+    public void setChildOutputStream(final InputStream in) {
+        assert in != null;
+
+        createChildOutputPump(in, out);
+    }
+
+    /**
+     * Set the input stream from which to read the standard error of the child.
+     */
+    public void setChildErrorStream(final InputStream in) {
+        assert in != null;
+
+        if (err != null) {
+            createChildErrorPump(in, err);
+        }
+    }
+
+    /**
+     * Set the output stream by means of which input can be sent to the child.
+     */
+    public void setChildInputStream(final OutputStream out) {
+        assert out != null;
+
+        if (in != null) {
+            inputPump = createInputPump(in, out, true);
+        } else {
+            try {
+                out.close();
+            } catch (IOException e) {
+            }
+        }
+    }
+
+    /**
+     * Attach to a child streams from the given process.
+     *
+     * @param p The process to attach to.
+     */
+    public void attach(final Process p) {
+        assert p != null;
+
+        setChildInputStream(p.getOutputStream());
+        setChildOutputStream(p.getInputStream());
+        setChildErrorStream(p.getErrorStream());
+    }
+
+    /**
+     * Start pumping the streams.
+     */
+    public void start() {
+        if (outputPump != null) {
+            Thread thread = new Thread(outputPump);
+            thread.setDaemon(true);
+            thread.setName("Output pump for " + this.name);
+            thread.start();
+        }
+
+        if (errorPump != null) {
+            Thread thread = new Thread(errorPump);
+            thread.setDaemon(true);
+            thread.setName("Error pump for " + this.name);
+            thread.start();
+        }
+
+        if (inputPump != null) {
+            Thread thread = new Thread(inputPump);
+            thread.setDaemon(true);
+            thread.setName("Input pump for " + this.name);
+            thread.start();
+        }
+    }
+
+    /**
+     * Stop pumping the streams.
+     */
+    public void stop() {
+        if (outputPump != null) {
+            try {
+                outputPump.stop();
+                outputPump.waitFor();
+            } catch (InterruptedException e) {
+                // ignore
+            }
+        }
+
+        if (errorPump != null) {
+            try {
+                errorPump.stop();
+                errorPump.waitFor();
+            } catch (InterruptedException e) {
+                // ignore
+            }
+        }
+
+        if (inputPump != null) {
+            inputPump.stop();
+        }
+
+        try {
+            err.flush();
+        } catch (IOException e) {
+        }
+        try {
+            out.flush();
+        } catch (IOException e) {
+        }
+    }
+
+    /**
+     * Create the pump to handle child output.
+     */
+    protected void createChildOutputPump(final InputStream in, final OutputStream out) {
+        assert in != null;
+        assert out != null;
+
+        outputPump = createPump(in, out);
+    }
+
+    /**
+     * Create the pump to handle error output.
+     */
+    protected void createChildErrorPump(final InputStream in, final OutputStream out) {
+        assert in != null;
+        assert out != null;
+
+        errorPump = createPump(in, out);
+    }
+
+    /**
+     * Creates a stream pumper to copy the given input stream to the given output stream.
+     */
+    protected StreamPumper createPump(final InputStream in, final OutputStream out) {
+        assert in != null;
+        assert out != null;
+
+        return createPump(in, out, false);
+    }
+
+    /**
+     * Creates a stream pumper to copy the given input stream to the
+     * given output stream.
+     *
+     * @param in                 The input stream to copy from.
+     * @param out                The output stream to copy to.
+     * @param closeWhenExhausted If true close the inputstream.
+     * @return A thread object that does the pumping.
+     */
+    protected StreamPumper createPump(final InputStream in, final OutputStream out, final boolean closeWhenExhausted) {
+        assert in != null;
+        assert out != null;
+
+        StreamPumper pumper = new StreamPumper(in, out, closeWhenExhausted);
+        return pumper;
+    }
+
+    /**
+     * Creates a stream pumper to copy the given input stream to the
+     * given output stream. Used for standard input.
+     */
+    protected StreamPumper createInputPump(final InputStream in, final OutputStream out, final boolean closeWhenExhausted) {
+        assert in != null;
+        assert out != null;
+
+        StreamPumper pumper = new StreamPumper(in, out, closeWhenExhausted);
+        pumper.setAutoflush(true);
+        return pumper;
+    }
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/4182735c/wrapper/src/main/java/org/apache/karaf/wrapper/internal/StreamPumper.java
----------------------------------------------------------------------
diff --git a/wrapper/src/main/java/org/apache/karaf/wrapper/internal/StreamPumper.java b/wrapper/src/main/java/org/apache/karaf/wrapper/internal/StreamPumper.java
new file mode 100644
index 0000000..330d8fc
--- /dev/null
+++ b/wrapper/src/main/java/org/apache/karaf/wrapper/internal/StreamPumper.java
@@ -0,0 +1,195 @@
+/*
+ * 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.karaf.wrapper.internal;
+
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.IOException;
+
+//
+// Based on Apache Ant 1.6.5
+//
+
+/**
+ * Copies all data from an input stream to an output stream.
+ */
+public class StreamPumper implements Runnable {
+
+    private InputStream in;
+
+    private OutputStream out;
+
+    private volatile boolean finish;
+
+    private volatile boolean finished;
+
+    private boolean closeWhenExhausted;
+
+    private boolean autoflush;
+
+    private Exception exception;
+
+    private int bufferSize = 128;
+
+    private boolean started;
+
+    /**
+     * Create a new stream pumper.
+     *
+     * @param in                 Input stream to read data from
+     * @param out                Output stream to write data to.
+     * @param closeWhenExhausted If true, the output stream will be closed when
+     *                           the input is exhausted.
+     */
+    public StreamPumper(final InputStream in, final OutputStream out, final boolean closeWhenExhausted) {
+        assert in != null;
+        assert out != null;
+
+        this.in = in;
+        this.out = out;
+        this.closeWhenExhausted = closeWhenExhausted;
+    }
+
+    /**
+     * Create a new stream pumper.
+     *
+     * @param in  Input stream to read data from
+     * @param out Output stream to write data to.
+     */
+    public StreamPumper(final InputStream in, final OutputStream out) {
+        this(in, out, false);
+    }
+
+    /**
+     * Set whether data should be flushed through to the output stream.
+     *
+     * @param autoflush If true, push through data; if false, let it be buffered
+     */
+    public void setAutoflush(boolean autoflush) {
+        this.autoflush = autoflush;
+    }
+
+    /**
+     * Copies data from the input stream to the output stream.
+     * <p/>
+     * Terminates as soon as the input stream is closed or an error occurs.
+     */
+    public void run() {
+        synchronized (this) {
+            started = true;
+        }
+        finished = false;
+        finish = false;
+
+        final byte[] buf = new byte[bufferSize];
+
+        int length;
+        try {
+            while ((length = in.read(buf)) > 0 && !finish) {
+                out.write(buf, 0, length);
+                if (autoflush) {
+                    out.flush();
+                }
+            }
+            out.flush();
+        } catch (Exception e) {
+            synchronized (this) {
+                exception = e;
+            }
+        } finally {
+            if (closeWhenExhausted) {
+                try {
+                    out.close();
+                } catch (IOException e) {
+                }
+            }
+            finished = true;
+
+            synchronized (this) {
+                notifyAll();
+            }
+        }
+    }
+
+    /**
+     * Tells whether the end of the stream has been reached.
+     *
+     * @return true     If the stream has been exhausted.
+     */
+    public boolean isFinished() {
+        return finished;
+    }
+
+    /**
+     * This method blocks until the stream pumper finishes.
+     *
+     * @see #isFinished()
+     */
+    public synchronized void waitFor() throws InterruptedException {
+        while (!isFinished()) {
+            wait();
+        }
+    }
+
+    /**
+     * Set the size in bytes of the read buffer.
+     *
+     * @param bufferSize the buffer size to use.
+     * @throws IllegalStateException if the StreamPumper is already running.
+     */
+    public synchronized void setBufferSize(final int bufferSize) {
+        if (started) {
+            throw new IllegalStateException("Cannot set buffer size on a running StreamPumper");
+        }
+
+        this.bufferSize = bufferSize;
+    }
+
+    /**
+     * Get the size in bytes of the read buffer.
+     *
+     * @return The size of the read buffer.
+     */
+    public synchronized int getBufferSize() {
+        return bufferSize;
+    }
+
+    /**
+     * Get the exception encountered, if any.
+     *
+     * @return The Exception encountered; or null if there was none.
+     */
+    public synchronized Exception getException() {
+        return exception;
+    }
+
+    /**
+     * Stop the pumper as soon as possible.
+     * <p/>
+     * Note that it may continue to block on the input stream
+     * but it will really stop the thread as soon as it gets EOF
+     * or any byte, and it will be marked as finished.
+     */
+    public synchronized void stop() {
+        finish = true;
+
+        notifyAll();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/4182735c/wrapper/src/main/java/org/apache/karaf/wrapper/internal/WrapperServiceImpl.java
----------------------------------------------------------------------
diff --git a/wrapper/src/main/java/org/apache/karaf/wrapper/internal/WrapperServiceImpl.java b/wrapper/src/main/java/org/apache/karaf/wrapper/internal/WrapperServiceImpl.java
new file mode 100644
index 0000000..ad4aa4a
--- /dev/null
+++ b/wrapper/src/main/java/org/apache/karaf/wrapper/internal/WrapperServiceImpl.java
@@ -0,0 +1,450 @@
+/*
+ * 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.karaf.wrapper.internal;
+
+import org.apache.karaf.wrapper.WrapperService;
+import org.fusesource.jansi.Ansi;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.*;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Scanner;
+import java.util.jar.JarOutputStream;
+import java.util.zip.ZipEntry;
+
+/**
+ * Default implementation of the wrapper service.
+ */
+public class WrapperServiceImpl implements WrapperService {
+
+    private final static Logger LOGGER = LoggerFactory.getLogger(WrapperServiceImpl.class);
+
+    public void install() throws Exception {
+        install("karaf", "karaf", "", "AUTO_START");
+    }
+
+    public File[] install(String name, String displayName, String description, String startType) throws Exception {
+
+        File base = new File(System.getProperty("karaf.base"));
+        File etc = new File(System.getProperty("karaf.etc"));
+        File bin = new File(base, "bin");
+        File lib = new File(base, "lib");
+
+        if (name == null) {
+            name = base.getName();
+        }
+
+        HashMap<String, String> props = new HashMap<String, String>();
+        props.put("${java.home}", System.getenv("JAVA_HOME"));
+        props.put("${karaf.home}", System.getProperty("karaf.home"));
+        props.put("${karaf.base}", base.getPath());
+        props.put("${karaf.data}", System.getProperty("karaf.data"));
+        props.put("${karaf.etc}", System.getProperty("karaf.etc"));
+        props.put("${name}", name);
+        props.put("${displayName}", displayName);
+        props.put("${description}", description);
+        props.put("${startType}", startType);
+
+        String os = System.getProperty("os.name", "Unknown");
+        File serviceFile = null;
+        File wrapperConf = null;
+        if (os.startsWith("Win")) {
+            String arch = System.getProperty("os.arch");
+            if (arch.equalsIgnoreCase("amd64") || arch.equalsIgnoreCase("x86_64")) {
+                mkdir(bin);
+
+                copyResourceTo(new File(bin, name + "-wrapper.exe"), "windows64/karaf-wrapper.exe", false);
+
+                serviceFile = new File(bin, name + "-service.bat");
+                wrapperConf = new File(etc, name + "-wrapper.conf");
+
+                copyFilteredResourceTo(wrapperConf, "windows64/karaf-wrapper.conf", props);
+                copyFilteredResourceTo(serviceFile, "windows64/karaf-service.bat", props);
+
+                mkdir(lib);
+                copyResourceTo(new File(lib, "wrapper.dll"), "windows64/wrapper.dll", false);
+            } else {
+                mkdir(bin);
+
+                copyResourceTo(new File(bin, name + "-wrapper.exe"), "windows/karaf-wrapper.exe", false);
+
+                serviceFile = new File(bin, name + "-service.bat");
+                wrapperConf = new File(etc, name + "-wrapper.conf");
+
+                copyFilteredResourceTo(wrapperConf, "windows/karaf-wrapper.conf", props);
+                copyFilteredResourceTo(serviceFile, "windows/karaf-service.bat", props);
+
+                mkdir(lib);
+                copyResourceTo(new File(lib, "wrapper.dll"), "windows/wrapper.dll", false);
+            }
+        } else if (os.startsWith("Mac OS X")) {
+            mkdir(bin);
+
+            File file = new File(bin, name + "-wrapper");
+            copyResourceTo(file, "macosx/karaf-wrapper", false);
+            chmod(file, "a+x");
+
+            serviceFile = new File(bin, name + "-service");
+            copyFilteredResourceTo(serviceFile, "unix/karaf-service", props);
+            chmod(serviceFile, "a+x");
+
+            wrapperConf = new File(etc, name + "-wrapper.conf");
+            copyFilteredResourceTo(wrapperConf, "unix/karaf-wrapper.conf", props);
+
+            File plistConf = new File(bin, "org.apache.karaf."+ name + ".plist");
+            copyFilteredResourceTo(plistConf, "macosx/org.apache.karaf.KARAF.plist", props);
+            
+            mkdir(lib);
+
+            copyResourceTo(new File(lib, "libwrapper.jnilib"), "macosx/libwrapper.jnilib", false);
+        } else if (os.startsWith("Linux")) {
+            String arch = System.getProperty("os.arch");
+            if (arch.equalsIgnoreCase("amd64") || arch.equalsIgnoreCase("x86_64")) {
+                mkdir(bin);
+
+                File file = new File(bin, name + "-wrapper");
+                copyResourceTo(file, "linux64/karaf-wrapper", false);
+                chmod(file, "a+x");
+
+                serviceFile = new File(bin, name + "-service");
+                copyFilteredResourceTo(serviceFile, "unix/karaf-service", props);
+                chmod(serviceFile, "a+x");
+
+                wrapperConf = new File(etc, name + "-wrapper.conf");
+                copyFilteredResourceTo(wrapperConf, "unix/karaf-wrapper.conf", props);
+
+                mkdir(lib);
+                copyResourceTo(new File(lib, "libwrapper.so"), "linux64/libwrapper.so", false);
+            } else {
+                mkdir(bin);
+
+                File file = new File(bin, name + "-wrapper");
+                copyResourceTo(file, "linux/karaf-wrapper", false);
+                chmod(file, "a+x");
+
+                serviceFile = new File(bin, name + "-service");
+                copyFilteredResourceTo(serviceFile, "unix/karaf-service", props);
+                chmod(serviceFile, "a+x");
+
+                wrapperConf = new File(etc, name + "-wrapper.conf");
+                copyFilteredResourceTo(wrapperConf, "unix/karaf-wrapper.conf", props);
+
+                mkdir(lib);
+                copyResourceTo(new File(lib, "libwrapper.so"), "linux/libwrapper.so", false);
+            }
+        } else if (os.startsWith("AIX")) {
+            String arch = System.getProperty("os.arch");
+            if (arch.equalsIgnoreCase("ppc64")) {
+                mkdir(bin);
+
+                File file = new File(bin, name + "-wrapper");
+                copyResourceTo(file, "aix/ppc64/karaf-wrapper", false);
+                chmod(file, "a+x");
+
+                serviceFile = new File(bin, name + "-service");
+                copyFilteredResourceTo(serviceFile, "unix/karaf-service", props);
+                chmod(serviceFile, "a+x");
+
+                wrapperConf = new File(etc, name + "-wrapper.conf");
+                copyFilteredResourceTo(wrapperConf, "unix/karaf-wrapper.conf", props);
+
+                mkdir(lib);
+                copyResourceTo(new File(lib, "libwrapper.a"), "aix/ppc64/libwrapper.a", false);
+            } else {
+                mkdir(bin);
+
+                File file = new File(bin, name + "-wrapper");
+                copyResourceTo(file, "aix/ppc32/karaf-wrapper", false);
+                chmod(file, "a+x");
+
+                serviceFile = new File(bin, name + "-service");
+                copyFilteredResourceTo(serviceFile, "unix/karaf-service", props);
+                chmod(serviceFile, "a+x");
+
+                wrapperConf = new File(etc, name + "-wrapper.conf");
+                copyFilteredResourceTo(wrapperConf, "unix/karaf-wrapper.conf", props);
+
+                mkdir(lib);
+                copyResourceTo(new File(lib, "libwrapper.a"), "aix/ppc32/libwrapper.a", false);
+            }
+        } else if (os.startsWith("Solaris") || os.startsWith("SunOS")) {
+            String arch = System.getProperty("os.arch");
+            if (arch.equalsIgnoreCase("sparc")) {
+                mkdir(bin);
+
+                File file = new File(bin, name + "-wrapper");
+                copyResourceTo(file, "solaris/sparc64/karaf-wrapper", false);
+                chmod(file, "a+x");
+
+                serviceFile = new File(bin, name + "-service");
+                copyFilteredResourceTo(serviceFile, "unix/karaf-service", props);
+                chmod(serviceFile, "a+x");
+
+                wrapperConf = new File(etc, name + "-wrapper.conf");
+                copyFilteredResourceTo(wrapperConf, "unix/karaf-wrapper.conf", props);
+
+                mkdir(lib);
+                copyResourceTo(new File(lib, "libwrapper.so"), "solaris/sparc64/libwrapper.so", false);
+            } else if (arch.equalsIgnoreCase("x86")) {
+                mkdir(bin);
+
+                File file = new File(bin, name + "-wrapper");
+                copyResourceTo(file, "solaris/x86/karaf-wrapper", false);
+                chmod(file, "a+x");
+
+                serviceFile = new File(bin, name + "-service");
+                copyFilteredResourceTo(serviceFile, "unix/karaf-service", props);
+                chmod(serviceFile, "a+x");
+
+                wrapperConf = new File(etc, name + "-wrapper.conf");
+                copyFilteredResourceTo(wrapperConf, "unix/karaf-wrapper.conf", props);
+
+                mkdir(lib);
+                copyResourceTo(new File(lib, "libwrapper.so"), "solaris/x86/libwrapper.so", false);
+            } else if (arch.equalsIgnoreCase("x86_64")) {
+                mkdir(bin);
+
+                File file = new File(bin, name + "-wrapper");
+                copyResourceTo(file, "solaris/x86_64/karaf-wrapper", false);
+                chmod(file, "a+x");
+
+                serviceFile = new File(bin, name + "-service");
+                copyFilteredResourceTo(serviceFile, "unix/karaf-service", props);
+                chmod(serviceFile, "a+x");
+
+                wrapperConf = new File(etc, name + "-wrapper.conf");
+                copyFilteredResourceTo(wrapperConf, "unix/karaf-wrapper.conf", props);
+
+                mkdir(lib);
+                copyResourceTo(new File(lib, "libwrapper.so"), "solaris/x86_64/libwrapper.so", false);
+            } else {
+                mkdir(bin);
+
+                File file = new File(bin, name + "-wrapper");
+                copyResourceTo(file, "solaris/sparc32/karaf-wrapper", false);
+                chmod(file, "a+x");
+
+                serviceFile = new File(bin, name + "-service");
+                copyFilteredResourceTo(serviceFile, "unix/karaf-service", props);
+                chmod(serviceFile, "a+x");
+
+                wrapperConf = new File(etc, name + "-wrapper.conf");
+                copyFilteredResourceTo(wrapperConf, "unix/karaf-wrapper.conf", props);
+
+                mkdir(lib);
+                copyResourceTo(new File(lib, "libwrapper.so"), "solaris/sparc32/libwrapper.so", false);
+            }
+        } else if (os.startsWith("HP-UX") || os.startsWith("HPUX")) {
+            mkdir(bin);
+
+            File file = new File(bin, name + "-wrapper");
+            copyResourceTo(file, "hpux/parisc64/karaf-wrapper", false);
+            chmod(file, "a+x");
+
+            serviceFile = new File(bin, name + "-service");
+            copyFilteredResourceTo(serviceFile, "unix/karaf-service", props);
+            chmod(serviceFile, "a+x");
+
+            wrapperConf = new File(etc, name + "-wrapper.conf");
+            copyFilteredResourceTo(wrapperConf, "unix/karaf-wrapper.conf", props);
+
+            mkdir(lib);
+            copyResourceTo(new File(lib, "libwrapper.sl"), "hpux/parisc64/libwrapper.sl", false);
+        } else {
+            throw new IllegalStateException("Your operating system '" + os + "' is not currently supported.");
+        }
+
+        // install the wrapper jar to the lib directory
+        mkdir(lib);
+        copyResourceTo(new File(lib, "karaf-wrapper.jar"), "all/karaf-wrapper.jar", false);
+        mkdir(etc);
+
+        createJar(new File(lib, "karaf-wrapper-main.jar"), "org/apache/karaf/wrapper/internal/Main.class");
+
+        File[] wrapperPaths = new File[2];
+        wrapperPaths[0] = wrapperConf;
+        wrapperPaths[1] = serviceFile;
+
+        return wrapperPaths;
+    }
+
+    private void mkdir(File file) {
+        if (!file.exists()) {
+            LOGGER.info("Creating missing directory: {}", file.getPath());
+            System.out.println(Ansi.ansi().a("Creating missing directory: ")
+                    .a(Ansi.Attribute.INTENSITY_BOLD).a(file.getPath()).a(Ansi.Attribute.RESET).toString());
+            file.mkdirs();
+        }
+    }
+
+    private void copyResourceTo(File outFile, String resource, boolean text) throws Exception {
+        if (!outFile.exists()) {
+            LOGGER.info("Creating file: {}", outFile.getPath());
+            System.out.println(Ansi.ansi().a("Creating file: ")
+                    .a(Ansi.Attribute.INTENSITY_BOLD).a(outFile.getPath()).a(Ansi.Attribute.RESET).toString());
+            InputStream is = WrapperServiceImpl.class.getResourceAsStream(resource);
+            if (is == null) {
+                throw new IllegalArgumentException("Resource " + resource + " doesn't exist");
+            }
+            try {
+                if (text) {
+                    // read it line at a time so what we can use the platform line ending when we write it out
+                    PrintStream out = new PrintStream(new FileOutputStream(outFile));
+                    try {
+                        Scanner scanner = new Scanner(is);
+                        while (scanner.hasNextLine()) {
+                            String line = scanner.nextLine();
+                            LOGGER.info("writing: {}", line);
+                            out.println(line);
+                        }
+                    } finally {
+                        safeClose(out);
+                    }
+                } else {
+                    // binary resource so just write it out the way it came in
+                    FileOutputStream out = new FileOutputStream(outFile);
+                    try {
+                        int c = 0;
+                        while ((c = is.read()) >= 0) {
+                            out.write(c);
+                        }
+                    } finally {
+                        safeClose(out);
+                    }
+                }
+            } finally {
+                safeClose(is);
+            }
+        } else {
+            LOGGER.warn("File already exists. Move it out of the way if you wish to recreate it: {}", outFile.getPath());
+            System.out.println(Ansi.ansi()
+                    .fg(Ansi.Color.RED).a("File already exists").a(Ansi.Attribute.RESET)
+                    .a(". Move it out of the way if you wish to recreate it: ").a(outFile.getPath()).toString());
+        }
+    }
+
+    private void copyFilteredResourceTo(File outFile, String resource, HashMap<String, String> props) throws Exception {
+        if (!outFile.exists()) {
+            LOGGER.info("Creating file: {}", outFile.getPath());
+            System.out.println(Ansi.ansi().a("Creating file: ")
+                    .a(Ansi.Attribute.INTENSITY_BOLD).a(outFile.getPath()).a(Ansi.Attribute.RESET).toString());
+            InputStream is = WrapperServiceImpl.class.getResourceAsStream(resource);
+            if (is == null) {
+                throw new IllegalArgumentException("Resource " + resource + " doesn't exist");
+            }
+            try {
+                // read it line at a time so that we can use the platform line ending when we write it out
+                PrintStream out = new PrintStream(new FileOutputStream(outFile));
+                try {
+                    Scanner scanner = new Scanner(is);
+                    while (scanner.hasNextLine()) {
+                        String line = scanner.nextLine();
+                        line = filter(line, props);
+                        out.println(line);
+                    }
+                } finally {
+                    safeClose(out);
+                }
+            } finally {
+                safeClose(is);
+            }
+        } else {
+            LOGGER.warn("File already exists. Move it out of the way if you wish to recreate it: {}", outFile.getPath());
+            System.out.println(Ansi.ansi()
+                    .fg(Ansi.Color.RED).a("File already exists").a(Ansi.Attribute.RESET)
+                    .a(". Move it out of the way if you wish to recreate it: ").a(outFile.getPath()).toString());
+        }
+    }
+
+    private void safeClose(InputStream is) throws IOException {
+        if (is == null)
+            return;
+        try {
+            is.close();
+        } catch (Throwable ignore) {
+            // nothing to do
+        }
+    }
+
+    private void safeClose(OutputStream is) throws IOException {
+        if (is == null)
+            return;
+        try {
+            is.close();
+        } catch (Throwable ignore) {
+            // nothing to do
+        }
+    }
+
+    private String filter(String line, HashMap<String, String> props) {
+        for (Map.Entry<String, String> i : props.entrySet()) {
+            int p1 = line.indexOf(i.getKey());
+            if (p1 >= 0) {
+                String l1 = line.substring(0, p1);
+                String l2 = line.substring(p1 + i.getKey().length());
+                line = l1 + i.getValue() + l2;
+            }
+        }
+        return line;
+    }
+
+    private int chmod(File serviceFile, String mode) throws Exception {
+        ProcessBuilder builder = new ProcessBuilder();
+        builder.command("chmod", mode, serviceFile.getCanonicalPath());
+        Process p = builder.start();
+
+        PumpStreamHandler handler = new PumpStreamHandler(System.in, System.out, System.err);
+        handler.attach(p);
+        handler.start();
+        int status = p.waitFor();
+        handler.stop();
+        return status;
+    }
+
+    private void createJar(File outFile, String resource) throws Exception {
+        if (!outFile.exists()) {
+            LOGGER.info("Creating file: {}", outFile.getPath());
+            System.out.println(Ansi.ansi().a("Creating file: ")
+                    .a(Ansi.Attribute.INTENSITY_BOLD).a(outFile.getPath()).a(Ansi.Attribute.RESET).toString());
+            InputStream is = getClass().getClassLoader().getResourceAsStream(resource);
+            if (is == null) {
+                throw new IllegalStateException("Resource " + resource + " not found!");
+            }
+            try {
+                JarOutputStream jar = new JarOutputStream(new FileOutputStream(outFile));
+                int idx = resource.indexOf('/');
+                while (idx > 0) {
+                    jar.putNextEntry(new ZipEntry(resource.substring(0, idx)));
+                    jar.closeEntry();
+                    idx = resource.indexOf('/', idx + 1);
+                }
+                jar.putNextEntry(new ZipEntry(resource));
+                int c;
+                while ((c = is.read()) >= 0) {
+                    jar.write(c);
+                }
+                jar.closeEntry();
+                jar.close();
+            } finally {
+                safeClose(is);
+            }
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/4182735c/wrapper/src/main/java/org/apache/karaf/wrapper/internal/osgi/Activator.java
----------------------------------------------------------------------
diff --git a/wrapper/src/main/java/org/apache/karaf/wrapper/internal/osgi/Activator.java b/wrapper/src/main/java/org/apache/karaf/wrapper/internal/osgi/Activator.java
new file mode 100644
index 0000000..0cb8242
--- /dev/null
+++ b/wrapper/src/main/java/org/apache/karaf/wrapper/internal/osgi/Activator.java
@@ -0,0 +1,36 @@
+/*
+ * 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.karaf.wrapper.internal.osgi;
+
+import org.apache.karaf.util.tracker.BaseActivator;
+import org.apache.karaf.wrapper.WrapperService;
+import org.apache.karaf.wrapper.internal.WrapperServiceImpl;
+import org.apache.karaf.wrapper.management.internal.WrapperMBeanImpl;
+
+public class Activator extends BaseActivator {
+
+    @Override
+    protected void doStart() throws Exception {
+        WrapperService wrapperService = new WrapperServiceImpl();
+        register(WrapperService.class, wrapperService);
+
+        WrapperMBeanImpl wrapperMBean = new WrapperMBeanImpl();
+        wrapperMBean.setWrapperService(wrapperService);
+        registerMBean(wrapperMBean, "type=wrapper");
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/4182735c/wrapper/src/main/java/org/apache/karaf/wrapper/management/WrapperMBean.java
----------------------------------------------------------------------
diff --git a/wrapper/src/main/java/org/apache/karaf/wrapper/management/WrapperMBean.java b/wrapper/src/main/java/org/apache/karaf/wrapper/management/WrapperMBean.java
new file mode 100644
index 0000000..937bfe2
--- /dev/null
+++ b/wrapper/src/main/java/org/apache/karaf/wrapper/management/WrapperMBean.java
@@ -0,0 +1,46 @@
+/*
+ * 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.karaf.wrapper.management;
+
+import javax.management.MBeanException;
+import java.io.File;
+
+/**
+ * Describe the WrapperMBean.
+ */
+public interface WrapperMBean {
+
+    /**
+     * Install the service wrapper.
+     *
+     * @throws MBeanException in case of installation failure.
+     */
+    void install() throws MBeanException;
+
+    /**
+     * Install the service wrapper.
+     *
+     * @param name the service name.
+     * @param displayName the service display name.
+     * @param description the service description.
+     * @param startType the start type.
+     * @return the wrapper configuration (index 0) and service files (index 1).
+     * @throws MBeanException in case of installation failure.
+     */
+    File[] install(String name, String displayName, String description, String startType) throws MBeanException;
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/4182735c/wrapper/src/main/java/org/apache/karaf/wrapper/management/internal/WrapperMBeanImpl.java
----------------------------------------------------------------------
diff --git a/wrapper/src/main/java/org/apache/karaf/wrapper/management/internal/WrapperMBeanImpl.java b/wrapper/src/main/java/org/apache/karaf/wrapper/management/internal/WrapperMBeanImpl.java
new file mode 100644
index 0000000..1523015
--- /dev/null
+++ b/wrapper/src/main/java/org/apache/karaf/wrapper/management/internal/WrapperMBeanImpl.java
@@ -0,0 +1,62 @@
+/*
+ * 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.karaf.wrapper.management.internal;
+
+import org.apache.karaf.wrapper.WrapperService;
+import org.apache.karaf.wrapper.management.WrapperMBean;
+
+import javax.management.MBeanException;
+import javax.management.NotCompliantMBeanException;
+import javax.management.StandardMBean;
+import java.io.File;
+
+/**
+ * Implementation of the wrapper MBean.
+ */
+public class WrapperMBeanImpl extends StandardMBean implements WrapperMBean {
+
+    private WrapperService wrapperService;
+
+    public WrapperMBeanImpl() throws NotCompliantMBeanException {
+        super(WrapperMBean.class);
+    }
+
+    public void setWrapperService(WrapperService wrapperService) {
+        this.wrapperService = wrapperService;
+    }
+
+    public WrapperService getWrapperService() {
+        return this.wrapperService;
+    }
+
+    public void install() throws MBeanException {
+        try {
+            wrapperService.install();
+        } catch (Exception e) {
+            throw new MBeanException(null, e.getMessage());
+        }
+    }
+
+    public File[] install(String name, String displayName, String description, String startType) throws MBeanException {
+        try {
+            return wrapperService.install(name, displayName, description, startType);
+        } catch (Exception e) {
+            throw new MBeanException(null, e.getMessage());
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/4182735c/wrapper/src/main/resources/META-INF/services/org/apache/karaf/shell/commands
----------------------------------------------------------------------
diff --git a/wrapper/src/main/resources/META-INF/services/org/apache/karaf/shell/commands b/wrapper/src/main/resources/META-INF/services/org/apache/karaf/shell/commands
new file mode 100644
index 0000000..73b329d
--- /dev/null
+++ b/wrapper/src/main/resources/META-INF/services/org/apache/karaf/shell/commands
@@ -0,0 +1,18 @@
+##---------------------------------------------------------------------------
+##  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.
+##---------------------------------------------------------------------------
+org.apache.karaf.wrapper.internal.WrapperServiceImpl
+org.apache.karaf.wrapper.commands.Install
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/karaf/blob/4182735c/wrapper/src/main/resources/OSGI-INF/bundle.info
----------------------------------------------------------------------
diff --git a/wrapper/src/main/resources/OSGI-INF/bundle.info b/wrapper/src/main/resources/OSGI-INF/bundle.info
new file mode 100644
index 0000000..8462cc5
--- /dev/null
+++ b/wrapper/src/main/resources/OSGI-INF/bundle.info
@@ -0,0 +1,16 @@
+h1. Synopsis
+
+${project.name}
+
+${project.description}
+
+Maven URL:
+[mvn:${project.groupId}/${project.artifactId}/${project.version}]
+
+h1. Description
+
+This bundle provides support of the service wrapper, which allows for starting/stopping Karaf as a system service.
+
+h1. See also
+
+Service Wrapper - section of the Karaf User Guide

http://git-wip-us.apache.org/repos/asf/karaf/blob/4182735c/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/aix/ppc32/karaf-wrapper
----------------------------------------------------------------------
diff --git a/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/aix/ppc32/karaf-wrapper b/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/aix/ppc32/karaf-wrapper
new file mode 100755
index 0000000..5215c2e
Binary files /dev/null and b/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/aix/ppc32/karaf-wrapper differ

http://git-wip-us.apache.org/repos/asf/karaf/blob/4182735c/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/aix/ppc32/libwrapper.a
----------------------------------------------------------------------
diff --git a/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/aix/ppc32/libwrapper.a b/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/aix/ppc32/libwrapper.a
new file mode 100755
index 0000000..4bcc342
Binary files /dev/null and b/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/aix/ppc32/libwrapper.a differ

http://git-wip-us.apache.org/repos/asf/karaf/blob/4182735c/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/aix/ppc64/karaf-wrapper
----------------------------------------------------------------------
diff --git a/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/aix/ppc64/karaf-wrapper b/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/aix/ppc64/karaf-wrapper
new file mode 100755
index 0000000..6ba0351
Binary files /dev/null and b/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/aix/ppc64/karaf-wrapper differ

http://git-wip-us.apache.org/repos/asf/karaf/blob/4182735c/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/aix/ppc64/libwrapper.a
----------------------------------------------------------------------
diff --git a/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/aix/ppc64/libwrapper.a b/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/aix/ppc64/libwrapper.a
new file mode 100755
index 0000000..b569e3f
Binary files /dev/null and b/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/aix/ppc64/libwrapper.a differ

http://git-wip-us.apache.org/repos/asf/karaf/blob/4182735c/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/all/karaf-wrapper.jar
----------------------------------------------------------------------
diff --git a/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/all/karaf-wrapper.jar b/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/all/karaf-wrapper.jar
new file mode 100644
index 0000000..4db355b
Binary files /dev/null and b/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/all/karaf-wrapper.jar differ

http://git-wip-us.apache.org/repos/asf/karaf/blob/4182735c/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/hpux/parisc64/karaf-wrapper
----------------------------------------------------------------------
diff --git a/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/hpux/parisc64/karaf-wrapper b/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/hpux/parisc64/karaf-wrapper
new file mode 100755
index 0000000..ad883d7
Binary files /dev/null and b/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/hpux/parisc64/karaf-wrapper differ

http://git-wip-us.apache.org/repos/asf/karaf/blob/4182735c/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/hpux/parisc64/libwrapper.sl
----------------------------------------------------------------------
diff --git a/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/hpux/parisc64/libwrapper.sl b/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/hpux/parisc64/libwrapper.sl
new file mode 100755
index 0000000..08adc52
Binary files /dev/null and b/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/hpux/parisc64/libwrapper.sl differ

http://git-wip-us.apache.org/repos/asf/karaf/blob/4182735c/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/linux/karaf-wrapper
----------------------------------------------------------------------
diff --git a/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/linux/karaf-wrapper b/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/linux/karaf-wrapper
new file mode 100644
index 0000000..7e00645
Binary files /dev/null and b/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/linux/karaf-wrapper differ

http://git-wip-us.apache.org/repos/asf/karaf/blob/4182735c/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/linux/libwrapper.so
----------------------------------------------------------------------
diff --git a/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/linux/libwrapper.so b/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/linux/libwrapper.so
new file mode 100644
index 0000000..2cc4ab3
Binary files /dev/null and b/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/linux/libwrapper.so differ

http://git-wip-us.apache.org/repos/asf/karaf/blob/4182735c/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/linux64/karaf-wrapper
----------------------------------------------------------------------
diff --git a/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/linux64/karaf-wrapper b/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/linux64/karaf-wrapper
new file mode 100644
index 0000000..3128b95
Binary files /dev/null and b/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/linux64/karaf-wrapper differ

http://git-wip-us.apache.org/repos/asf/karaf/blob/4182735c/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/linux64/libwrapper.so
----------------------------------------------------------------------
diff --git a/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/linux64/libwrapper.so b/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/linux64/libwrapper.so
new file mode 100644
index 0000000..24197bf
Binary files /dev/null and b/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/linux64/libwrapper.so differ

http://git-wip-us.apache.org/repos/asf/karaf/blob/4182735c/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/macosx/karaf-wrapper
----------------------------------------------------------------------
diff --git a/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/macosx/karaf-wrapper b/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/macosx/karaf-wrapper
new file mode 100644
index 0000000..0165db0
Binary files /dev/null and b/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/macosx/karaf-wrapper differ

http://git-wip-us.apache.org/repos/asf/karaf/blob/4182735c/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/macosx/libwrapper.jnilib
----------------------------------------------------------------------
diff --git a/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/macosx/libwrapper.jnilib b/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/macosx/libwrapper.jnilib
new file mode 100644
index 0000000..6356705
Binary files /dev/null and b/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/macosx/libwrapper.jnilib differ

http://git-wip-us.apache.org/repos/asf/karaf/blob/4182735c/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/macosx/org.apache.karaf.KARAF.plist
----------------------------------------------------------------------
diff --git a/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/macosx/org.apache.karaf.KARAF.plist b/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/macosx/org.apache.karaf.KARAF.plist
new file mode 100644
index 0000000..1c18918
--- /dev/null
+++ b/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/macosx/org.apache.karaf.KARAF.plist
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    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.
+    -->
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>ProcessType</key>
+	<string>Background</string>
+	<key>KeepAlive</key>
+	<false/>
+	<key>Label</key>
+	<string>org.apache.karaf.KARAF</string>
+	<key>ProgramArguments</key>
+	<array>
+		<!-- path to your KARAF-service wrapper -->
+		<string>${karaf.home}/bin/${name}-service</string>
+		<string>console</string>
+	</array>
+	<key>RunAtLoad</key>
+	<true/>
+</dict>
+</plist>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/karaf/blob/4182735c/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/solaris/sparc32/karaf-wrapper
----------------------------------------------------------------------
diff --git a/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/solaris/sparc32/karaf-wrapper b/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/solaris/sparc32/karaf-wrapper
new file mode 100755
index 0000000..7cac208
Binary files /dev/null and b/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/solaris/sparc32/karaf-wrapper differ

http://git-wip-us.apache.org/repos/asf/karaf/blob/4182735c/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/solaris/sparc32/libwrapper.so
----------------------------------------------------------------------
diff --git a/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/solaris/sparc32/libwrapper.so b/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/solaris/sparc32/libwrapper.so
new file mode 100755
index 0000000..4093262
Binary files /dev/null and b/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/solaris/sparc32/libwrapper.so differ

http://git-wip-us.apache.org/repos/asf/karaf/blob/4182735c/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/solaris/sparc64/karaf-wrapper
----------------------------------------------------------------------
diff --git a/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/solaris/sparc64/karaf-wrapper b/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/solaris/sparc64/karaf-wrapper
new file mode 100755
index 0000000..91257c6
Binary files /dev/null and b/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/solaris/sparc64/karaf-wrapper differ

http://git-wip-us.apache.org/repos/asf/karaf/blob/4182735c/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/solaris/sparc64/libwrapper.so
----------------------------------------------------------------------
diff --git a/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/solaris/sparc64/libwrapper.so b/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/solaris/sparc64/libwrapper.so
new file mode 100755
index 0000000..008bef6
Binary files /dev/null and b/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/solaris/sparc64/libwrapper.so differ

http://git-wip-us.apache.org/repos/asf/karaf/blob/4182735c/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/solaris/x86/karaf-wrapper
----------------------------------------------------------------------
diff --git a/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/solaris/x86/karaf-wrapper b/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/solaris/x86/karaf-wrapper
new file mode 100755
index 0000000..bdec254
Binary files /dev/null and b/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/solaris/x86/karaf-wrapper differ

http://git-wip-us.apache.org/repos/asf/karaf/blob/4182735c/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/solaris/x86/libwrapper.so
----------------------------------------------------------------------
diff --git a/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/solaris/x86/libwrapper.so b/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/solaris/x86/libwrapper.so
new file mode 100755
index 0000000..963ff49
Binary files /dev/null and b/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/solaris/x86/libwrapper.so differ

http://git-wip-us.apache.org/repos/asf/karaf/blob/4182735c/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/solaris/x86_64/karaf-wrapper
----------------------------------------------------------------------
diff --git a/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/solaris/x86_64/karaf-wrapper b/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/solaris/x86_64/karaf-wrapper
new file mode 100755
index 0000000..6bd165e
Binary files /dev/null and b/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/solaris/x86_64/karaf-wrapper differ

http://git-wip-us.apache.org/repos/asf/karaf/blob/4182735c/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/solaris/x86_64/libwrapper.so
----------------------------------------------------------------------
diff --git a/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/solaris/x86_64/libwrapper.so b/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/solaris/x86_64/libwrapper.so
new file mode 100755
index 0000000..0d52ffa
Binary files /dev/null and b/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/solaris/x86_64/libwrapper.so differ

http://git-wip-us.apache.org/repos/asf/karaf/blob/4182735c/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/unix/karaf-service
----------------------------------------------------------------------
diff --git a/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/unix/karaf-service b/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/unix/karaf-service
new file mode 100644
index 0000000..a7ca8bb
--- /dev/null
+++ b/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/unix/karaf-service
@@ -0,0 +1,557 @@
+#! /bin/sh
+
+# ------------------------------------------------------------------------
+# 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.
+# ------------------------------------------------------------------------
+
+# If require, set the JAVA_HOME to launch the wrapper
+#
+#JAVA_HOME=
+#
+
+# Application
+APP_NAME="${name}"
+APP_LONG_NAME="${displayName}"
+
+# Wrapper
+WRAPPER_CMD="${karaf.base}/bin/${APP_NAME}-wrapper"
+WRAPPER_CONF="${karaf.etc}/${APP_NAME}-wrapper.conf"
+
+# Priority at which to run the wrapper.  See "man nice" for valid priorities.
+#  nice is only used if a priority is specified.
+PRIORITY=
+
+# Location of the data folder.
+DATADIR="${karaf.data}"
+
+# Location of the pid file.
+PIDDIR="${karaf.data}"
+
+# If uncommented, causes the Wrapper to be shutdown using an anchor file.
+#  When launched with the 'start' command, it will also ignore all INT and
+#  TERM signals.
+#IGNORE_SIGNALS=true
+
+# If specified, the Wrapper will be run as the specified user.
+# IMPORTANT - Make sure that the user has the required privileges to write
+#  the PID file and wrapper.log files.  Failure to be able to write the log
+#  file will cause the Wrapper to exit without any way to write out an error
+#  message.
+# NOTE - This will set the user which is used to run the Wrapper as well as
+#  the JVM and is not useful in situations where a privileged resource or
+#  port needs to be allocated prior to the user being changed.
+#RUN_AS_USER=
+
+# The following two lines are used by the chkconfig command. Change as is
+#  appropriate for your application.  They should remain commented.
+# chkconfig: 2345 20 80
+# description: ${displayName}
+
+# Do not modify anything beyond this point
+#-----------------------------------------------------------------------------
+
+# Get the fully qualified path to the script
+case $0 in
+    /*)
+        SCRIPT="$0"
+        ;;
+    *)
+        PWD=`pwd`
+        SCRIPT="$PWD/$0"
+        ;;
+esac
+
+# Resolve the true real path without any sym links.
+CHANGED=true
+while [ "X$CHANGED" != "X" ]
+do
+    # Change spaces to ":" so the tokens can be parsed.
+    SCRIPT=`echo $SCRIPT | sed -e 's; ;:;g'`
+    # Get the real path to this script, resolving any symbolic links
+    TOKENS=`echo $SCRIPT | sed -e 's;/; ;g'`
+    REALPATH=
+    for C in $TOKENS; do
+        REALPATH="$REALPATH/$C"
+        while [ -h "$REALPATH" ] ; do
+            LS="`ls -ld "$REALPATH"`"
+            LINK="`expr "$LS" : '.*-> \(.*\)$'`"
+            if expr "$LINK" : '/.*' > /dev/null; then
+                REALPATH="$LINK"
+            else
+                REALPATH="`dirname "$REALPATH"`""/$LINK"
+            fi
+        done
+    done
+    # Change ":" chars back to spaces.
+    REALPATH=`echo $REALPATH | sed -e 's;:; ;g'`
+
+    if [ "$REALPATH" = "$SCRIPT" ]
+    then
+        CHANGED=""
+    else
+        SCRIPT="$REALPATH"
+    fi
+done
+
+# Change the current directory to the location of the script
+cd "`dirname "$REALPATH"`"
+REALDIR=`pwd`
+
+# If the PIDDIR is relative, set its value relative to the full REALPATH to avoid problems if
+#  the working directory is later changed.
+FIRST_CHAR=`echo $PIDDIR | cut -c1,1`
+if [ "$FIRST_CHAR" != "/" ]
+then
+    PIDDIR=$REALDIR/$PIDDIR
+fi
+# Same test for WRAPPER_CMD
+FIRST_CHAR=`echo $WRAPPER_CMD | cut -c1,1`
+if [ "$FIRST_CHAR" != "/" ]
+then
+    WRAPPER_CMD=$REALDIR/$WRAPPER_CMD
+fi
+# Same test for WRAPPER_CONF
+FIRST_CHAR=`echo $WRAPPER_CONF | cut -c1,1`
+if [ "$FIRST_CHAR" != "/" ]
+then
+    WRAPPER_CONF=$REALDIR/$WRAPPER_CONF
+fi
+
+# Process ID
+ANCHORFILE="$PIDDIR/$APP_NAME.anchor"
+PIDFILE="$PIDDIR/$APP_NAME.pid"
+LOCKDIR="/var/lock/subsys"
+LOCKFILE="$LOCKDIR/$APP_NAME"
+pid=""
+
+# Resolve the location of the 'ps' command
+PSEXE="/usr/bin/ps"
+if [ ! -x $PSEXE ]
+then
+    PSEXE="/bin/ps"
+    if [ ! -x $PSEXE ]
+    then
+        echo "Unable to locate 'ps'."
+        echo "Please report this message along with the location of the command on your system."
+        exit 1
+    fi
+fi
+
+# Resolve the os
+DIST_OS=`uname -s | tr [:upper:] [:lower:] | tr -d [:blank:]`
+case "$DIST_OS" in
+    'sunos')
+        DIST_OS="solaris"
+        ;;
+    'hp-ux' | 'hp-ux64')
+        DIST_OS="hpux"
+        ;;
+    'darwin')
+        DIST_OS="macosx"
+        ;;
+    'unix_sv')
+        DIST_OS="unixware"
+        ;;
+esac
+
+# Resolve the architecture
+DIST_ARCH=`uname -p | tr [:upper:] [:lower:] | tr -d [:blank:]`
+if [ "$DIST_ARCH" = "unknown" ]
+then
+    DIST_ARCH=`uname -m | tr [:upper:] [:lower:] | tr -d [:blank:]`
+fi
+case "$DIST_ARCH" in
+    'amd64' | 'ia32' | 'ia64' | 'i386' | 'i486' | 'i586' | 'i686' | 'x86_64')
+        DIST_ARCH="x86"
+        ;;
+    'ip27')
+        DIST_ARCH="mips"
+        ;;
+    'power' | 'powerpc' | 'power_pc' | 'ppc64')
+        DIST_ARCH="ppc"
+        ;;
+    'pa_risc' | 'pa-risc')
+        DIST_ARCH="parisc"
+        ;;
+    'sun4u' | 'sparcv9')
+        DIST_ARCH="sparc"
+        ;;
+    '9000/800')
+        DIST_ARCH="parisc"
+        ;;
+esac
+
+# Decide on the wrapper binary to use.
+# If a 32-bit wrapper binary exists then it will work on 32 or 64 bit
+#  platforms, if the 64-bit binary exists then the distribution most
+#  likely wants to use long names.  Otherwise, look for the default.
+# For macosx, we also want to look for universal binaries.
+WRAPPER_TEST_CMD="$WRAPPER_CMD-$DIST_OS-$DIST_ARCH-32"
+if [ -x $WRAPPER_TEST_CMD ]
+then
+    WRAPPER_CMD="$WRAPPER_TEST_CMD"
+else
+    if [ "$DIST_OS" = "macosx" ]
+    then
+        WRAPPER_TEST_CMD="$WRAPPER_CMD-$DIST_OS-universal-32"
+        if [ -x $WRAPPER_TEST_CMD ]
+        then
+            WRAPPER_CMD="$WRAPPER_TEST_CMD"
+        else
+            WRAPPER_TEST_CMD="$WRAPPER_CMD-$DIST_OS-$DIST_ARCH-64"
+            if [ -x $WRAPPER_TEST_CMD ]
+            then
+                WRAPPER_CMD="$WRAPPER_TEST_CMD"
+            else
+                WRAPPER_TEST_CMD="$WRAPPER_CMD-$DIST_OS-universal-64"
+                if [ -x $WRAPPER_TEST_CMD ]
+                then
+                    WRAPPER_CMD="$WRAPPER_TEST_CMD"
+                else
+                    if [ ! -x $WRAPPER_CMD ]
+                    then
+                        echo "Unable to locate any of the following binaries:"
+                        echo "  $WRAPPER_CMD-$DIST_OS-$DIST_ARCH-32"
+                        echo "  $WRAPPER_CMD-$DIST_OS-universal-32"
+                        echo "  $WRAPPER_CMD-$DIST_OS-$DIST_ARCH-64"
+                        echo "  $WRAPPER_CMD-$DIST_OS-universal-64"
+                        echo "  $WRAPPER_CMD"
+                        exit 1
+                    fi
+                fi
+            fi
+        fi
+    else
+        WRAPPER_TEST_CMD="$WRAPPER_CMD-$DIST_OS-$DIST_ARCH-64"
+        if [ -x $WRAPPER_TEST_CMD ]
+        then
+            WRAPPER_CMD="$WRAPPER_TEST_CMD"
+        else
+            if [ ! -x $WRAPPER_CMD ]
+            then
+                echo "Unable to locate any of the following binaries:"
+                echo "  $WRAPPER_CMD-$DIST_OS-$DIST_ARCH-32"
+                echo "  $WRAPPER_CMD-$DIST_OS-$DIST_ARCH-64"
+                echo "  $WRAPPER_CMD"
+                exit 1
+            fi
+        fi
+    fi
+fi
+
+# Build the nice clause
+if [ "X$PRIORITY" = "X" ]
+then
+    CMDNICE=""
+else
+    CMDNICE="nice -$PRIORITY"
+fi
+
+# Build the anchor file clause.
+if [ "X$IGNORE_SIGNALS" = "X" ]
+then
+   ANCHORPROP=
+   IGNOREPROP=
+else
+   ANCHORPROP=wrapper.anchorfile=$ANCHORFILE
+   IGNOREPROP=wrapper.ignore_signals=TRUE
+fi
+
+# Build the lock file clause.  Only create a lock file if the lock directory exists on this platform.
+if [ -d $LOCKDIR ]
+then
+    LOCKPROP=wrapper.lockfile=$LOCKFILE
+else
+    LOCKPROP=
+fi
+
+checkUser() {
+    # Check the configured user.  If necessary rerun this script as the desired user.
+    if [ "X$RUN_AS_USER" != "X" ]
+    then
+        # Resolve the location of the 'id' command
+        IDEXE="/usr/xpg4/bin/id"
+        if [ ! -x $IDEXE ]
+        then
+            IDEXE="/usr/bin/id"
+            if [ ! -x $IDEXE ]
+            then
+                echo "Unable to locate 'id'."
+                echo "Please report this message along with the location of the command on your system."
+                exit 1
+            fi
+        fi
+
+        if [ "`$IDEXE -u -n`" = "$RUN_AS_USER" ]
+        then
+            # Already running as the configured user.  Avoid password prompts by not calling su.
+            RUN_AS_USER=""
+        fi
+    fi
+    if [ "X$RUN_AS_USER" != "X" ]
+    then
+        # If LOCKPROP and $RUN_AS_USER are defined then the new user will most likely not be
+        # able to create the lock file.  The Wrapper will be able to update this file once it
+        # is created but will not be able to delete it on shutdown.  If $2 is defined then
+        # the lock file should be created for the current command
+        if [ "X$LOCKPROP" != "X" ]
+        then
+            if [ "X$2" != "X" ]
+            then
+                # Resolve the primary group
+                RUN_AS_GROUP=`groups $RUN_AS_USER | awk '{print $3}' | tail -1`
+                if [ "X$RUN_AS_GROUP" = "X" ]
+                then
+                    RUN_AS_GROUP=$RUN_AS_USER
+                fi
+                touch $LOCKFILE
+                chown $RUN_AS_USER:$RUN_AS_GROUP $LOCKFILE
+            fi
+        fi
+
+        # Still want to change users, recurse.  This means that the user will only be
+        #  prompted for a password once.
+        su -m $RUN_AS_USER -s /bin/sh -c "$REALPATH $1"
+        RETVAL=$?
+
+        # Now that we are the original user again, we may need to clean up the lock file.
+        if [ "X$LOCKPROP" != "X" ]
+        then
+            getpid
+            if [ "X$pid" = "X" ]
+            then
+                # Wrapper is not running so make sure the lock file is deleted.
+                if [ -f $LOCKFILE ]
+                then
+                    rm $LOCKFILE
+                fi
+            fi
+        fi
+
+        exit $RETVAL
+    fi
+}
+
+getpid() {
+    if [ -f $PIDFILE ]
+    then
+        if [ -r $PIDFILE ]
+        then
+            pid=`cat $PIDFILE`
+            if [ "X$pid" != "X" ]
+            then
+                # It is possible that 'a' process with the pid exists but that it is not the
+                #  correct process.  This can happen in a number of cases, but the most
+                #  common is during system startup after an unclean shutdown.
+                # The ps statement below looks for the specific wrapper command running as
+                #  the pid.  If it is not found then the pid file is considered to be stale.
+                if [ "$DIST_OS" = "solaris" ]
+                then
+                    pidtest=`$PSEXE -p $pid -o comm | grep $WRAPPER_CMD | tail -1`
+                else
+                    pidtest=`$PSEXE -p $pid -o command | grep $WRAPPER_CMD | tail -1`
+                fi
+                if [ "X$pidtest" = "X" ]
+                then
+                    # This is a stale pid file.
+                    rm -f $PIDFILE
+                    echo "Removed stale pid file: $PIDFILE"
+                    pid=""
+                fi
+            fi
+        else
+            echo "Cannot read $PIDFILE."
+            exit 1
+        fi
+    fi
+}
+
+testpid() {
+    pid=`$PSEXE -p $pid | grep $pid | grep -v grep | awk '{print $1}' | tail -1`
+    if [ "X$pid" = "X" ]
+    then
+        # Process is gone so remove the pid file.
+        rm -f $PIDFILE
+        pid=""
+    fi
+}
+
+console() {
+    echo "Running $APP_LONG_NAME..."
+    getpid
+    if [ "X$pid" = "X" ]
+    then
+        COMMAND_LINE="$CMDNICE $WRAPPER_CMD $WRAPPER_CONF wrapper.syslog.ident=$APP_NAME wrapper.pidfile=$PIDFILE $ANCHORPROP $LOCKPROP"
+        exec $COMMAND_LINE
+    else
+        echo "$APP_LONG_NAME is already running."
+        exit 1
+    fi
+}
+
+start() {
+    echo "Starting $APP_LONG_NAME..."
+    getpid
+    if [ "X$pid" = "X" ]
+    then
+        if [ ! -d $DATADIR ]; then
+            mkdir $DATADIR
+        fi
+        if [ ! -d $DATADIR/log ]; then
+            mkdir $DATADIR/log
+        fi
+        COMMAND_LINE="$CMDNICE $WRAPPER_CMD $WRAPPER_CONF wrapper.syslog.ident=$APP_NAME wrapper.pidfile=$PIDFILE wrapper.daemonize=TRUE $ANCHORPROP $IGNOREPROP $LOCKPROP"
+        exec $COMMAND_LINE
+    else
+        echo "$APP_LONG_NAME is already running."
+        exit 1
+    fi
+}
+
+stopit() {
+    echo "Stopping $APP_LONG_NAME..."
+    getpid
+    if [ "X$pid" = "X" ]
+    then
+        echo "$APP_LONG_NAME was not running."
+    else
+        if [ "X$IGNORE_SIGNALS" = "X" ]
+        then
+            # Running so try to stop it.
+            kill $pid
+            if [ $? -ne 0 ]
+            then
+                # An explanation for the failure should have been given
+                echo "Unable to stop $APP_LONG_NAME."
+                exit 1
+            fi
+        else
+            rm -f $ANCHORFILE
+            if [ -f $ANCHORFILE ]
+            then
+                # An explanation for the failure should have been given
+                echo "Unable to stop $APP_LONG_NAME."
+                exit 1
+            fi
+        fi
+
+        # We can not predict how long it will take for the wrapper to
+        #  actually stop as it depends on settings in wrapper.conf.
+        #  Loop until it does.
+        savepid=$pid
+        CNT=0
+        TOTCNT=0
+        while [ "X$pid" != "X" ]
+        do
+            # Show a waiting message every 5 seconds.
+            if [ "$CNT" -lt "5" ]
+            then
+                CNT=`expr $CNT + 1`
+            else
+                echo "Waiting for $APP_LONG_NAME to exit..."
+                CNT=0
+            fi
+            TOTCNT=`expr $TOTCNT + 1`
+
+            sleep 1
+
+            testpid
+        done
+
+        pid=$savepid
+        testpid
+        if [ "X$pid" != "X" ]
+        then
+            echo "Failed to stop $APP_LONG_NAME."
+            exit 1
+        else
+            echo "Stopped $APP_LONG_NAME."
+        fi
+    fi
+}
+
+status() {
+    getpid
+    if [ "X$pid" = "X" ]
+    then
+        echo "$APP_LONG_NAME is not running."
+        exit 1
+    else
+        echo "$APP_LONG_NAME is running ($pid)."
+        exit 0
+    fi
+}
+
+dump() {
+    echo "Dumping $APP_LONG_NAME..."
+    getpid
+    if [ "X$pid" = "X" ]
+    then
+        echo "$APP_LONG_NAME was not running."
+
+    else
+        kill -3 $pid
+
+        if [ $? -ne 0 ]
+        then
+            echo "Failed to dump $APP_LONG_NAME."
+            exit 1
+        else
+            echo "Dumped $APP_LONG_NAME."
+        fi
+    fi
+}
+
+case "$1" in
+
+    'console')
+        checkUser $1 touchlock
+        console
+        ;;
+
+    'start')
+        checkUser $1 touchlock
+        start
+        ;;
+
+    'stop')
+        checkUser $1
+        stopit
+        ;;
+
+    'restart')
+        checkUser $1 touchlock
+        stopit
+        start
+        ;;
+
+    'status')
+        checkUser $1
+        status
+        ;;
+
+    'dump')
+        checkUser $1
+        dump
+        ;;
+
+    *)
+        echo "Usage: $0 { console | start | stop | restart | status | dump }"
+        exit 1
+        ;;
+esac
+
+exit 0

http://git-wip-us.apache.org/repos/asf/karaf/blob/4182735c/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/unix/karaf-wrapper.conf
----------------------------------------------------------------------
diff --git a/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/unix/karaf-wrapper.conf b/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/unix/karaf-wrapper.conf
new file mode 100644
index 0000000..a3f98a5
--- /dev/null
+++ b/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/unix/karaf-wrapper.conf
@@ -0,0 +1,135 @@
+# ------------------------------------------------------------------------
+# 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.
+# ------------------------------------------------------------------------
+
+#********************************************************************
+# Wrapper Properties
+#********************************************************************
+set.default.JAVA_HOME=${java.home}
+set.default.KARAF_HOME=${karaf.home}
+set.default.KARAF_BASE=${karaf.base}
+set.default.KARAF_DATA=${karaf.data}
+set.default.KARAF_ETC=${karaf.etc}
+
+# Java Application
+wrapper.working.dir=%KARAF_BASE%
+wrapper.java.command=%JAVA_HOME%/bin/java
+wrapper.java.mainclass=org.apache.karaf.wrapper.internal.Main
+wrapper.java.classpath.1=%KARAF_HOME%/lib/karaf-wrapper.jar
+wrapper.java.classpath.2=%KARAF_HOME%/lib/karaf.jar
+wrapper.java.classpath.3=%KARAF_HOME%/lib/karaf-jmx-boot.jar
+wrapper.java.classpath.4=%KARAF_HOME%/lib/karaf-jaas-boot.jar
+wrapper.java.classpath.5=%KARAF_HOME%/lib/karaf-wrapper-main.jar
+wrapper.java.classpath.6=%KARAF_HOME%/lib/karaf-org.osgi.core.jar
+wrapper.java.library.path.1=%KARAF_HOME%/lib/
+
+# Application Parameters.  Add parameters as needed starting from 1
+#wrapper.app.parameter.1=
+
+# JVM Parameters            
+# note that n is the parameter number starting from 1.
+wrapper.java.additional.1=-Dkaraf.home=%KARAF_HOME%
+wrapper.java.additional.2=-Dkaraf.base=%KARAF_BASE%
+wrapper.java.additional.3=-Dkaraf.data=%KARAF_DATA%
+wrapper.java.additional.4=-Dkaraf.etc=%KARAF_ETC%
+wrapper.java.additional.5=-Dcom.sun.management.jmxremote
+wrapper.java.additional.6=-Djavax.management.builder.initial=org.apache.karaf.management.boot.KarafMBeanServerBuilder
+wrapper.java.additional.7=-Dkaraf.startLocalConsole=false
+wrapper.java.additional.8=-Dkaraf.startRemoteShell=true
+wrapper.java.additional.9=-Djava.endorsed.dirs=%JAVA_HOME%/jre/lib/endorsed:%JAVA_HOME%/lib/endorsed:%KARAF_HOME%/lib/endorsed
+wrapper.java.additional.10=-Djava.ext.dirs=%JAVA_HOME%/jre/lib/ext:%JAVA_HOME%/lib/ext:%KARAF_HOME%/lib/ext
+
+# Uncomment to enable jmx
+#wrapper.java.additional.n=-Dcom.sun.management.jmxremote.port=1616
+#wrapper.java.additional.n=-Dcom.sun.management.jmxremote.authenticate=false
+#wrapper.java.additional.n=-Dcom.sun.management.jmxremote.ssl=false
+
+# Uncomment to enable YourKit profiling
+#wrapper.java.additional.n=-Xrunyjpagent
+
+# Uncomment to enable remote debugging
+#wrapper.java.additional.n=-Xdebug -Xnoagent -Djava.compiler=NONE
+#wrapper.java.additional.n=-Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005
+
+# Initial Java Heap Size (in MB)
+#wrapper.java.initmemory=3
+
+# Maximum Java Heap Size (in MB)
+wrapper.java.maxmemory=512
+
+
+#********************************************************************
+# Wrapper Logging Properties
+#********************************************************************
+# Format of output for the console.  (See docs for formats)
+wrapper.console.format=PM
+
+# Log Level for console output.  (See docs for log levels)
+wrapper.console.loglevel=INFO
+
+# Log file to use for wrapper output logging.
+wrapper.logfile=%KARAF_DATA%/log/wrapper.log
+
+# Format of output for the log file.  (See docs for formats)
+wrapper.logfile.format=LPTM
+
+# Log Level for log file output.  (See docs for log levels)
+wrapper.logfile.loglevel=INFO
+
+# Maximum size that the log file will be allowed to grow to before
+#  the log is rolled. Size is specified in bytes.  The default value
+#  of 0, disables log rolling.  May abbreviate with the 'k' (kb) or
+#  'm' (mb) suffix.  For example: 10m = 10 megabytes.
+wrapper.logfile.maxsize=10m
+
+# Maximum number of rolled log files which will be allowed before old
+#  files are deleted.  The default value of 0 implies no limit.
+wrapper.logfile.maxfiles=5
+
+# Log Level for sys/event log output.  (See docs for log levels)
+wrapper.syslog.loglevel=NONE
+
+#********************************************************************
+# Wrapper Windows Properties
+#********************************************************************
+# Title to use when running as a console
+wrapper.console.title=${name}
+
+#********************************************************************
+# Wrapper Windows NT/2000/XP Service Properties
+#********************************************************************
+# WARNING - Do not modify any of these properties when an application
+#  using this configuration file has been installed as a service.
+#  Please uninstall the service before modifying this section.  The
+#  service can then be reinstalled.
+
+# Name of the service
+wrapper.ntservice.name=${name}
+
+# Display name of the service
+wrapper.ntservice.displayname=${displayName}
+
+# Description of the service
+wrapper.ntservice.description=${description}
+
+# Service dependencies.  Add dependencies as needed starting from 1
+wrapper.ntservice.dependency.1=
+
+# Mode in which the service is installed.  AUTO_START or DEMAND_START
+wrapper.ntservice.starttype=${startType}
+
+# Allow the service to interact with the desktop.
+wrapper.ntservice.interactive=false

http://git-wip-us.apache.org/repos/asf/karaf/blob/4182735c/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/windows/karaf-service.bat
----------------------------------------------------------------------
diff --git a/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/windows/karaf-service.bat b/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/windows/karaf-service.bat
new file mode 100644
index 0000000..0dd0474
--- /dev/null
+++ b/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/windows/karaf-service.bat
@@ -0,0 +1,51 @@
+@echo off
+
+REM ------------------------------------------------------------------------
+REM Licensed to the Apache Software Foundation (ASF) under one or more
+REM contributor license agreements.  See the NOTICE file distributed with
+REM this work for additional information regarding copyright ownership.
+REM The ASF licenses this file to You under the Apache License, Version 2.0
+REM (the "License"); you may not use this file except in compliance with
+REM the License.  You may obtain a copy of the License at
+REM
+REM http://www.apache.org/licenses/LICENSE-2.0
+REM
+REM Unless required by applicable law or agreed to in writing, software
+REM distributed under the License is distributed on an "AS IS" BASIS,
+REM WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+REM See the License for the specific language governing permissions and
+REM limitations under the License.
+REM ------------------------------------------------------------------------
+
+setlocal
+
+set APP_NAME=${name}
+set APP_LONG_NAME=${displayName}
+set APP_BASE=${karaf.base}
+set APP_ETC=${karaf.etc}
+
+if ""%1"" == ""run"" goto doRun
+if ""%1"" == ""install"" goto doInstall
+if ""%1"" == ""remove"" goto doRemove
+
+echo Usage:  karaf-service ( commands ... )
+echo commands:
+echo   run               Start %APP_NAME% in the current console
+echo   install           Install %APP_NAME% as a Windows service
+echo   remove            Remove the %APP_NAME% Windows service
+goto end
+
+:doRun
+"%APP_BASE%\bin\%APP_NAME%-wrapper.exe" -c "%APP_ETC%\%APP_NAME%-wrapper.conf"
+goto end
+
+:doInstall
+"%APP_BASE%\bin\%APP_NAME%-wrapper.exe" -i "%APP_ETC%\%APP_NAME%-wrapper.conf"
+goto end
+
+:doRemove
+"%APP_BASE%\bin\%APP_NAME%-wrapper.exe" -r "%APP_ETC%\%APP_NAME%-wrapper.conf"
+goto end
+
+:end
+if not "%PAUSE%" == "" pause

http://git-wip-us.apache.org/repos/asf/karaf/blob/4182735c/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/windows/karaf-wrapper.conf
----------------------------------------------------------------------
diff --git a/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/windows/karaf-wrapper.conf b/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/windows/karaf-wrapper.conf
new file mode 100644
index 0000000..def40f7
--- /dev/null
+++ b/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/windows/karaf-wrapper.conf
@@ -0,0 +1,135 @@
+# ------------------------------------------------------------------------
+# 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.
+# ------------------------------------------------------------------------
+
+#********************************************************************
+# Wrapper Properties
+#********************************************************************
+set.default.JAVA_HOME=${java.home}
+set.default.KARAF_HOME=${karaf.home}
+set.default.KARAF_BASE=${karaf.base}
+set.default.KARAF_DATA=${karaf.data}
+set.default.KARAF_ETC=${karaf.etc}
+
+# Java Application
+wrapper.working.dir=%KARAF_BASE%
+wrapper.java.command=%JAVA_HOME%/bin/java
+wrapper.java.mainclass=org.apache.karaf.wrapper.internal.Main
+wrapper.java.classpath.1=%KARAF_HOME%/lib/karaf-wrapper.jar
+wrapper.java.classpath.2=%KARAF_HOME%/lib/karaf.jar
+wrapper.java.classpath.3=%KARAF_HOME%/lib/karaf-jmx-boot.jar
+wrapper.java.classpath.4=%KARAF_HOME%/lib/karaf-jaas-boot.jar
+wrapper.java.classpath.5=%KARAF_HOME%/lib/karaf-wrapper-main.jar
+wrapper.java.classpath.6=%KARAF_HOME%/lib/karaf-org.osgi.core.jar
+wrapper.java.library.path.1=%KARAF_HOME%/lib/
+
+# Application Parameters.  Add parameters as needed starting from 1
+#wrapper.app.parameter.1=
+
+# JVM Parameters
+# note that n is the parameter number starting from 1.
+wrapper.java.additional.1=-Dkaraf.home="%KARAF_HOME%"
+wrapper.java.additional.2=-Dkaraf.base="%KARAF_BASE%"
+wrapper.java.additional.3=-Dkaraf.data="%KARAF_DATA%"
+wrapper.java.additional.4=-Dkaraf.etc="%KARAF_ETC%"
+wrapper.java.additional.5=-Dcom.sun.management.jmxremote
+wrapper.java.additional.6=-Djavax.management.builder.initial=org.apache.karaf.management.boot.KarafMBeanServerBuilder
+wrapper.java.additional.7=-Dkaraf.startLocalConsole=false
+wrapper.java.additional.8=-Dkaraf.startRemoteShell=true
+wrapper.java.additional.9=-Djava.endorsed.dirs="%JAVA_HOME%/jre/lib/endorsed;%JAVA_HOME%/lib/endorsed;%KARAF_HOME%/lib/endorsed"
+wrapper.java.additional.10=-Djava.ext.dirs="%JAVA_HOME%/jre/lib/ext;%JAVA_HOME%/lib/ext;%KARAF_HOME%/lib/ext"
+
+# Uncomment to enable jmx
+#wrapper.java.additional.n=-Dcom.sun.management.jmxremote.port=1616
+#wrapper.java.additional.n=-Dcom.sun.management.jmxremote.authenticate=false
+#wrapper.java.additional.n=-Dcom.sun.management.jmxremote.ssl=false
+
+# Uncomment to enable YourKit profiling
+#wrapper.java.additional.n=-Xrunyjpagent
+
+# Uncomment to enable remote debugging
+#wrapper.java.additional.n=-Xdebug -Xnoagent -Djava.compiler=NONE
+#wrapper.java.additional.n=-Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005
+
+# Initial Java Heap Size (in MB)
+#wrapper.java.initmemory=3
+
+# Maximum Java Heap Size (in MB)
+wrapper.java.maxmemory=512
+
+
+#********************************************************************
+# Wrapper Logging Properties
+#********************************************************************
+# Format of output for the console.  (See docs for formats)
+wrapper.console.format=PM
+
+# Log Level for console output.  (See docs for log levels)
+wrapper.console.loglevel=INFO
+
+# Log file to use for wrapper output logging.
+wrapper.logfile=%KARAF_DATA%/log/wrapper.log
+
+# Format of output for the log file.  (See docs for formats)
+wrapper.logfile.format=LPTM
+
+# Log Level for log file output.  (See docs for log levels)
+wrapper.logfile.loglevel=INFO
+
+# Maximum size that the log file will be allowed to grow to before
+#  the log is rolled. Size is specified in bytes.  The default value
+#  of 0, disables log rolling.  May abbreviate with the 'k' (kb) or
+#  'm' (mb) suffix.  For example: 10m = 10 megabytes.
+wrapper.logfile.maxsize=10m
+
+# Maximum number of rolled log files which will be allowed before old
+#  files are deleted.  The default value of 0 implies no limit.
+wrapper.logfile.maxfiles=5
+
+# Log Level for sys/event log output.  (See docs for log levels)
+wrapper.syslog.loglevel=NONE
+
+#********************************************************************
+# Wrapper Windows Properties
+#********************************************************************
+# Title to use when running as a console
+wrapper.console.title=${name}
+
+#********************************************************************
+# Wrapper Windows NT/2000/XP Service Properties
+#********************************************************************
+# WARNING - Do not modify any of these properties when an application
+#  using this configuration file has been installed as a service.
+#  Please uninstall the service before modifying this section.  The
+#  service can then be reinstalled.
+
+# Name of the service
+wrapper.ntservice.name=${name}
+
+# Display name of the service
+wrapper.ntservice.displayname=${displayName}
+
+# Description of the service
+wrapper.ntservice.description=${description}
+
+# Service dependencies.  Add dependencies as needed starting from 1
+wrapper.ntservice.dependency.1=
+
+# Mode in which the service is installed.  AUTO_START or DEMAND_START
+wrapper.ntservice.starttype=${startType}
+
+# Allow the service to interact with the desktop.
+wrapper.ntservice.interactive=false

http://git-wip-us.apache.org/repos/asf/karaf/blob/4182735c/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/windows/karaf-wrapper.exe
----------------------------------------------------------------------
diff --git a/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/windows/karaf-wrapper.exe b/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/windows/karaf-wrapper.exe
new file mode 100644
index 0000000..b4cfc55
Binary files /dev/null and b/wrapper/src/main/resources/org/apache/karaf/wrapper/internal/windows/karaf-wrapper.exe differ


[09/59] [abbrv] [KARAF-2852] Merge features/core and features/command

Posted by gn...@apache.org.
http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/core/src/test/java/org/apache/karaf/features/internal/service/BundleManagerTest.java
----------------------------------------------------------------------
diff --git a/features/core/src/test/java/org/apache/karaf/features/internal/service/BundleManagerTest.java b/features/core/src/test/java/org/apache/karaf/features/internal/service/BundleManagerTest.java
deleted file mode 100644
index bed8104..0000000
--- a/features/core/src/test/java/org/apache/karaf/features/internal/service/BundleManagerTest.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * 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.karaf.features.internal.service;
-
-import org.apache.karaf.features.TestBase;
-
-public class BundleManagerTest extends TestBase {
-
-    /*
-    @Test
-    public void testfindBundlestoRefreshWithHostToRefresh() throws Exception {
-        Bundle hostBundle = createDummyBundle(12345l, "Host", headers());
-        Bundle fragmentBundle = createDummyBundle(54321l, "fragment", headers(Constants.FRAGMENT_HOST, "Host"));
-
-        BundleContext bundleContext = EasyMock.createMock(BundleContext.class);
-        BundleManager bundleManager = new BundleManager(bundleContext);
-
-        // Host was already installed, fragment is new
-        Set<Bundle> existing = new HashSet<Bundle>(Arrays.asList(hostBundle, fragmentBundle));
-        Set<Bundle> installed = new HashSet<Bundle>(Arrays.asList(fragmentBundle));
-        
-        replay(bundleContext);
-        Set<Bundle> bundles = bundleManager.findBundlesWithFragmentsToRefresh(existing, installed);
-        EasyMock.verify(bundleContext);
-
-        Assert.assertEquals(1, bundles.size());
-        Assert.assertEquals(hostBundle, bundles.iterator().next());
-    }
-    
-    @Test
-    public void testfindBundlestoRefreshWithOptionalPackages() throws Exception {
-        Bundle exporterBundle = createDummyBundle(12345l, "exporter", headers(Constants.EXPORT_PACKAGE, "org.my.package"));
-        Bundle importerBundle = createDummyBundle(54321l, "importer", headers(Constants.IMPORT_PACKAGE, "org.my.package;resolution:=optional"));
-
-        BundleContext bundleContext = EasyMock.createMock(BundleContext.class);
-        BundleManager bundleManager = new BundleManager(bundleContext);
-
-        // Importer was already installed, exporter is new
-        Set<Bundle> existing = new HashSet<Bundle>(Arrays.asList(importerBundle, exporterBundle));
-        Set<Bundle> installed = new HashSet<Bundle>(Arrays.asList(exporterBundle));
-        
-        replay(bundleContext);
-        Set<Bundle> bundles = bundleManager.findBundlesWithOptionalPackagesToRefresh(existing, installed);
-        EasyMock.verify(bundleContext);
-
-        Assert.assertEquals(1, bundles.size());
-        Assert.assertEquals(importerBundle, bundles.iterator().next());
-    }
-    */
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/core/src/test/java/org/apache/karaf/features/internal/service/FeaturesServiceImplTest.java
----------------------------------------------------------------------
diff --git a/features/core/src/test/java/org/apache/karaf/features/internal/service/FeaturesServiceImplTest.java b/features/core/src/test/java/org/apache/karaf/features/internal/service/FeaturesServiceImplTest.java
deleted file mode 100644
index b8b5fc0..0000000
--- a/features/core/src/test/java/org/apache/karaf/features/internal/service/FeaturesServiceImplTest.java
+++ /dev/null
@@ -1,167 +0,0 @@
-/*
- * 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.karaf.features.internal.service;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertSame;
-import static org.junit.Assert.fail;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.util.Map;
-
-import org.apache.karaf.features.Feature;
-import org.apache.karaf.features.TestBase;
-import org.junit.Before;
-import org.junit.Test;
-
-/**
- * Test cases for {@link org.apache.karaf.features.internal.service.FeaturesServiceImpl}
- */
-public class FeaturesServiceImplTest extends TestBase {
-    
-    File dataFile;
-
-    @Before
-    public void setUp() throws IOException {
-        dataFile = File.createTempFile("features", null, null);
-    }
-
-    @Test
-    public void testGetFeature() throws Exception {
-        Feature transactionFeature = feature("transaction", "1.0.0");
-        final Map<String, Map<String, Feature>> features = features(transactionFeature);
-        final FeaturesServiceImpl impl = new FeaturesServiceImpl(null, null, new Storage(), null, null, null, "", null, null, null) {
-            protected Map<String,Map<String,Feature>> getFeatures() throws Exception {
-                return features;
-            }
-        };
-        assertNotNull(impl.getFeature("transaction", org.apache.karaf.features.internal.model.Feature.DEFAULT_VERSION));
-        assertSame(transactionFeature, impl.getFeature("transaction", org.apache.karaf.features.internal.model.Feature.DEFAULT_VERSION));
-    }
-    
-    @Test
-    public void testGetFeatureStripVersion() throws Exception {
-        final FeaturesServiceImpl impl = new FeaturesServiceImpl(null, null, new Storage(), null, null, null, "", null, null, null) {
-            protected Map<String,Map<String,Feature>> getFeatures() throws Exception {
-                return features(feature("transaction", "1.0.0"));
-            }
-        };
-        Feature feature = impl.getFeature("transaction", "  1.0.0  ");
-        assertNotNull(feature);
-        assertSame("transaction", feature.getName());
-    }
-    
-    @Test
-    public void testGetFeatureNotAvailable() throws Exception {
-        final FeaturesServiceImpl impl = new FeaturesServiceImpl(null, null, new Storage(), null, null, null, "", null, null, null) {
-            protected Map<String,Map<String,Feature>> getFeatures() throws Exception {
-                return features(feature("transaction", "1.0.0"));
-            }
-        };
-        assertNull(impl.getFeature("activemq", org.apache.karaf.features.internal.model.Feature.DEFAULT_VERSION));
-    }
-    
-    @Test
-    public void testGetFeatureHighestAvailable() throws Exception {
-        final Map<String, Map<String, Feature>> features = features(
-                feature("transaction", "1.0.0"),
-                feature("transaction", "2.0.0")
-        );
-        final FeaturesServiceImpl impl = new FeaturesServiceImpl(null, null, new Storage(), null, null, null, "", null, null, null) {
-            protected Map<String,Map<String,Feature>> getFeatures() throws Exception {
-                return features;
-            }
-        };
-        assertNotNull(impl.getFeature("transaction", org.apache.karaf.features.internal.model.Feature.DEFAULT_VERSION));
-        assertSame("2.0.0", impl.getFeature("transaction", org.apache.karaf.features.internal.model.Feature.DEFAULT_VERSION).getVersion());
-    }
-
-    /**
-     * This test ensures that every feature get installed only once, even if it appears multiple times in the list
-     * of transitive feature dependencies (KARAF-1600)
-     */
-    /*
-    @Test
-    @SuppressWarnings("unchecked")
-    public void testNoDuplicateFeaturesInstallation() throws Exception {
-        final List<Feature> installed = new LinkedList<Feature>();
-        BundleManager bundleManager = EasyMock.createMock(BundleManager.class);
-        expect(bundleManager.installBundleIfNeeded(EasyMock.anyObject(String.class), EasyMock.anyInt(), EasyMock.anyObject(String.class)))
-            .andReturn(new BundleInstallerResult(createDummyBundle(1l, "", headers()), true)).anyTimes();
-        bundleManager.refreshBundles(EasyMock.anyObject(Set.class), EasyMock.anyObject(Set.class), EasyMock.anyObject(EnumSet.class));
-        EasyMock.expectLastCall();
-        final FeaturesServiceImpl impl = new FeaturesServiceImpl(bundleManager, null) {
-            // override methods which refers to bundle context to avoid mocking everything
-            @Override
-            protected boolean loadState() {
-                return true;
-            }
-
-            @Override
-            protected void saveState() {
-
-            }
-
-            @Override
-            protected void doInstallFeature(InstallationState state, Feature feature, boolean verbose) throws Exception {
-                installed.add(feature);
-
-                super.doInstallFeature(state, feature, verbose);
-            }
-
-        };
-        replay(bundleManager);
-        impl.addRepository(getClass().getResource("repo2.xml").toURI());
-        impl.installFeature("all");
-
-        // copying the features to a set to filter out the duplicates
-        Set<Feature> noduplicates = new HashSet<Feature>();
-        noduplicates.addAll(installed);
-
-        assertEquals("Every feature should only have been installed once", installed.size(), noduplicates.size());
-    }
-
-    @Test
-    public void testGetOptionalImportsOnly() {
-        BundleManager bundleManager = new BundleManager(null, 0l);
-
-        List<Clause> result = bundleManager.getOptionalImports("org.apache.karaf,org.apache.karaf.optional;resolution:=optional");
-        assertEquals("One optional import expected", 1, result.size());
-        assertEquals("org.apache.karaf.optional", result.get(0).getName());
-
-        result = bundleManager.getOptionalImports(null);
-        assertNotNull(result);
-        assertEquals("No optional imports expected", 0, result.size());
-    }
-    */
-
-    static class Storage extends StateStorage {
-        @Override
-        protected InputStream getInputStream() throws IOException {
-            return null;
-        }
-        @Override
-        protected OutputStream getOutputStream() throws IOException {
-            return null;
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/core/src/test/java/org/apache/karaf/features/internal/service/FeaturesValidationTest.java
----------------------------------------------------------------------
diff --git a/features/core/src/test/java/org/apache/karaf/features/internal/service/FeaturesValidationTest.java b/features/core/src/test/java/org/apache/karaf/features/internal/service/FeaturesValidationTest.java
deleted file mode 100644
index f3ca2e6..0000000
--- a/features/core/src/test/java/org/apache/karaf/features/internal/service/FeaturesValidationTest.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * 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.karaf.features.internal.service;
-
-import org.junit.Test;
-
-import static org.junit.Assert.fail;
-
-public class FeaturesValidationTest {
-
-    @Test
-    public void testNoNs() throws Exception {
-        FeatureValidationUtil.validate(getClass().getResource("f01.xml").toURI());
-    }
-
-    @Test
-    public void testNs10() throws Exception {
-        FeatureValidationUtil.validate(getClass().getResource("f02.xml").toURI());
-    }
-
-    @Test
-    public void testNs10NoName() throws Exception {
-        FeatureValidationUtil.validate(getClass().getResource("f03.xml").toURI());
-    }
-
-    @Test
-    public void testNs11() throws Exception {
-        FeatureValidationUtil.validate(getClass().getResource("f04.xml").toURI());
-    }
-
-    @Test
-    public void testNs12() throws Exception {
-        FeatureValidationUtil.validate(getClass().getResource("f06.xml").toURI());
-    }
-
-    @Test
-    public void testNs11NoName() throws Exception {
-        try {
-            FeatureValidationUtil.validate(getClass().getResource("f05.xml").toURI());
-            fail("Validation should have failed");
-        } catch (Exception e) {
-            // ok
-        }
-    }
-
-    @Test
-    public void testNs13() throws Exception {
-        FeatureValidationUtil.validate(getClass().getResource("f07.xml").toURI());
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/core/src/test/java/org/apache/karaf/features/internal/service/OverridesTest.java
----------------------------------------------------------------------
diff --git a/features/core/src/test/java/org/apache/karaf/features/internal/service/OverridesTest.java b/features/core/src/test/java/org/apache/karaf/features/internal/service/OverridesTest.java
deleted file mode 100644
index c4976cf..0000000
--- a/features/core/src/test/java/org/apache/karaf/features/internal/service/OverridesTest.java
+++ /dev/null
@@ -1,208 +0,0 @@
-/*
- * 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.karaf.features.internal.service;
-
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.FileWriter;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.Writer;
-import java.net.URI;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import org.apache.felix.utils.manifest.Clause;
-import org.apache.felix.utils.manifest.Parser;
-import org.apache.karaf.features.BundleInfo;
-import org.apache.karaf.features.internal.model.Bundle;
-import org.apache.karaf.features.internal.resolver.ResourceBuilder;
-import org.apache.karaf.features.internal.resolver.UriNamespace;
-import org.junit.Before;
-import org.junit.Test;
-import org.ops4j.pax.tinybundles.core.TinyBundles;
-import org.osgi.framework.BundleException;
-import org.osgi.resource.Resource;
-
-import static org.apache.karaf.features.internal.resolver.UriNamespace.getUri;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-
-public class OverridesTest {
-
-    private String bsn = "bsn";
-    private Resource b100;
-    private Resource b101;
-    private Resource b102;
-    private Resource b110;
-    private Resource c100;
-    private Resource c101;
-    private Resource c110;
-
-    @Before
-    public void setUp() throws BundleException {
-        b100 = resource("karaf-100.jar")
-                .set("Bundle-SymbolicName", bsn)
-                .set("Bundle-Version", "1.0.0")
-                .build();
-
-        b101 = resource("karaf-101.jar")
-                .set("Bundle-SymbolicName", bsn)
-                .set("Bundle-Version", "1.0.1")
-                .build();
-
-        b102 = resource("karaf-102.jar")
-                .set("Bundle-SymbolicName", bsn)
-                .set("Bundle-Version", "1.0.2")
-                .build();
-
-        b110 = resource("karaf-110.jar")
-                .set("Bundle-SymbolicName", bsn)
-                .set("Bundle-Version", "1.1.0")
-                .build();
-
-        c100 = resource("karafc-100.jar")
-                .set("Bundle-SymbolicName", bsn)
-                .set("Bundle-Version", "1.0.0")
-                .set("Bundle-Vendor", "Apache")
-                .build();
-
-        c101 = resource("karafc-101.jar")
-                .set("Bundle-SymbolicName", bsn)
-                .set("Bundle-Version", "1.0.1")
-                .set("Bundle-Vendor", "NotApache")
-                .build();
-
-        c110 = resource("karafc-110.jar")
-                .set("Bundle-SymbolicName", bsn)
-                .set("Bundle-Version", "1.1.0")
-                .set("Bundle-Vendor", "NotApache")
-                .build();
-    }
-
-    @Test
-    public void testDifferentVendors() throws IOException {
-        Map<String, Resource> map = asResourceMap(c100, c101, c110);
-        assertEquals(c100, map.get(getUri(c100)));
-        Overrides.override(map, Arrays.asList(getUri(c101), getUri(c110)));
-        assertEquals(c101, map.get(getUri(c100)));
-    }
-
-    @Test
-    public void testMatching101() throws IOException {
-        Map<String, Resource> map = asResourceMap(b100, b101, b110);
-        assertEquals(b100, map.get(getUri(b100)));
-        Overrides.override(map, Arrays.asList(getUri(b101), getUri(b110)));
-        assertEquals(b101, map.get(getUri(b100)));
-    }
-
-    @Test
-    public void testMatching102() throws IOException {
-        Map<String, Resource> map = asResourceMap(b100, b101, b102, b110);
-        assertEquals(b100, map.get(getUri(b100)));
-        Overrides.override(map, Arrays.asList(getUri(b101), getUri(b102), getUri(b110)));
-        assertEquals(b102, map.get(getUri(b100)));
-    }
-
-    @Test
-    public void testMatchingRange() throws IOException {
-        Map<String, Resource> map = asResourceMap(b100, b101, b110);
-        assertEquals(b100, map.get(getUri(b100)));
-        Overrides.override(map, Arrays.asList(getUri(b101), getUri(b110) + ";range=\"[1.0, 2.0)\""));
-        assertEquals(b110, map.get(getUri(b100)));
-    }
-
-    @Test
-    public void testNotMatching() throws IOException {
-        Map<String, Resource> map = asResourceMap(b100, b110);
-        assertEquals(b100, map.get(getUri(b100)));
-        Overrides.override(map, Arrays.asList(getUri(b110)));
-        assertEquals(b100, map.get(getUri(b100)));
-    }
-
-    @Test
-    public void testLoadOverrides() {
-        Set<String> overrides = Overrides.loadOverrides(getClass().getResource("overrides.properties").toExternalForm());
-        assertEquals(2, overrides.size());
-
-        Clause karafAdminCommand = null;
-        Clause karafAdminCore = null;
-        for (Clause clause : Parser.parseClauses(overrides.toArray(new String[overrides.size()]))) {
-            if (clause.getName().equals("mvn:org.apache.karaf.admin/org.apache.karaf.admin.command/2.3.0.redhat-61033X")) {
-                karafAdminCommand = clause;
-            }
-            if (clause.getName().equals("mvn:org.apache.karaf.admin/org.apache.karaf.admin.core/2.3.0.redhat-61033X")) {
-                karafAdminCore = clause;
-            }
-        }
-        assertNotNull("Missing admin.command bundle override", karafAdminCommand);
-        assertNotNull("Missing admin.core bundle override", karafAdminCore);
-        assertNotNull("Missing range on admin.core override", karafAdminCore.getAttribute(Overrides.OVERRIDE_RANGE));
-    }
-
-    /**
-     * Copies the content of {@link java.io.InputStream} to {@link java.io.OutputStream}.
-     *
-     * @param input
-     * @param output
-     * @throws java.io.IOException
-     */
-    private void copy(final InputStream input, final OutputStream output) throws IOException {
-        byte[] buffer = new byte[1024 * 16];
-        int n;
-        while (-1 != (n = input.read(buffer))) {
-            output.write(buffer, 0, n);
-            output.flush();
-        }
-        input.close();
-        output.close();
-    }
-
-    static Builder resource(String uri) {
-        return new Builder(uri);
-    }
-
-    static Map<String, Resource> asResourceMap(Resource... resources) {
-        Map<String, Resource> map = new HashMap<String, Resource>();
-        for (Resource resource : resources) {
-            map.put(getUri(resource), resource);
-        }
-        return map;
-    }
-
-    static class Builder {
-        String uri;
-        Map<String,String> headers = new HashMap<String,String>();
-        Builder(String uri) {
-            this.uri = uri;
-            this.headers.put("Bundle-ManifestVersion", "2");
-        }
-        Builder set(String key, String value) {
-            this.headers.put(key, value);
-            return this;
-        }
-        Resource build() throws BundleException {
-            return ResourceBuilder.build(uri, headers);
-        }
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/core/src/test/resources/org/apache/karaf/features/internal/service/f01.xml
----------------------------------------------------------------------
diff --git a/features/core/src/test/resources/org/apache/karaf/features/internal/service/f01.xml b/features/core/src/test/resources/org/apache/karaf/features/internal/service/f01.xml
deleted file mode 100644
index 814c722..0000000
--- a/features/core/src/test/resources/org/apache/karaf/features/internal/service/f01.xml
+++ /dev/null
@@ -1,92 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-      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.
--->
-<features name="karaf-2.0.0">
-    <feature name="spring" version="3.0.3.RELEASE">
-        <bundle>mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.aopalliance/1.0_6</bundle>
-        <bundle>mvn:org.springframework/spring-core/3.0.3.RELEASE</bundle>
-        <bundle>mvn:org.springframework/spring-asm/3.0.3.RELEASE</bundle>
-        <bundle>mvn:org.springframework/spring-expression/3.0.3.RELEASE</bundle>
-        <bundle>mvn:org.springframework/spring-beans/3.0.3.RELEASE</bundle>
-        <bundle>mvn:org.springframework/spring-aop/3.0.3.RELEASE</bundle>
-        <bundle>mvn:org.springframework/spring-context/3.0.3.RELEASE</bundle>
-        <bundle>mvn:org.springframework/spring-context-support/3.0.3.RELEASE</bundle>
-    </feature>
-    <feature name="spring-dm" version="1.2.0">
-        <feature version="3.0.3.RELEASE">spring</feature>
-        <bundle>mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.cglib/2.2.2_1</bundle>
-        <bundle>mvn:org.springframework.osgi/spring-osgi-io/1.2.0</bundle>
-        <bundle>mvn:org.springframework.osgi/spring-osgi-core/1.2.0</bundle>
-        <bundle>mvn:org.springframework.osgi/spring-osgi-extender/1.2.0</bundle>
-        <bundle>mvn:org.springframework.osgi/spring-osgi-annotation/1.2.0</bundle>
-        <bundle>mvn:org.apache.karaf.deployer/org.apache.karaf.deployer.spring/2.0.0</bundle>
-    </feature>
-    <feature name="wrapper" version="2.0.0">
-        <bundle>mvn:org.apache.karaf.shell/org.apache.karaf.shell.wrapper/2.0.0</bundle>
-    </feature>
-    <feature name="obr" version="2.0.0">
-        <bundle>mvn:org.apache.felix/org.apache.felix.bundlerepository/1.6.4</bundle>
-        <bundle>mvn:org.apache.karaf.shell/org.apache.karaf.shell.obr/2.0.0</bundle>
-        <bundle>mvn:org.apache.karaf.features/org.apache.karaf.features.obr/2.0.0</bundle>
-    </feature>
-    <feature name="http" version="2.0.0">
-        <config name="org.ops4j.pax.web">
-            org.osgi.service.http.port=8181
-        </config>
-        <bundle>mvn:org.apache.geronimo.specs/geronimo-servlet_2.5_spec/1.1.2</bundle>
-        <bundle>mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.jetty-bundle/6.1.22_1</bundle>
-        <bundle>mvn:org.ops4j.pax.web/pax-web-api/0.7.2</bundle>
-        <bundle>mvn:org.ops4j.pax.web/pax-web-spi/0.7.2</bundle>
-        <bundle>mvn:org.ops4j.pax.web/pax-web-runtime/0.7.2</bundle>
-        <bundle>mvn:org.ops4j.pax.web/pax-web-jetty/0.7.2</bundle>
-    </feature>
-    <feature name="war" version="2.0.0">
-        <feature version="2.0.0">http</feature>
-        <bundle>mvn:org.ops4j.pax.web/pax-web-jsp/0.7.2</bundle>
-        <bundle>mvn:org.ops4j.pax.web/pax-web-extender-war/0.7.2</bundle>
-        <bundle>mvn:org.ops4j.pax.web/pax-web-extender-whiteboard/0.7.2</bundle>
-        <bundle>mvn:org.ops4j.pax.url/pax-url-war/1.1.3</bundle>
-        <bundle>mvn:org.apache.karaf.deployer/org.apache.karaf.deployer.war/2.0.0</bundle>
-    </feature>
-    <feature name="webconsole" version="2.0.0">
-        <feature version="2.0.0">http</feature>
-        <config name="org.apache.karaf.webconsole">
-            realm=karaf
-        </config>
-        <bundle>mvn:org.apache.felix/org.apache.felix.metatype/1.0.2</bundle>
-        <bundle>mvn:org.apache.karaf.webconsole/org.apache.karaf.webconsole.branding/2.0.0</bundle>
-        <bundle>mvn:org.apache.felix/org.apache.felix.webconsole/3.1.0</bundle>
-        <bundle>mvn:org.apache.karaf.webconsole/org.apache.karaf.webconsole.admin/2.0.0</bundle>
-        <bundle>mvn:org.apache.karaf.webconsole/org.apache.karaf.webconsole.features/2.0.0</bundle>
-        <bundle>mvn:org.apache.karaf.webconsole/org.apache.karaf.webconsole.gogo/2.0.0</bundle>
-    </feature>
-    <feature name="ssh" version="2.0.0">
-        <config name="org.apache.karaf.shell.ssh">
-            sshPort=8101
-            sshHost=0.0.0.0
-            sshRealm=karaf
-        </config>
-        <bundle>mvn:org.apache.mina/mina-core/2.0.0-RC1</bundle>
-        <bundle>mvn:org.apache.sshd/sshd-core/0.4.0</bundle>
-        <bundle>mvn:org.apache.karaf.shell/org.apache.karaf.shell.ssh/2.0.0</bundle>
-    </feature>
-    <feature name="management" version="2.0.0">
-        <bundle>mvn:org.apache.karaf/org.apache.karaf.management/2.0.0</bundle>
-        <bundle>mvn:org.apache.aries.jmx/org.apache.aries.jmx/0.1-r964701</bundle>
-        <bundle>mvn:org.apache.aries.jmx/org.apache.aries.jmx.blueprint/0.1-r964701</bundle>
-    </feature>
-</features>

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/core/src/test/resources/org/apache/karaf/features/internal/service/f02.xml
----------------------------------------------------------------------
diff --git a/features/core/src/test/resources/org/apache/karaf/features/internal/service/f02.xml b/features/core/src/test/resources/org/apache/karaf/features/internal/service/f02.xml
deleted file mode 100644
index 1578faa..0000000
--- a/features/core/src/test/resources/org/apache/karaf/features/internal/service/f02.xml
+++ /dev/null
@@ -1,164 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-      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.
--->
-<features name="karaf-2.2.0" xmlns="http://karaf.apache.org/xmlns/features/v1.0.0">
-    <feature name="spring" version="2.5.6.SEC02" resolver="(obr)">
-        <bundle dependency='true'>mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.aopalliance/1.0_6</bundle>
-        <bundle>mvn:org.springframework/spring-core/2.5.6.SEC02</bundle>
-        <bundle>mvn:org.springframework/spring-beans/2.5.6.SEC02</bundle>
-        <bundle>mvn:org.springframework/spring-aop/2.5.6.SEC02</bundle>
-        <bundle>mvn:org.springframework/spring-context/2.5.6.SEC02</bundle>
-        <bundle>mvn:org.springframework/spring-context-support/2.5.6.SEC02</bundle>
-    </feature>
-    <feature name="spring-web" version="2.5.6.SEC02" resolver="(obr)">
-    	<feature version="2.5.6.SEC02">spring</feature>
-    	<feature version="2.2.0">http</feature>
-    	<bundle>mvn:org.springframework/spring-web/2.5.6.SEC02</bundle>
-		<bundle>mvn:org.springframework/spring-webmvc/2.5.6.SEC02</bundle>
-    </feature>
-    <feature name="spring" version="3.0.5.RELEASE" resolver="(obr)">
-        <bundle dependency='true'>mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.aopalliance/1.0_6</bundle>
-        <bundle>mvn:org.springframework/spring-core/3.0.5.RELEASE</bundle>
-        <bundle>mvn:org.springframework/spring-asm/3.0.5.RELEASE</bundle>
-        <bundle>mvn:org.springframework/spring-expression/3.0.5.RELEASE</bundle>
-        <bundle>mvn:org.springframework/spring-beans/3.0.5.RELEASE</bundle>
-        <bundle>mvn:org.springframework/spring-aop/3.0.5.RELEASE</bundle>
-        <bundle>mvn:org.springframework/spring-context/3.0.5.RELEASE</bundle>
-        <bundle>mvn:org.springframework/spring-context-support/3.0.5.RELEASE</bundle>
-    </feature>
-    <feature name="spring-web" version="3.0.5.RELEASE" resolver="(obr)">
-    	<feature version="3.0.5.RELEASE">spring</feature>
-    	<feature version="2.2.0">http</feature>
-    	<bundle>mvn:org.springframework/spring-web/3.0.5.RELEASE</bundle>
-		<bundle>mvn:org.springframework/spring-webmvc/3.0.5.RELEASE</bundle>
-    </feature>
-    <feature name="spring-dm" version="1.2.1" resolver="(obr)">
-        <feature version="[2.5.6,4)">spring</feature>
-        <bundle dependency='true'>mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.cglib/2.2.2_1</bundle>
-        <bundle>mvn:org.springframework.osgi/spring-osgi-io/1.2.1</bundle>
-        <bundle>mvn:org.springframework.osgi/spring-osgi-core/1.2.1</bundle>
-        <bundle>mvn:org.springframework.osgi/spring-osgi-extender/1.2.1</bundle>
-        <bundle>mvn:org.springframework.osgi/spring-osgi-annotation/1.2.1</bundle>
-        <bundle>mvn:org.apache.karaf.deployer/org.apache.karaf.deployer.spring/2.2.0</bundle>
-    </feature>
-    <feature name="spring-dm-web" version="1.2.1" resolver="(obr)">
-    	<feature version="1.2.1">spring-dm</feature>
-    	<feature version="[2.5.6,4)">spring-web</feature>
-    	<feature version="2.2.0">http</feature>
-		<bundle>mvn:org.springframework.osgi/spring-osgi-web/1.2.1</bundle>
-    </feature>
-    <feature name="wrapper" version="2.2.0">
-        <bundle>mvn:org.apache.karaf.shell/org.apache.karaf.shell.wrapper/2.2.0</bundle>
-    </feature>
-    <feature name="obr" version="2.2.0">
-        <bundle>mvn:org.apache.felix/org.apache.felix.bundlerepository/1.6.4</bundle>
-        <bundle>mvn:org.apache.karaf.shell/org.apache.karaf.shell.obr/2.2.0</bundle>
-        <bundle>mvn:org.apache.karaf.features/org.apache.karaf.features.obr/2.2.0</bundle>
-    </feature>
-    <feature name="config" version="2.2.0">
-        <bundle start-level='30'>mvn:org.apache.karaf.shell/org.apache.karaf.shell.config/2.2.0</bundle>
-    </feature>
-	<feature name="jetty" version="7.2.2.v20101205" resolver="(obr)">
-		<bundle dependency='true'>mvn:org.apache.geronimo.specs/geronimo-servlet_2.5_spec/1.1.2</bundle>
-        <bundle dependency='true'>mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.asm/3.3_1</bundle>
-	    <bundle>mvn:org.eclipse.jetty/jetty-util/7.2.2.v20101205</bundle>
-	    <bundle>mvn:org.eclipse.jetty/jetty-io/7.2.2.v20101205</bundle>
-	    <bundle>mvn:org.eclipse.jetty/jetty-http/7.2.2.v20101205</bundle>
-	    <bundle>mvn:org.eclipse.jetty/jetty-continuation/7.2.2.v20101205</bundle>
-	    <bundle>mvn:org.eclipse.jetty/jetty-server/7.2.2.v20101205</bundle>
-	    <bundle>mvn:org.eclipse.jetty/jetty-security/7.2.2.v20101205</bundle>
-	    <bundle>mvn:org.eclipse.jetty/jetty-servlet/7.2.2.v20101205</bundle>
-    	<bundle>mvn:org.eclipse.jetty/jetty-xml/7.2.2.v20101205</bundle>
-	</feature>
-	<feature name="jetty-jaas" version="7.2.2.v20101205" resolver="(obr)">
-		<feature version="[7.0,8.0)">jetty</feature>
-		<bundle dependency='true'>mvn:javax.mail/mail/1.4.3</bundle>
-		<bundle dependency='true'>mvn:org.apache.geronimo.specs/geronimo-jta_1.1_spec/1.1.1</bundle>
-		<bundle>mvn:org.eclipse.jetty/jetty-webapp/7.2.2.v20101205</bundle>
-		<bundle>mvn:org.eclipse.jetty/jetty-jndi/7.2.2.v20101205</bundle>
-		<bundle>mvn:org.eclipse.jetty/jetty-plus/7.2.2.v20101205</bundle>
-	</feature>
-    <feature name="http" version="2.2.0" resolver="(obr)">
-    	<configfile finalname="/etc/jetty.xml">mvn:org.apache.karaf/apache-karaf/2.2.0/xml/jettyconfig</configfile>
-		<config name="org.ops4j.pax.web">
-            org.osgi.service.http.port=8181
-            javax.servlet.context.tempdir=${karaf.data}/pax-web-jsp
-            org.ops4j.pax.web.config.file=${karaf.etc}/jetty.xml
-        </config>
-        <feature version="[7.0,8.0)">jetty</feature>
-    	<bundle>mvn:org.ops4j.pax.web/pax-web-api/1.0.1</bundle>
-        <bundle>mvn:org.ops4j.pax.web/pax-web-spi/1.0.1</bundle>
-        <bundle>mvn:org.ops4j.pax.web/pax-web-runtime/1.0.1</bundle>
-        <bundle>mvn:org.ops4j.pax.web/pax-web-jetty/1.0.1</bundle>
-    </feature>
-    <feature name="war" version="2.2.0" resolver="(obr)">
-        <config name="org.ops4j.pax.url.war">
-            org.ops4j.pax.url.war.importPaxLoggingPackages=true
-        </config>
-        <feature>http</feature>
-        <bundle start-level='30'>mvn:org.apache.karaf.shell/org.apache.karaf.shell.web/2.2.0</bundle>
-        <bundle>mvn:org.ops4j.pax.web/pax-web-jsp/1.0.1</bundle>
-        <bundle>mvn:org.ops4j.pax.web/pax-web-extender-war/1.0.1</bundle>
-        <bundle>mvn:org.ops4j.pax.web/pax-web-extender-whiteboard/1.0.1</bundle>
-        <bundle>mvn:org.ops4j.pax.web/pax-web-deployer/1.0.1</bundle>
-        <bundle>mvn:org.ops4j.pax.url/pax-url-war/1.2.5</bundle>
-    </feature>
-    <feature name="kar" version="2.2.0">
-        <bundle>mvn:org.apache.karaf.deployer/org.apache.karaf.deployer.kar/2.2.0</bundle>
-    </feature>
-    <feature name="webconsole-base" version="2.2.0">
-        <config name="org.apache.karaf.webconsole">
-            realm=karaf
-        </config>
-        <feature>http</feature>
-        <bundle>mvn:org.apache.felix/org.apache.felix.metatype/1.0.4</bundle>
-        <bundle>mvn:org.apache.karaf.webconsole/org.apache.karaf.webconsole.branding/2.2.0</bundle>
-        <bundle>mvn:org.apache.karaf.webconsole/org.apache.karaf.webconsole.console/2.2.0</bundle>
-    </feature>
-    <feature name="webconsole" version="2.2.0">
-        <feature version="2.2.0">webconsole-base</feature>
-        <bundle>mvn:org.apache.karaf.webconsole/org.apache.karaf.webconsole.admin/2.2.0</bundle>
-        <bundle>mvn:org.apache.karaf.webconsole/org.apache.karaf.webconsole.features/2.2.0</bundle>
-        <bundle>mvn:org.apache.karaf.webconsole/org.apache.karaf.webconsole.gogo/2.2.0</bundle>
-		<bundle>mvn:org.apache.felix/org.apache.felix.webconsole.plugins.event/1.0.2</bundle>
-    </feature>
-    <feature name="ssh" version="2.2.0">
-        <config name="org.apache.karaf.shell">
-            sshPort=8101
-            sshHost=0.0.0.0
-            sshRealm=karaf
-            hostKey=${karaf.etc}/host.key
-        </config>
-        <bundle dependency='true'>mvn:org.apache.mina/mina-core/2.0.1</bundle>
-        <bundle dependency='true'>mvn:org.apache.sshd/sshd-core/0.5.0</bundle>
-        <bundle>mvn:org.apache.karaf.shell/org.apache.karaf.shell.ssh/2.2.0</bundle>
-    </feature>
-    <feature name="management" version="2.2.0">
-        <bundle>mvn:org.apache.karaf/org.apache.karaf.management/2.2.0</bundle>
-        <bundle>mvn:org.apache.aries.jmx/org.apache.aries.jmx/0.3</bundle>
-        <bundle>mvn:org.apache.aries.jmx/org.apache.aries.jmx.blueprint/0.3</bundle>
-    </feature>
-    <feature name="eventadmin" version="2.2.0">
-		<bundle start-level='30'>mvn:org.apache.felix/org.apache.felix.eventadmin/1.2.8</bundle>
-    </feature>
-    <feature name="jasypt-encryption" version="2.2.0" resolver="(obr)">
-        <bundle dependency='true'>mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.commons-codec/1.3_3</bundle>
-        <bundle dependency='true'>mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.commons-lang/2.4_4</bundle>
-        <bundle dependency='true'>mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.jasypt/1.7_1</bundle>
-        <bundle>mvn:org.apache.karaf.jaas/org.apache.karaf.jaas.jasypt/2.2.0</bundle>
-    </feature>
-</features>

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/core/src/test/resources/org/apache/karaf/features/internal/service/f03.xml
----------------------------------------------------------------------
diff --git a/features/core/src/test/resources/org/apache/karaf/features/internal/service/f03.xml b/features/core/src/test/resources/org/apache/karaf/features/internal/service/f03.xml
deleted file mode 100644
index c058095..0000000
--- a/features/core/src/test/resources/org/apache/karaf/features/internal/service/f03.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-    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.
--->
-<features xmlns="http://karaf.apache.org/xmlns/features/v1.0.0">
-    <feature name="spring" version="2.5.6.SEC02" resolver="(obr)">
-        <bundle dependency='true'>mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.aopalliance/1.0_6</bundle>
-        <bundle>mvn:org.springframework/spring-core/2.5.6.SEC02</bundle>
-        <bundle>mvn:org.springframework/spring-beans/2.5.6.SEC02</bundle>
-        <bundle>mvn:org.springframework/spring-aop/2.5.6.SEC02</bundle>
-        <bundle>mvn:org.springframework/spring-context/2.5.6.SEC02</bundle>
-        <bundle>mvn:org.springframework/spring-context-support/2.5.6.SEC02</bundle>
-    </feature>
-</features>

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/core/src/test/resources/org/apache/karaf/features/internal/service/f04.xml
----------------------------------------------------------------------
diff --git a/features/core/src/test/resources/org/apache/karaf/features/internal/service/f04.xml b/features/core/src/test/resources/org/apache/karaf/features/internal/service/f04.xml
deleted file mode 100644
index 85f28ad..0000000
--- a/features/core/src/test/resources/org/apache/karaf/features/internal/service/f04.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-    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.
--->
-<features name="karaf" xmlns="http://karaf.apache.org/xmlns/features/v1.1.0">
-    <feature name="spring" version="2.5.6.SEC02" resolver="(obr)">
-        <bundle dependency='true'>mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.aopalliance/1.0_6</bundle>
-        <bundle>mvn:org.springframework/spring-core/2.5.6.SEC02</bundle>
-        <bundle>mvn:org.springframework/spring-beans/2.5.6.SEC02</bundle>
-        <bundle>mvn:org.springframework/spring-aop/2.5.6.SEC02</bundle>
-        <bundle>mvn:org.springframework/spring-context/2.5.6.SEC02</bundle>
-        <bundle>mvn:org.springframework/spring-context-support/2.5.6.SEC02</bundle>
-    </feature>
-</features>
-

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/core/src/test/resources/org/apache/karaf/features/internal/service/f05.xml
----------------------------------------------------------------------
diff --git a/features/core/src/test/resources/org/apache/karaf/features/internal/service/f05.xml b/features/core/src/test/resources/org/apache/karaf/features/internal/service/f05.xml
deleted file mode 100644
index 15d84e2..0000000
--- a/features/core/src/test/resources/org/apache/karaf/features/internal/service/f05.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-    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.
--->
-<features xmlns="http://karaf.apache.org/xmlns/features/v1.1.0">
-    <feature name="spring" version="2.5.6.SEC02" resolver="(obr)">
-        <bundle dependency='true'>mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.aopalliance/1.0_6</bundle>
-        <bundle>mvn:org.springframework/spring-core/2.5.6.SEC02</bundle>
-        <bundle>mvn:org.springframework/spring-beans/2.5.6.SEC02</bundle>
-        <bundle>mvn:org.springframework/spring-aop/2.5.6.SEC02</bundle>
-        <bundle>mvn:org.springframework/spring-context/2.5.6.SEC02</bundle>
-        <bundle>mvn:org.springframework/spring-context-support/2.5.6.SEC02</bundle>
-    </feature>
-</features>
-

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/core/src/test/resources/org/apache/karaf/features/internal/service/f06.xml
----------------------------------------------------------------------
diff --git a/features/core/src/test/resources/org/apache/karaf/features/internal/service/f06.xml b/features/core/src/test/resources/org/apache/karaf/features/internal/service/f06.xml
deleted file mode 100644
index 496cbdb..0000000
--- a/features/core/src/test/resources/org/apache/karaf/features/internal/service/f06.xml
+++ /dev/null
@@ -1,32 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-    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.
--->
-<features name="karaf" xmlns="http://karaf.apache.org/xmlns/features/v1.2.0">
-    <feature name="spring" version="2.5.6.SEC02" resolver="(obr)">
-        <bundle dependency='true'>mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.aopalliance/1.0_4</bundle>
-        <bundle>mvn:org.springframework/spring-core/2.5.6.SEC02</bundle>
-        <bundle>mvn:org.springframework/spring-beans/2.5.6.SEC02</bundle>
-        <bundle>mvn:org.springframework/spring-aop/2.5.6.SEC02</bundle>
-        <bundle>mvn:org.springframework/spring-context/2.5.6.SEC02</bundle>
-        <bundle>mvn:org.springframework/spring-context-support/2.5.6.SEC02</bundle>
-        <conditional>
-            <condition>http</condition>
-            <bundle>mvn:org.springframework/spring-web/2.5.6.SEC02</bundle>
-        </conditional>
-    </feature>
-</features>
-

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/core/src/test/resources/org/apache/karaf/features/internal/service/f07.xml
----------------------------------------------------------------------
diff --git a/features/core/src/test/resources/org/apache/karaf/features/internal/service/f07.xml b/features/core/src/test/resources/org/apache/karaf/features/internal/service/f07.xml
deleted file mode 100644
index 5b7dd90..0000000
--- a/features/core/src/test/resources/org/apache/karaf/features/internal/service/f07.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-    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.
--->
-<features name="karaf" xmlns="http://karaf.apache.org/xmlns/features/v1.3.0">
-    <feature name="spring" version="2.5.6.SEC02" resolver="(obr)">
-        <bundle dependency='true'>mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.aopalliance/1.0_4</bundle>
-        <bundle>mvn:org.springframework/spring-core/2.5.6.SEC02</bundle>
-        <bundle>mvn:org.springframework/spring-beans/2.5.6.SEC02</bundle>
-        <bundle>mvn:org.springframework/spring-aop/2.5.6.SEC02</bundle>
-        <bundle>mvn:org.springframework/spring-context/2.5.6.SEC02</bundle>
-        <bundle>mvn:org.springframework/spring-context-support/2.5.6.SEC02</bundle>
-        <conditional>
-            <condition>http</condition>
-            <bundle>mvn:org.springframework/spring-web/2.5.6.SEC02</bundle>
-        </conditional>
-        <capability>
-            service-reference;effective:=active;objectClass=org.apache.aries.proxy.ProxyManager
-        </capability>
-    </feature>
-</features>
-

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/core/src/test/resources/org/apache/karaf/features/internal/service/overrides.properties
----------------------------------------------------------------------
diff --git a/features/core/src/test/resources/org/apache/karaf/features/internal/service/overrides.properties b/features/core/src/test/resources/org/apache/karaf/features/internal/service/overrides.properties
deleted file mode 100644
index d34fa7e..0000000
--- a/features/core/src/test/resources/org/apache/karaf/features/internal/service/overrides.properties
+++ /dev/null
@@ -1,23 +0,0 @@
-
-################################################################################
-#
-#    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.
-#
-################################################################################
-
-# Sample etc/overrides.properties file for testing purposes
-mvn:org.apache.karaf.admin/org.apache.karaf.admin.command/2.3.0.redhat-61033X
-mvn:org.apache.karaf.admin/org.apache.karaf.admin.core/2.3.0.redhat-61033X;range=[2.3.0,2.5)

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/core/src/test/resources/org/apache/karaf/features/internal/service/repo2.xml
----------------------------------------------------------------------
diff --git a/features/core/src/test/resources/org/apache/karaf/features/internal/service/repo2.xml b/features/core/src/test/resources/org/apache/karaf/features/internal/service/repo2.xml
deleted file mode 100644
index 5fd51d0..0000000
--- a/features/core/src/test/resources/org/apache/karaf/features/internal/service/repo2.xml
+++ /dev/null
@@ -1,41 +0,0 @@
-<!--
-
-    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.
--->
-<features name="repo2">
-    <feature name="common">
-        <bundle>b1</bundle>
-    </feature>
-    <feature name="f1">
-        <feature>common</feature>
-        <bundle>b2</bundle>
-    </feature>
-    <feature name="f2">
-        <feature>common</feature>
-        <feature>f1</feature>
-        <bundle>b3</bundle>
-    </feature>
-    <feature name="f3">
-        <feature>f1</feature>
-        <feature>f2</feature>
-    	<bundle>b4</bundle>
-    </feature>
-    <feature name="all">
-        <feature>f1</feature>
-        <feature>f2</feature>
-        <feature>f3</feature>
-    </feature>
-</features>

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/core/src/test/resources/org/apache/karaf/features/repo1.xml
----------------------------------------------------------------------
diff --git a/features/core/src/test/resources/org/apache/karaf/features/repo1.xml b/features/core/src/test/resources/org/apache/karaf/features/repo1.xml
deleted file mode 100644
index 641ef12..0000000
--- a/features/core/src/test/resources/org/apache/karaf/features/repo1.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-    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.
--->
-<features name="test" xmlns="http://karaf.apache.org/xmlns/features/v1.1.0">
-    <repository>urn:r1</repository>
-    <feature name="f1" region="foo">
-        <config name="c1">
-            k=v
-        </config>
-        <bundle>b1</bundle>
-        <bundle>b2</bundle>
-    </feature>
-    <feature name="f2">
-        <feature>f1</feature>
-        <bundle>b3</bundle>
-    </feature>
-    <feature name="f3">
-    	<configfile finalname="cf1" override="true">cfloc</configfile>
-    	<bundle>b4</bundle> 
-    </feature>
-</features>

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/core/src/test/resources/org/apache/karaf/features/repo2.xml
----------------------------------------------------------------------
diff --git a/features/core/src/test/resources/org/apache/karaf/features/repo2.xml b/features/core/src/test/resources/org/apache/karaf/features/repo2.xml
deleted file mode 100644
index f5e96ae..0000000
--- a/features/core/src/test/resources/org/apache/karaf/features/repo2.xml
+++ /dev/null
@@ -1,37 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-    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.
--->
-<features name="test" xmlns="http://karaf.apache.org/xmlns/features/v1.0.0">
-    <repository>
-        urn:r1
-    </repository>
-    <feature name="f1" region="foo">
-        <config name="c1">
-            k=v
-        </config>
-        <bundle>b1</bundle>
-        <bundle>b2</bundle>
-    </feature>
-    <feature name="f2">
-        <feature>f1</feature>
-        <bundle>b3</bundle>
-    </feature>
-    <feature name="f3">
-    	<configfile finalname="cf1" override="true">cfloc</configfile>
-    	<bundle>b4</bundle> 
-    </feature>
-</features>

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/core/src/test/resources/org/apache/karaf/features/repo3.xml
----------------------------------------------------------------------
diff --git a/features/core/src/test/resources/org/apache/karaf/features/repo3.xml b/features/core/src/test/resources/org/apache/karaf/features/repo3.xml
deleted file mode 100644
index ffe08ed..0000000
--- a/features/core/src/test/resources/org/apache/karaf/features/repo3.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-    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.
--->
-<features name="test" xmlns="http://karaf.apache.org/xmlns/features/v1.3.0">
-    <feature name="f1">
-        <capability>
-            cap
-        </capability>
-        <requirement>
-            req
-        </requirement>
-    </feature>
-</features>

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/pom.xml
----------------------------------------------------------------------
diff --git a/features/pom.xml b/features/pom.xml
index 8cfede1..5013057 100644
--- a/features/pom.xml
+++ b/features/pom.xml
@@ -29,13 +29,120 @@
     </parent>
 
     <groupId>org.apache.karaf.features</groupId>
-    <artifactId>features</artifactId>
-    <packaging>pom</packaging>
-    <name>Apache Karaf :: Features</name>
-
-    <modules>
-        <module>core</module>
-        <module>command</module>
-    </modules>
+    <artifactId>org.apache.karaf.features.core</artifactId>
+    <packaging>bundle</packaging>
+    <name>Apache Karaf :: Features :: Core</name>
+    <description>This bundle is the core implementation of the Karaf features support.</description>
+
+    <properties>
+        <appendedResourcesDirectory>${basedir}/../../etc/appended-resources</appendedResourcesDirectory>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>org.osgi.core</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>org.osgi.compendium</artifactId>
+            <scope>provided</scope>
+            <optional>true</optional>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.felix</groupId>
+            <artifactId>org.apache.felix.utils</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-api</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.karaf</groupId>
+            <artifactId>org.apache.karaf.util</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.felix</groupId>
+            <artifactId>org.apache.felix.resolver</artifactId>
+            <scope>provided</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.karaf.shell</groupId>
+            <artifactId>org.apache.karaf.shell.core</artifactId>
+            <optional>true</optional>
+        </dependency>
+
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-jdk14</artifactId>
+            <scope>test</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.ops4j.pax.tinybundles</groupId>
+            <artifactId>tinybundles</artifactId>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <resources>
+            <resource>
+                <directory>${project.basedir}/src/main/resources</directory>
+                <includes>
+                    <include>**/*</include>
+                </includes>
+            </resource>
+            <resource>
+                <directory>${project.basedir}/src/main/resources</directory>
+                <filtering>true</filtering>
+                <includes>
+                    <include>**/*.info</include>
+                </includes>
+            </resource>
+        </resources>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+                <configuration>
+                    <instructions>
+                        <Export-Package>
+                            org.apache.karaf.features;
+                            org.apache.karaf.features.command;
+                            org.apache.karaf.features.command.completers;
+                            org.apache.karaf.features.management;
+                            org.apache.karaf.features.management.codec;
+                                -noimport:=true
+                        </Export-Package>
+                        <Provide-Capability>
+                            service-reference;effective:=active;objectClass=org.apache.karaf.features.FeaturesService
+                        </Provide-Capability>
+                        <Private-Package>
+                            org.apache.karaf.features.internal.*,
+                            org.apache.felix.resolver,
+                            org.apache.felix.utils.version,
+                            org.apache.felix.utils.manifest,
+                            org.apache.karaf.util.collections,
+                            org.apache.karaf.util.json,
+                            org.apache.karaf.util.tracker,
+                            org.osgi.service.resolver,
+                            org.osgi.service.repository
+                        </Private-Package>
+                        <Bundle-Activator>
+                            org.apache.karaf.features.internal.osgi.Activator
+                        </Bundle-Activator>
+                        <Karaf-Commands>org.apache.karaf.features.command.*</Karaf-Commands>
+                    </instructions>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
 
 </project>

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/src/main/java/org/apache/karaf/features/BootFinished.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/BootFinished.java b/features/src/main/java/org/apache/karaf/features/BootFinished.java
new file mode 100644
index 0000000..aa72248
--- /dev/null
+++ b/features/src/main/java/org/apache/karaf/features/BootFinished.java
@@ -0,0 +1,24 @@
+/*
+ * 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.karaf.features;
+
+/**
+ * Marker interface for a service that announces when the karaf boot is finished
+ */
+public interface BootFinished {
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/src/main/java/org/apache/karaf/features/BundleInfo.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/BundleInfo.java b/features/src/main/java/org/apache/karaf/features/BundleInfo.java
new file mode 100644
index 0000000..97a541f
--- /dev/null
+++ b/features/src/main/java/org/apache/karaf/features/BundleInfo.java
@@ -0,0 +1,32 @@
+/*
+ * 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.karaf.features;
+
+/**
+ * A bundle info holds info about a Bundle.
+ */
+public interface BundleInfo {
+
+	String getLocation();
+	
+    int getStartLevel();
+    
+    boolean isStart();
+
+    boolean isDependency();
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/src/main/java/org/apache/karaf/features/Capability.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/Capability.java b/features/src/main/java/org/apache/karaf/features/Capability.java
new file mode 100644
index 0000000..d329708
--- /dev/null
+++ b/features/src/main/java/org/apache/karaf/features/Capability.java
@@ -0,0 +1,23 @@
+/*
+ * 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.karaf.features;
+
+public interface Capability {
+
+    String getValue();
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/src/main/java/org/apache/karaf/features/Conditional.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/Conditional.java b/features/src/main/java/org/apache/karaf/features/Conditional.java
new file mode 100644
index 0000000..c0e4d59
--- /dev/null
+++ b/features/src/main/java/org/apache/karaf/features/Conditional.java
@@ -0,0 +1,35 @@
+/*
+ * 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.karaf.features;
+
+import java.util.List;
+import java.util.Map;
+
+public interface Conditional {
+
+    List<? extends Dependency> getCondition();
+
+    List<Dependency> getDependencies();
+
+    List<BundleInfo> getBundles();
+
+    Map<String, Map<String, String>> getConfigurations();
+
+    List<ConfigFileInfo> getConfigurationFiles();
+
+    Feature asFeature(String name, String version);
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/src/main/java/org/apache/karaf/features/ConfigFileInfo.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/ConfigFileInfo.java b/features/src/main/java/org/apache/karaf/features/ConfigFileInfo.java
new file mode 100644
index 0000000..960fb31
--- /dev/null
+++ b/features/src/main/java/org/apache/karaf/features/ConfigFileInfo.java
@@ -0,0 +1,27 @@
+/*
+ * 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.karaf.features;
+
+public interface ConfigFileInfo {
+	
+	String getLocation();
+	
+	String getFinalname();
+	
+	boolean isOverride();
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/src/main/java/org/apache/karaf/features/Dependency.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/Dependency.java b/features/src/main/java/org/apache/karaf/features/Dependency.java
new file mode 100644
index 0000000..cafdd92
--- /dev/null
+++ b/features/src/main/java/org/apache/karaf/features/Dependency.java
@@ -0,0 +1,29 @@
+/*
+ * 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.karaf.features;
+
+public interface Dependency {
+
+    String getName();
+
+    String getVersion();
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/src/main/java/org/apache/karaf/features/EventConstants.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/EventConstants.java b/features/src/main/java/org/apache/karaf/features/EventConstants.java
new file mode 100644
index 0000000..f83f185
--- /dev/null
+++ b/features/src/main/java/org/apache/karaf/features/EventConstants.java
@@ -0,0 +1,46 @@
+/*
+ * 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.karaf.features;
+
+/**
+ * Constants for EventAdmin events
+ */
+public final class EventConstants {
+
+    public static final String TYPE = "type";
+    public static final String EVENT = "event";
+    public static final String TIMESTAMP = "timestamp";
+
+    public static final String FEATURE_NAME = "name";
+    public static final String FEATURE_VERSION = "version";
+
+    public static final String REPOSITORY_NAME = "name";
+    public static final String REPOSITORY_URI = "uri";
+
+    public static final String TOPIC_EVENTS = "org/apache/karaf/features";
+    public static final String TOPIC_FEATURES_INSTALLED = TOPIC_EVENTS + "/features/INSTALLED";
+    public static final String TOPIC_FEATURES_UNINSTALLED = TOPIC_EVENTS + "/features/UNINSTALLED";
+    public static final String TOPIC_REPOSITORY_ADDED = TOPIC_EVENTS + "/repositories/ADDED";
+    public static final String TOPIC_REPOSITORY_REMOVED = TOPIC_EVENTS + "/repositories/REMOVED";
+
+    private EventConstants() {
+        // non-instantiable class
+    }
+
+
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/src/main/java/org/apache/karaf/features/Feature.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/Feature.java b/features/src/main/java/org/apache/karaf/features/Feature.java
new file mode 100644
index 0000000..2f9f001
--- /dev/null
+++ b/features/src/main/java/org/apache/karaf/features/Feature.java
@@ -0,0 +1,63 @@
+/*
+ * 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.karaf.features;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * A feature is a list of bundles associated identified by its name.
+ */
+public interface Feature {
+
+    public static String DEFAULT_INSTALL_MODE = "auto";
+
+    String getId();
+
+    String getName();
+
+    String getDescription();
+
+    String getDetails();
+
+    String getVersion();
+
+    boolean hasVersion();
+
+    String getResolver();
+
+    String getInstall();
+
+    List<Dependency> getDependencies();
+
+    List<BundleInfo> getBundles();
+
+    Map<String, Map<String, String>> getConfigurations();
+
+    List<ConfigFileInfo> getConfigurationFiles();
+
+    List<? extends Conditional> getConditional();
+    
+    int getStartLevel();
+
+    String getRegion();
+
+    List<? extends Capability> getCapabilities();
+
+    List<? extends Requirement> getRequirements();
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/src/main/java/org/apache/karaf/features/FeatureEvent.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/FeatureEvent.java b/features/src/main/java/org/apache/karaf/features/FeatureEvent.java
new file mode 100644
index 0000000..516c988
--- /dev/null
+++ b/features/src/main/java/org/apache/karaf/features/FeatureEvent.java
@@ -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.karaf.features;
+
+import java.util.EventObject;
+
+public class FeatureEvent extends EventObject {
+
+    public static enum EventType {
+        FeatureInstalled,
+        FeatureUninstalled
+    }
+
+    private final EventType type;
+    private final Feature feature;
+    private final boolean replay;
+
+    public FeatureEvent(Feature feature, EventType type, boolean replay) {
+        super(feature);
+        this.type = type;
+        this.feature = feature;
+        this.replay = replay;
+    }
+
+    public EventType getType() {
+        return type;
+    }
+
+    public Feature getFeature() {
+        return feature;
+    }
+
+    public boolean isReplay() {
+        return replay;
+    }
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/src/main/java/org/apache/karaf/features/FeaturesListener.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/FeaturesListener.java b/features/src/main/java/org/apache/karaf/features/FeaturesListener.java
new file mode 100644
index 0000000..69f68c6
--- /dev/null
+++ b/features/src/main/java/org/apache/karaf/features/FeaturesListener.java
@@ -0,0 +1,25 @@
+/*
+ * 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.karaf.features;
+
+public interface FeaturesListener {
+
+    void featureEvent(FeatureEvent event);
+
+    void repositoryEvent(RepositoryEvent event);
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/src/main/java/org/apache/karaf/features/FeaturesNamespaces.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/FeaturesNamespaces.java b/features/src/main/java/org/apache/karaf/features/FeaturesNamespaces.java
new file mode 100644
index 0000000..282ff71
--- /dev/null
+++ b/features/src/main/java/org/apache/karaf/features/FeaturesNamespaces.java
@@ -0,0 +1,41 @@
+/*
+ * 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.karaf.features;
+
+import javax.xml.namespace.QName;
+
+/**
+ * Provides features XML/XSD constants.
+ */
+public interface FeaturesNamespaces {
+
+    String URI_0_0_0 = "";
+    String URI_1_0_0 = "http://karaf.apache.org/xmlns/features/v1.0.0";
+    String URI_1_1_0 = "http://karaf.apache.org/xmlns/features/v1.1.0";
+    String URI_1_2_0 = "http://karaf.apache.org/xmlns/features/v1.2.0";
+    String URI_1_3_0 = "http://karaf.apache.org/xmlns/features/v1.3.0";
+
+    String URI_CURRENT = URI_1_3_0;
+
+    QName FEATURES_0_0_0 = new QName("features");
+    QName FEATURES_1_0_0 = new QName(URI_1_0_0, "features");
+    QName FEATURES_1_1_0 = new QName(URI_1_1_0, "features");
+    QName FEATURES_1_2_0 = new QName(URI_1_2_0, "features");
+    QName FEATURES_1_3_0 = new QName(URI_1_3_0, "features");
+
+    QName FEATURES_CURRENT = FEATURES_1_3_0;
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/src/main/java/org/apache/karaf/features/FeaturesService.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/FeaturesService.java b/features/src/main/java/org/apache/karaf/features/FeaturesService.java
new file mode 100644
index 0000000..ef3dbcf
--- /dev/null
+++ b/features/src/main/java/org/apache/karaf/features/FeaturesService.java
@@ -0,0 +1,104 @@
+/*
+ * 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.karaf.features;
+
+import java.net.URI;
+import java.util.EnumSet;
+import java.util.Set;
+
+/**
+ * The service managing features repositories.
+ */
+public interface FeaturesService {
+
+    enum Option {
+        NoFailOnFeatureNotFound,
+        NoAutoRefreshManagedBundles,
+        NoAutoRefreshUnmanagedBundles,
+        NoAutoRefreshBundles,
+        NoAutoStartBundles,
+        Simulate,
+        Verbose
+    }
+
+    /**
+     * Validate repository contents.
+     * 
+     * @param uri Repository uri.
+     * @throws Exception When validation fails.
+     */
+    void validateRepository(URI uri) throws Exception;
+
+    void addRepository(URI uri) throws Exception;
+
+    void addRepository(URI uri, boolean install) throws Exception;
+
+    void removeRepository(URI uri) throws Exception;
+
+    void removeRepository(URI uri, boolean uninstall) throws Exception;
+    
+    void restoreRepository(URI uri) throws Exception;
+
+    Repository[] listRequiredRepositories() throws Exception;
+
+    Repository[] listRepositories() throws Exception;
+    
+    Repository getRepository(String repoName) throws Exception;
+
+    void installFeature(String name) throws Exception;
+
+    void installFeature(String name, EnumSet<Option> options) throws Exception;
+    
+    void installFeature(String name, String version) throws Exception;
+
+    void installFeature(String name, String version, EnumSet<Option> options) throws Exception;
+
+    void installFeature(Feature f, EnumSet<Option> options) throws Exception;
+
+    void installFeatures(Set<String> features, EnumSet<Option> options) throws Exception;
+
+    void uninstallFeature(String name, EnumSet<Option> options) throws Exception;
+
+    void uninstallFeature(String name) throws Exception;
+
+    void uninstallFeature(String name, String version, EnumSet<Option> options) throws Exception;
+    
+    void uninstallFeature(String name, String version) throws Exception;
+
+    void uninstallFeatures(Set<String> features, EnumSet<Option> options) throws Exception;
+
+    Feature[] listFeatures() throws Exception;
+
+    Feature[] listRequiredFeatures() throws Exception;
+
+    Feature[] listInstalledFeatures() throws Exception;
+
+    boolean isRequired(Feature f);
+
+    boolean isInstalled(Feature f);
+
+    Feature getFeature(String name, String version) throws Exception;
+
+    Feature getFeature(String name) throws Exception;
+
+	void refreshRepository(URI uri) throws Exception;
+
+    public URI getRepositoryUriFor(String name, String version);
+
+    public String[] getRepositoryNames();
+
+}


[39/59] [abbrv] git commit: [KARAF-2852] Merge package/core and package/command

Posted by gn...@apache.org.
[KARAF-2852] Merge package/core and package/command


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

Branch: refs/heads/master
Commit: 91232f80fede4df8e71b6bd15c3055ce0ab4df7c
Parents: 7f1463c
Author: Guillaume Nodet <gn...@gmail.com>
Authored: Wed Apr 9 23:18:14 2014 +0200
Committer: Guillaume Nodet <gn...@gmail.com>
Committed: Thu Apr 10 16:02:23 2014 +0200

----------------------------------------------------------------------
 .../standard/src/main/feature/feature.xml       |   1 -
 package/NOTICE                                  |  71 +++++++++
 .../apache/karaf/packages/command/Exports.java  | 132 -----------------
 .../apache/karaf/packages/command/Imports.java  |  65 ---------
 package/core/NOTICE                             |  71 ---------
 package/core/pom.xml                            | 119 ---------------
 .../karaf/packages/core/PackageRequirement.java |  64 ---------
 .../karaf/packages/core/PackageService.java     |  51 -------
 .../karaf/packages/core/PackageVersion.java     |  52 -------
 .../karaf/packages/core/PackagesMBean.java      |  32 -----
 .../core/internal/PackageServiceImpl.java       | 134 -----------------
 .../core/internal/PackagesMBeanImpl.java        | 143 -------------------
 .../packages/core/internal/osgi/Activator.java  |  34 -----
 .../src/main/resources/OSGI-INF/bundle.info     |  15 --
 .../karaf/packages/core/InstallMBeantest.java   |  44 ------
 .../packages/core/PackageRequirementTest.java   |  32 -----
 package/pom.xml                                 | 107 ++++++++++++--
 .../apache/karaf/packages/command/Exports.java  | 132 +++++++++++++++++
 .../apache/karaf/packages/command/Imports.java  |  65 +++++++++
 .../karaf/packages/core/PackageRequirement.java |  64 +++++++++
 .../karaf/packages/core/PackageService.java     |  51 +++++++
 .../karaf/packages/core/PackageVersion.java     |  52 +++++++
 .../karaf/packages/core/PackagesMBean.java      |  32 +++++
 .../core/internal/PackageServiceImpl.java       | 134 +++++++++++++++++
 .../core/internal/PackagesMBeanImpl.java        | 143 +++++++++++++++++++
 .../packages/core/internal/osgi/Activator.java  |  34 +++++
 package/src/main/resources/OSGI-INF/bundle.info |  15 ++
 .../karaf/packages/core/InstallMBeantest.java   |  44 ++++++
 .../packages/core/PackageRequirementTest.java   |  32 +++++
 29 files changed, 967 insertions(+), 998 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/karaf/blob/91232f80/assemblies/features/standard/src/main/feature/feature.xml
----------------------------------------------------------------------
diff --git a/assemblies/features/standard/src/main/feature/feature.xml b/assemblies/features/standard/src/main/feature/feature.xml
index 6fa3319..ae6ab68 100644
--- a/assemblies/features/standard/src/main/feature/feature.xml
+++ b/assemblies/features/standard/src/main/feature/feature.xml
@@ -157,7 +157,6 @@
 
     <feature name="package" version="${project.version}" resolver="(obr)" description="Package commands and mbeans">
         <bundle start-level="30">mvn:org.apache.karaf.package/org.apache.karaf.package.core/${project.version}</bundle>
-        <bundle start-level="30">mvn:org.apache.karaf.package/org.apache.karaf.package.command/${project.version}</bundle>
     </feature>
 
     <feature name="service" description="Provide Service support" version="${project.version}">

http://git-wip-us.apache.org/repos/asf/karaf/blob/91232f80/package/NOTICE
----------------------------------------------------------------------
diff --git a/package/NOTICE b/package/NOTICE
new file mode 100644
index 0000000..b70f1f9
--- /dev/null
+++ b/package/NOTICE
@@ -0,0 +1,71 @@
+Apache Karaf
+Copyright 2010-2014 The Apache Software Foundation
+
+
+I. Included Software
+
+This product includes software developed at
+The Apache Software Foundation (http://www.apache.org/).
+Licensed under the Apache License 2.0.
+
+This product uses software developed at
+The OSGi Alliance (http://www.osgi.org/).
+Copyright (c) OSGi Alliance (2000, 2010).
+Licensed under the Apache License 2.0.
+
+This product includes software developed at
+OW2 (http://www.ow2.org/).
+Licensed under the BSD License.
+
+This product includes software developed at
+OPS4J (http://www.ops4j.org/).
+Licensed under the Apache License 2.0.
+
+This product includes software developed at
+Eclipse Foundation (http://www.eclipse.org/).
+Licensed under the EPL.
+
+This product includes software written by
+Antony Lesuisse.
+Licensed under Public Domain.
+
+
+II. Used Software
+
+This product uses software developed at
+FUSE Source (http://www.fusesource.org/).
+Licensed under the Apache License 2.0.
+
+This product uses software developed at
+AOP Alliance (http://aopalliance.sourceforge.net/).
+Licensed under the Public Domain.
+
+This product uses software developed at
+Tanuki Software (http://www.tanukisoftware.com/).
+Licensed under the Apache License 2.0.
+
+This product uses software developed at
+Jasypt (http://jasypt.sourceforge.net/).
+Licensed under the Apache License 2.0.
+
+This product uses software developed at
+JLine (http://jline.sourceforge.net).
+Licensed under the BSD License.
+
+This product uses software developed at
+SLF4J (http://www.slf4j.org/).
+Licensed under the MIT License.
+
+This product uses software developed at
+SpringSource (http://www.springsource.org/).
+Licensed under the Apache License 2.0.
+
+This product includes software from http://www.json.org.
+Copyright (c) 2002 JSON.org
+
+
+III. License Summary
+- Apache License 2.0
+- BSD License
+- EPL License
+- MIT License

http://git-wip-us.apache.org/repos/asf/karaf/blob/91232f80/package/command/src/main/java/org/apache/karaf/packages/command/Exports.java
----------------------------------------------------------------------
diff --git a/package/command/src/main/java/org/apache/karaf/packages/command/Exports.java b/package/command/src/main/java/org/apache/karaf/packages/command/Exports.java
deleted file mode 100644
index c09a5f6..0000000
--- a/package/command/src/main/java/org/apache/karaf/packages/command/Exports.java
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * 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.karaf.packages.command;
-
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.SortedMap;
-import java.util.TreeMap;
-
-import org.apache.karaf.packages.core.PackageService;
-import org.apache.karaf.packages.core.PackageVersion;
-import org.apache.karaf.shell.api.action.Action;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Option;
-import org.apache.karaf.shell.api.action.lifecycle.Reference;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.apache.karaf.shell.support.table.Col;
-import org.apache.karaf.shell.support.table.ShellTable;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.Version;
-import org.osgi.framework.wiring.BundleCapability;
-import org.osgi.framework.wiring.BundleRevision;
-
-@Command(scope = "package", name = "exports", description = "Lists exported packages and the bundles that export them")
-@Service
-public class Exports implements Action {
-
-    @Option(name = "-d", description = "Only show packages that are exported by more than one bundle", required = false, multiValued = false)
-    private boolean onlyDuplicates;
-
-    @Option(name = "--no-format", description = "Disable table rendered output", required = false, multiValued = false)
-    boolean noFormat;
-
-    @Reference
-    private PackageService packageService;
-
-    @Reference
-    private BundleContext bundleContext;
-
-    @Override
-    public Object execute() throws Exception {
-    	if (onlyDuplicates) {
-    		checkDuplicateExports();
-    	} else {
-    		showExports();
-    	}
-        return null;
-    }
-
-	private void showExports() {
-		SortedMap<String, PackageVersion> exports = packageService.getExports();
-        ShellTable table = new ShellTable();
-        table.column(new Col("Package Name"));
-        table.column(new Col("Version"));
-        table.column(new Col("ID"));
-        table.column(new Col("Bundle Name"));
-        
-        for (String key : exports.keySet()) {
-            PackageVersion pVer = exports.get(key);
-            for (Bundle bundle : pVer.getBundles()) {
-                table.addRow().addContent(pVer.getPackageName(),pVer.getVersion().toString(), bundle.getBundleId(), bundle.getSymbolicName());
-            }
-        }
-        table.print(System.out, !noFormat);
-	}
-    
-    private void checkDuplicateExports() {
-        Bundle[] bundles = bundleContext.getBundles();
-        SortedMap<String, PackageVersion> packageVersionMap = getDuplicatePackages(bundles);
-        ShellTable table = new ShellTable();
-        table.column(new Col("Package Name"));
-        table.column(new Col("Version"));
-        table.column(new Col("Exporting bundles (ID)"));
-       
-        for (String key : packageVersionMap.keySet()) {
-            PackageVersion pVer = packageVersionMap.get(key);
-            if (pVer.getBundles().size() > 1) {
-            	String pBundles = getBundlesSt(pVer.getBundles());
-            	table.addRow().addContent(pVer.getPackageName(), pVer.getVersion().toString(), pBundles); 
-            }
-        }
-        table.print(System.out, !noFormat);
-    }
-
-	private String getBundlesSt(Set<Bundle> bundles) {
-		StringBuilder st = new StringBuilder();
-		for (Bundle bundle : bundles) {
-            st.append(bundle.getBundleId() + " ");
-        }
-		return st.toString();
-	}
-
-	private SortedMap<String, PackageVersion> getDuplicatePackages(
-			Bundle[] bundles) {
-		SortedMap<String, PackageVersion> packageVersionMap = new TreeMap<String, PackageVersion>();
-        for (Bundle bundle : bundles) {
-            BundleRevision rev = bundle.adapt(BundleRevision.class);
-            if (rev!=null) {
-                List<BundleCapability> caps = rev.getDeclaredCapabilities(BundleRevision.PACKAGE_NAMESPACE);
-                for (BundleCapability cap : caps) {
-                    Map<String, Object> attr = cap.getAttributes();
-                    String packageName = (String)attr.get(BundleRevision.PACKAGE_NAMESPACE);
-                    Version version = (Version)attr.get("version");
-                    String key = packageName + ":" + version.toString();
-                    PackageVersion pVer = packageVersionMap.get(key);
-                    if (pVer == null) {
-                        pVer = new PackageVersion(packageName, version);
-                        packageVersionMap.put(key, pVer);
-                    }
-                    pVer.addBundle(bundle);
-                }
-            }
-        }
-		return packageVersionMap;
-	}
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/91232f80/package/command/src/main/java/org/apache/karaf/packages/command/Imports.java
----------------------------------------------------------------------
diff --git a/package/command/src/main/java/org/apache/karaf/packages/command/Imports.java b/package/command/src/main/java/org/apache/karaf/packages/command/Imports.java
deleted file mode 100644
index 3d086e9..0000000
--- a/package/command/src/main/java/org/apache/karaf/packages/command/Imports.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * 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.karaf.packages.command;
-
-import java.util.SortedMap;
-
-import org.apache.karaf.packages.core.PackageRequirement;
-import org.apache.karaf.packages.core.PackageService;
-import org.apache.karaf.shell.api.action.Action;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Option;
-import org.apache.karaf.shell.api.action.lifecycle.Reference;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.apache.karaf.shell.support.table.Col;
-import org.apache.karaf.shell.support.table.ShellTable;
-import org.osgi.framework.Bundle;
-
-@Command(scope = "package", name = "imports", description = "Lists imported packages and the bundles that import them")
-@Service
-public class Imports implements Action {
-    
-    @Option(name = "-p", description = "Only show package instead of full filter", required = false, multiValued = false)
-    boolean onlyPackage;
-
-    @Option(name = "--no-format", description = "Disable table rendered output", required = false, multiValued = false)
-    boolean noFormat;
-
-    @Reference
-    private PackageService packageService;
-
-    @Override
-    public Object execute() throws Exception {
-        SortedMap<String, PackageRequirement> imports = packageService.getImports();
-        ShellTable table = new ShellTable();
-        table.column(new Col(onlyPackage ? "Package name" : "Filter"));
-        table.column(new Col("Optional"));
-        table.column(new Col("ID"));
-        table.column(new Col("Bundle Name"));
-        table.column(new Col("Resolveable"));
-        
-        for (String filter : imports.keySet()) {
-            PackageRequirement req = imports.get(filter);
-            Bundle bundle = req.getBundle();
-            String firstCol = onlyPackage ? req.getPackageName() : req.getFilter();
-            table.addRow().addContent(firstCol, req.isOptional() ? "optional" : "", bundle.getBundleId(), bundle.getSymbolicName(), req.isResolveable());
-        }
-        table.print(System.out, !noFormat);
-        return null;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/91232f80/package/core/NOTICE
----------------------------------------------------------------------
diff --git a/package/core/NOTICE b/package/core/NOTICE
deleted file mode 100644
index b70f1f9..0000000
--- a/package/core/NOTICE
+++ /dev/null
@@ -1,71 +0,0 @@
-Apache Karaf
-Copyright 2010-2014 The Apache Software Foundation
-
-
-I. Included Software
-
-This product includes software developed at
-The Apache Software Foundation (http://www.apache.org/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-The OSGi Alliance (http://www.osgi.org/).
-Copyright (c) OSGi Alliance (2000, 2010).
-Licensed under the Apache License 2.0.
-
-This product includes software developed at
-OW2 (http://www.ow2.org/).
-Licensed under the BSD License.
-
-This product includes software developed at
-OPS4J (http://www.ops4j.org/).
-Licensed under the Apache License 2.0.
-
-This product includes software developed at
-Eclipse Foundation (http://www.eclipse.org/).
-Licensed under the EPL.
-
-This product includes software written by
-Antony Lesuisse.
-Licensed under Public Domain.
-
-
-II. Used Software
-
-This product uses software developed at
-FUSE Source (http://www.fusesource.org/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-AOP Alliance (http://aopalliance.sourceforge.net/).
-Licensed under the Public Domain.
-
-This product uses software developed at
-Tanuki Software (http://www.tanukisoftware.com/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-Jasypt (http://jasypt.sourceforge.net/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-JLine (http://jline.sourceforge.net).
-Licensed under the BSD License.
-
-This product uses software developed at
-SLF4J (http://www.slf4j.org/).
-Licensed under the MIT License.
-
-This product uses software developed at
-SpringSource (http://www.springsource.org/).
-Licensed under the Apache License 2.0.
-
-This product includes software from http://www.json.org.
-Copyright (c) 2002 JSON.org
-
-
-III. License Summary
-- Apache License 2.0
-- BSD License
-- EPL License
-- MIT License

http://git-wip-us.apache.org/repos/asf/karaf/blob/91232f80/package/core/pom.xml
----------------------------------------------------------------------
diff --git a/package/core/pom.xml b/package/core/pom.xml
deleted file mode 100644
index bc5238f..0000000
--- a/package/core/pom.xml
+++ /dev/null
@@ -1,119 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-
-    <!--
-
-        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.
-    -->
-
-    <modelVersion>4.0.0</modelVersion>
-
-    <parent>
-        <groupId>org.apache.karaf.package</groupId>
-        <artifactId>package</artifactId>
-        <version>4.0.0-SNAPSHOT</version>
-        <relativePath>../pom.xml</relativePath>
-    </parent>
-
-    <artifactId>org.apache.karaf.package.core</artifactId>
-    <packaging>bundle</packaging>
-    <name>Apache Karaf :: Package :: Core</name>
-    <description>Package Services and API</description>
-
-    <properties>
-        <appendedResourcesDirectory>${basedir}/../../etc/appended-resources</appendedResourcesDirectory>
-    </properties>
-
-    <dependencies>
-
-        <dependency>
-            <groupId>org.apache.aries.blueprint</groupId>
-            <artifactId>org.apache.aries.blueprint.api</artifactId>
-            <scope>provided</scope>
-        </dependency>
-
-        <dependency>
-            <groupId>org.osgi</groupId>
-            <artifactId>org.osgi.core</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.slf4j</groupId>
-            <artifactId>slf4j-api</artifactId>
-            <scope>provided</scope>
-        </dependency>
-
-        <dependency>
-            <groupId>org.apache.felix</groupId>
-            <artifactId>org.apache.felix.utils</artifactId>
-            <scope>provided</scope>
-        </dependency>
-
-        <dependency>
-            <groupId>org.apache.karaf</groupId>
-            <artifactId>org.apache.karaf.util</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        
-        <dependency>
-            <groupId>org.slf4j</groupId>
-            <artifactId>slf4j-jdk14</artifactId>
-            <scope>test</scope>
-        </dependency>
-    </dependencies>
-
-    <build>
-        <resources>
-            <resource>
-                <directory>${project.basedir}/src/main/resources</directory>
-                <includes>
-                    <include>**/*</include>
-                </includes>
-            </resource>
-            <resource>
-                <directory>${project.basedir}/src/main/resources</directory>
-                <filtering>true</filtering>
-                <includes>
-                    <include>**/*.info</include>
-                </includes>
-            </resource>
-        </resources>
-        <plugins>
-            <plugin>
-                <groupId>org.apache.felix</groupId>
-                <artifactId>maven-bundle-plugin</artifactId>
-                <configuration>
-                    <instructions>
-                        <Export-Package>
-                            org.apache.karaf.packages.core;-noimport:=true
-                        </Export-Package>
-                        <Private-Package>
-                            org.apache.karaf.packages.core.internal,
-                            org.apache.karaf.packages.core.internal.osgi,
-                            org.apache.karaf.util.tracker,
-                            org.apache.felix.utils.version,
-                            org.apache.felix.utils.manifest
-                        </Private-Package>
-                        <Bundle-Activator>
-                            org.apache.karaf.packages.core.internal.osgi.Activator
-                        </Bundle-Activator>
-                    </instructions>
-                </configuration>
-            </plugin>
-        </plugins>
-    </build>
-
-</project>

http://git-wip-us.apache.org/repos/asf/karaf/blob/91232f80/package/core/src/main/java/org/apache/karaf/packages/core/PackageRequirement.java
----------------------------------------------------------------------
diff --git a/package/core/src/main/java/org/apache/karaf/packages/core/PackageRequirement.java b/package/core/src/main/java/org/apache/karaf/packages/core/PackageRequirement.java
deleted file mode 100644
index ed8550b..0000000
--- a/package/core/src/main/java/org/apache/karaf/packages/core/PackageRequirement.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * 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.karaf.packages.core;
-
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import org.osgi.framework.Bundle;
-
-public class PackageRequirement {
-    private String filter;
-    private boolean optional;
-    private Bundle bundle;
-    private boolean resolveable;
-    private static Pattern packagePattern  = Pattern.compile(".*" + Pattern.quote("(osgi.wiring.package=") + "(.*?)\\).*");
-    
-    public PackageRequirement(String filter, boolean optional, Bundle bundle, boolean resolveable) {
-        super();
-        this.filter = filter;
-        this.optional = optional;
-        this.bundle = bundle;
-        this.resolveable = resolveable;
-    }
-    
-    public Bundle getBundle() {
-        return bundle;
-    }
-
-    public String getFilter() {
-        return filter;
-    }
-    public boolean isOptional() {
-        return optional;
-    }
-
-    public boolean isResolveable() {
-        return resolveable;
-    }
-
-    public String getPackageName() {
-        return getPackageName(filter);
-    }
-    
-    public static String getPackageName(String filter) {
-        Matcher matcher = packagePattern.matcher(filter);
-        matcher.matches();
-        return matcher.group(1);
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/91232f80/package/core/src/main/java/org/apache/karaf/packages/core/PackageService.java
----------------------------------------------------------------------
diff --git a/package/core/src/main/java/org/apache/karaf/packages/core/PackageService.java b/package/core/src/main/java/org/apache/karaf/packages/core/PackageService.java
deleted file mode 100644
index d6ccc65..0000000
--- a/package/core/src/main/java/org/apache/karaf/packages/core/PackageService.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * 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.karaf.packages.core;
-
-import java.util.List;
-import java.util.SortedMap;
-
-public interface PackageService {
-
-	/**
-	 * Gets the simplified package exports of a bundle. This does not show the 
-	 * package versions.
-	 * 
-	 * @param bundleId
-	 * @return
-	 */
-    List<String> getExports(long bundleId);
-
-    List<String> getImports(long bundleId);
-
-	/**
-	 * Gets a map of all exported packages with their version and the bundles that exprot them
-	 * The key is in the form packagename:version.
-	 * 
-	 * @return 
-	 */
-    SortedMap<String, PackageVersion> getExports();
-
-    /**
-     * Gets a map of all package imports. 
-     * The key is the import filter.
-     *  
-     * @return
-     */
-    SortedMap<String, PackageRequirement> getImports();
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/91232f80/package/core/src/main/java/org/apache/karaf/packages/core/PackageVersion.java
----------------------------------------------------------------------
diff --git a/package/core/src/main/java/org/apache/karaf/packages/core/PackageVersion.java b/package/core/src/main/java/org/apache/karaf/packages/core/PackageVersion.java
deleted file mode 100644
index aed0c48..0000000
--- a/package/core/src/main/java/org/apache/karaf/packages/core/PackageVersion.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * 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.karaf.packages.core;
-
-import java.util.HashSet;
-import java.util.Set;
-
-import org.osgi.framework.Bundle;
-import org.osgi.framework.Version;
-
-public class PackageVersion {
-
-    private String packageName;
-    private Version version;
-    private Set<Bundle> bundles = new HashSet<Bundle>();
-    
-    public PackageVersion(String packageName, Version version) {
-        this.packageName = packageName;
-        this.version = version;
-    }
-    
-    public String getPackageName() {
-        return packageName;
-    }
-
-    public Version getVersion() {
-        return version;
-    }
-    
-    public void addBundle(Bundle bundle) {
-        this.bundles.add(bundle);
-    }
-    
-    public Set<Bundle> getBundles() {
-        return this.bundles;
-    }
-
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/karaf/blob/91232f80/package/core/src/main/java/org/apache/karaf/packages/core/PackagesMBean.java
----------------------------------------------------------------------
diff --git a/package/core/src/main/java/org/apache/karaf/packages/core/PackagesMBean.java b/package/core/src/main/java/org/apache/karaf/packages/core/PackagesMBean.java
deleted file mode 100644
index 9f07546..0000000
--- a/package/core/src/main/java/org/apache/karaf/packages/core/PackagesMBean.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * 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.karaf.packages.core;
-
-import java.util.List;
-
-import javax.management.openmbean.TabularData;
-
-/**
- * Packages MBean.
- */
-public interface PackagesMBean {
-
-    TabularData getExports();
-    TabularData getImports();
-    List<String> getExports(long bundleId);
-    List<String> getImports(long bundleId);
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/91232f80/package/core/src/main/java/org/apache/karaf/packages/core/internal/PackageServiceImpl.java
----------------------------------------------------------------------
diff --git a/package/core/src/main/java/org/apache/karaf/packages/core/internal/PackageServiceImpl.java b/package/core/src/main/java/org/apache/karaf/packages/core/internal/PackageServiceImpl.java
deleted file mode 100644
index a7e7dd1..0000000
--- a/package/core/src/main/java/org/apache/karaf/packages/core/internal/PackageServiceImpl.java
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * 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.karaf.packages.core.internal;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import java.util.SortedMap;
-import java.util.TreeMap;
-
-import org.apache.karaf.packages.core.PackageRequirement;
-import org.apache.karaf.packages.core.PackageService;
-import org.apache.karaf.packages.core.PackageVersion;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.Version;
-import org.osgi.framework.wiring.BundleCapability;
-import org.osgi.framework.wiring.BundleRequirement;
-import org.osgi.framework.wiring.BundleRevision;
-
-public class PackageServiceImpl implements PackageService {
-
-    private final BundleContext bundleContext;
-
-    public PackageServiceImpl(BundleContext bundleContext) {
-        this.bundleContext = bundleContext;
-    }
-
-    public SortedMap<String, PackageVersion> getExports() {
-        Bundle[] bundles = bundleContext.getBundles();
-        SortedMap<String, PackageVersion> packageVersionMap = new TreeMap<String, PackageVersion>();
-        for (Bundle bundle : bundles) {
-            BundleRevision rev = bundle.adapt(BundleRevision.class);
-            if (rev != null) {
-                List<BundleCapability> caps = rev.getDeclaredCapabilities(BundleRevision.PACKAGE_NAMESPACE);
-                for (BundleCapability cap : caps) {
-                    Map<String, Object> attr = cap.getAttributes();
-                    String packageName = (String)attr.get(BundleRevision.PACKAGE_NAMESPACE);
-                    Version version = (Version)attr.get("version");
-                    String key = packageName + ":" + version.toString();
-                    PackageVersion pVer = packageVersionMap.get(key);
-                    if (pVer == null) {
-                        pVer = new PackageVersion(packageName, version);
-                        packageVersionMap.put(key, pVer);
-                    }
-                    pVer.addBundle(bundle);
-                }
-            }
-        }
-        return packageVersionMap;
-    }
-
-    @Override
-    public SortedMap<String, PackageRequirement> getImports() {
-        Bundle[] bundles = bundleContext.getBundles();
-        SortedMap<String, PackageRequirement> filterMap = new TreeMap<String, PackageRequirement>();
-        for (Bundle bundle : bundles) {
-            BundleRevision rev = bundle.adapt(BundleRevision.class);
-            if (rev != null) {
-                List<BundleRequirement> reqs = rev.getDeclaredRequirements(BundleRevision.PACKAGE_NAMESPACE);
-                for (BundleRequirement req : reqs) {
-                    Map<String, String> attr = req.getDirectives();
-                    String filter = attr.get("filter");
-                    String resolution = attr.get("resolution");
-                    boolean optional = "optional".equals(resolution);
-                    boolean resolveable = checkResolveAble(req);
-                    PackageRequirement preq = new PackageRequirement(filter, optional, bundle, resolveable);
-                    filterMap.put(filter, preq);
-                }
-            }
-        }
-        return filterMap;
-    }
-
-    private boolean checkResolveAble(BundleRequirement req) {
-        Bundle[] bundles = bundleContext.getBundles();
-        for (Bundle bundle : bundles) {
-            BundleRevision rev = bundle.adapt(BundleRevision.class);
-            if (rev != null) {
-                List<BundleCapability> caps = rev.getDeclaredCapabilities(BundleRevision.PACKAGE_NAMESPACE);
-                for (BundleCapability cap : caps) {
-                    if (req.matches(cap)) {
-                        return true;
-                    }
-                }
-            }
-        }
-        return false;
-    }
-
-	@Override
-	public List<String> getExports(long bundleId) {
-		Bundle bundle = bundleContext.getBundle(bundleId);
-        BundleRevision rev = bundle.adapt(BundleRevision.class);
-        List<BundleCapability> caps = rev.getDeclaredCapabilities(BundleRevision.PACKAGE_NAMESPACE);
-        List<String> exports = new ArrayList<String>();
-        for (BundleCapability cap : caps) {
-            Map<String, Object> attr = cap.getAttributes();
-            String packageName = (String)attr.get(BundleRevision.PACKAGE_NAMESPACE);
-            exports.add(packageName);
-        }
-		return exports ;
-	}
-
-	@Override
-	public List<String> getImports(long bundleId) {
-		Bundle bundle = bundleContext.getBundle(bundleId);
-        BundleRevision rev = bundle.adapt(BundleRevision.class);
-        List<BundleRequirement> reqs = rev.getDeclaredRequirements(BundleRevision.PACKAGE_NAMESPACE);
-        List<String> imports = new ArrayList<String>();
-        for (BundleRequirement req : reqs) {
-            Map<String, String> attr = req.getDirectives();
-            String filter = attr.get("filter");
-            String name = PackageRequirement.getPackageName(filter);
-            imports.add(name);
-        }
-		return imports;
-	}
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/91232f80/package/core/src/main/java/org/apache/karaf/packages/core/internal/PackagesMBeanImpl.java
----------------------------------------------------------------------
diff --git a/package/core/src/main/java/org/apache/karaf/packages/core/internal/PackagesMBeanImpl.java b/package/core/src/main/java/org/apache/karaf/packages/core/internal/PackagesMBeanImpl.java
deleted file mode 100644
index bce7b8f..0000000
--- a/package/core/src/main/java/org/apache/karaf/packages/core/internal/PackagesMBeanImpl.java
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * 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.karaf.packages.core.internal;
-
-import java.util.List;
-import java.util.SortedMap;
-
-import javax.management.NotCompliantMBeanException;
-import javax.management.StandardMBean;
-import javax.management.openmbean.CompositeData;
-import javax.management.openmbean.CompositeDataSupport;
-import javax.management.openmbean.CompositeType;
-import javax.management.openmbean.OpenDataException;
-import javax.management.openmbean.OpenType;
-import javax.management.openmbean.SimpleType;
-import javax.management.openmbean.TabularData;
-import javax.management.openmbean.TabularDataSupport;
-import javax.management.openmbean.TabularType;
-
-import org.apache.karaf.packages.core.PackageRequirement;
-import org.apache.karaf.packages.core.PackageService;
-import org.apache.karaf.packages.core.PackageVersion;
-import org.apache.karaf.packages.core.PackagesMBean;
-import org.osgi.framework.Bundle;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Implementation of the Packages MBean.
- */
-public class PackagesMBeanImpl extends StandardMBean implements PackagesMBean {
-
-    private final static Logger LOGGER = LoggerFactory.getLogger(PackagesMBeanImpl.class);
-
-    private final PackageService packageService;
-
-    public PackagesMBeanImpl(PackageService packageService) throws NotCompliantMBeanException {
-        super(PackagesMBean.class);
-        this.packageService = packageService;
-    }
-
-    public TabularData getExports() {
-        try {
-            String[] names = new String[] {"Name", "Version", "ID", "Bundle Name"};
-            CompositeType bundleType = new CompositeType("PackageExport", "Exported packages", names,
-                                                         new String[] {"Package name", "Version of the Package",
-                                                                       "ID of the Bundle", "Bundle symbolic name"},
-                                                         new OpenType[] {SimpleType.STRING, SimpleType.STRING,
-                                                                         SimpleType.LONG, SimpleType.STRING});
-            TabularType tableType = new TabularType("PackageExports", "Exported packages", bundleType,
-                                                    new String[] {"Name", "Version", "ID"});
-            TabularData table = new TabularDataSupport(tableType);
-
-            SortedMap<String, PackageVersion> exports = packageService.getExports();
-
-            for (String key : exports.keySet()) {
-                PackageVersion export = exports.get(key);
-                for (Bundle bundle : export.getBundles()) {
-                    Object[] data = new Object[] {
-                                         export.getPackageName(),
-                                         export.getVersion().toString(), 
-                                         bundle.getBundleId(),
-                                         bundle.getSymbolicName()};
-                    CompositeData comp = new CompositeDataSupport(bundleType, names, data);
-                    LOGGER.debug("Adding CompositeDataSupport {} for key: {}", comp, key);
-                    table.put(comp);
-                }
-            }
-            return table;
-        } catch (RuntimeException e) {
-            // To avoid the exception gets swallowed by jmx
-            LOGGER.error(e.getMessage(), e);
-            throw e;
-        } catch (OpenDataException e) {
-            LOGGER.error(e.getMessage(), e);
-            throw new RuntimeException(e.getMessage(), e);
-        }
-    }
-
-    @Override
-    public TabularData getImports() {
-        try {
-            String[] names = new String[] {"PackageName", "Filter", "Optional", "ID", "Bundle Name", "Resolvable"};
-            CompositeType bundleType = new CompositeType("PackageImports", "Imported packages", 
-                                                         names,
-                                                         names,
-                                                         new OpenType[] {SimpleType.STRING, SimpleType.STRING, SimpleType.BOOLEAN,
-                                                                         SimpleType.LONG, SimpleType.STRING, SimpleType.BOOLEAN});
-            TabularType tableType = new TabularType("PackageImports", "Imported packages", bundleType,
-                                                    new String[] {"Filter", "ID"});
-            TabularData table = new TabularDataSupport(tableType);
-
-            SortedMap<String, PackageRequirement> imports = packageService.getImports();
-
-            for (String key : imports.keySet()) {
-                PackageRequirement req = imports.get(key);
-                Object[] data = new Object[] {
-                                         req.getPackageName(),
-                                         req.getFilter(),
-                                         req.isOptional(), 
-                                         req.getBundle().getBundleId(),
-                                         req.getBundle().getSymbolicName(),
-                                         req.isResolveable()};
-                CompositeData comp = new CompositeDataSupport(bundleType, names, data);
-                table.put(comp);
-             }
-            return table;
-        } catch (RuntimeException e) {
-            // To avoid the exception gets swallowed by jmx
-            LOGGER.error(e.getMessage(), e);
-            throw e;
-        } catch (OpenDataException e) {
-            LOGGER.error(e.getMessage(), e);
-            throw new RuntimeException(e.getMessage(), e);
-        }
-    }
-
-	@Override
-	public List<String> getExports(long bundleId) {
-		return packageService.getExports(bundleId);
-		
-	}
-
-	@Override
-	public List<String> getImports(long bundleId) {
-		return packageService.getImports(bundleId);
-	}
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/91232f80/package/core/src/main/java/org/apache/karaf/packages/core/internal/osgi/Activator.java
----------------------------------------------------------------------
diff --git a/package/core/src/main/java/org/apache/karaf/packages/core/internal/osgi/Activator.java b/package/core/src/main/java/org/apache/karaf/packages/core/internal/osgi/Activator.java
deleted file mode 100644
index ea8ce1d..0000000
--- a/package/core/src/main/java/org/apache/karaf/packages/core/internal/osgi/Activator.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * 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.karaf.packages.core.internal.osgi;
-
-import org.apache.karaf.packages.core.PackageService;
-import org.apache.karaf.packages.core.internal.PackageServiceImpl;
-import org.apache.karaf.packages.core.internal.PackagesMBeanImpl;
-import org.apache.karaf.util.tracker.BaseActivator;
-
-public class Activator extends BaseActivator {
-
-    @Override
-    protected void doStart() throws Exception {
-        PackageService packageService = new PackageServiceImpl(bundleContext);
-        register(PackageService.class, packageService);
-
-        PackagesMBeanImpl mbean = new PackagesMBeanImpl(packageService);
-        registerMBean(mbean, "type=package");
-    }
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/91232f80/package/core/src/main/resources/OSGI-INF/bundle.info
----------------------------------------------------------------------
diff --git a/package/core/src/main/resources/OSGI-INF/bundle.info b/package/core/src/main/resources/OSGI-INF/bundle.info
deleted file mode 100644
index b5747b7..0000000
--- a/package/core/src/main/resources/OSGI-INF/bundle.info
+++ /dev/null
@@ -1,15 +0,0 @@
-h1. Synopsis
-
-${project.name}
-
-${project.description}
-
-Maven URL:
-   [mvn:${project.groupId}/${project.artifactId}/${project.version}]
-
-h1. Description
-
-Services for handling packages
-
-h1. See also
-

http://git-wip-us.apache.org/repos/asf/karaf/blob/91232f80/package/core/src/test/java/org/apache/karaf/packages/core/InstallMBeantest.java
----------------------------------------------------------------------
diff --git a/package/core/src/test/java/org/apache/karaf/packages/core/InstallMBeantest.java b/package/core/src/test/java/org/apache/karaf/packages/core/InstallMBeantest.java
deleted file mode 100644
index a9ab11b..0000000
--- a/package/core/src/test/java/org/apache/karaf/packages/core/InstallMBeantest.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * 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.karaf.packages.core;
-
-import java.lang.management.ManagementFactory;
-
-import javax.management.MBeanServer;
-import javax.management.ObjectName;
-
-import org.apache.karaf.packages.core.internal.PackagesMBeanImpl;
-import org.junit.Test;
-
-/**
- * Checks that the PackagesMBean is valid and can be installed in the MBeanServer
- *
- */
-public class InstallMBeantest {
-
-    @Test
-    public void test() throws Exception {
-        MBeanServer server = ManagementFactory.getPlatformMBeanServer();
-        PackagesMBeanImpl pack = new PackagesMBeanImpl(null);
-        ObjectName oName = new ObjectName("org.apache.karaf:type=package,name=root");
-        server.registerMBean(pack,  oName);
-        server.unregisterMBean(oName);
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/91232f80/package/core/src/test/java/org/apache/karaf/packages/core/PackageRequirementTest.java
----------------------------------------------------------------------
diff --git a/package/core/src/test/java/org/apache/karaf/packages/core/PackageRequirementTest.java b/package/core/src/test/java/org/apache/karaf/packages/core/PackageRequirementTest.java
deleted file mode 100644
index 2ea1cf8..0000000
--- a/package/core/src/test/java/org/apache/karaf/packages/core/PackageRequirementTest.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * 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.karaf.packages.core;
-
-import junit.framework.Assert;
-
-import org.junit.Test;
-
-public class PackageRequirementTest {
-
-    @Test
-    public void testGetPackageName() {
-        PackageRequirement req = new PackageRequirement("(&(osgi.wiring.package=org.osgi.service.useradmin)(version>=1.1.0))", false, null, false);
-        String packageName = req.getPackageName();
-        Assert.assertEquals("org.osgi.service.useradmin", packageName);
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/91232f80/package/pom.xml
----------------------------------------------------------------------
diff --git a/package/pom.xml b/package/pom.xml
index ae401d8..8c3e1a1 100644
--- a/package/pom.xml
+++ b/package/pom.xml
@@ -10,7 +10,7 @@
         (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
+           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,
@@ -29,13 +29,102 @@
     </parent>
 
     <groupId>org.apache.karaf.package</groupId>
-    <artifactId>package</artifactId>
-    <packaging>pom</packaging>
-    <name>Apache Karaf :: Bundle</name>
-
-    <modules>
-        <module>core</module>
-        <module>command</module>
-    </modules>
+    <artifactId>org.apache.karaf.package.core</artifactId>
+    <packaging>bundle</packaging>
+    <name>Apache Karaf :: Package :: Core</name>
+    <description>Package Services and API</description>
+
+    <properties>
+        <appendedResourcesDirectory>${basedir}/../../etc/appended-resources</appendedResourcesDirectory>
+    </properties>
+
+    <dependencies>
+
+        <dependency>
+            <groupId>org.apache.aries.blueprint</groupId>
+            <artifactId>org.apache.aries.blueprint.api</artifactId>
+            <scope>provided</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>org.osgi.core</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-api</artifactId>
+            <scope>provided</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.felix</groupId>
+            <artifactId>org.apache.felix.utils</artifactId>
+            <scope>provided</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.karaf</groupId>
+            <artifactId>org.apache.karaf.util</artifactId>
+            <scope>provided</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.karaf.shell</groupId>
+            <artifactId>org.apache.karaf.shell.core</artifactId>
+            <optional>true</optional>
+        </dependency>
+
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-jdk14</artifactId>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <resources>
+            <resource>
+                <directory>${project.basedir}/src/main/resources</directory>
+                <includes>
+                    <include>**/*</include>
+                </includes>
+            </resource>
+            <resource>
+                <directory>${project.basedir}/src/main/resources</directory>
+                <filtering>true</filtering>
+                <includes>
+                    <include>**/*.info</include>
+                </includes>
+            </resource>
+        </resources>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+                <configuration>
+                    <instructions>
+                        <Export-Package>
+                            org.apache.karaf.packages.core;-noimport:=true
+                        </Export-Package>
+                        <Private-Package>
+                            org.apache.karaf.packages.command,
+                            org.apache.karaf.packages.core.internal,
+                            org.apache.karaf.packages.core.internal.osgi,
+                            org.apache.karaf.util.tracker,
+                            org.apache.felix.utils.version,
+                            org.apache.felix.utils.manifest
+                        </Private-Package>
+                        <Bundle-Activator>
+                            org.apache.karaf.packages.core.internal.osgi.Activator
+                        </Bundle-Activator>
+                        <Karaf-Commands>
+                            org.apache.karaf.packages.command
+                        </Karaf-Commands>
+                    </instructions>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
 
 </project>

http://git-wip-us.apache.org/repos/asf/karaf/blob/91232f80/package/src/main/java/org/apache/karaf/packages/command/Exports.java
----------------------------------------------------------------------
diff --git a/package/src/main/java/org/apache/karaf/packages/command/Exports.java b/package/src/main/java/org/apache/karaf/packages/command/Exports.java
new file mode 100644
index 0000000..c09a5f6
--- /dev/null
+++ b/package/src/main/java/org/apache/karaf/packages/command/Exports.java
@@ -0,0 +1,132 @@
+/*
+ * 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.karaf.packages.command;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.SortedMap;
+import java.util.TreeMap;
+
+import org.apache.karaf.packages.core.PackageService;
+import org.apache.karaf.packages.core.PackageVersion;
+import org.apache.karaf.shell.api.action.Action;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.Option;
+import org.apache.karaf.shell.api.action.lifecycle.Reference;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.apache.karaf.shell.support.table.Col;
+import org.apache.karaf.shell.support.table.ShellTable;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Version;
+import org.osgi.framework.wiring.BundleCapability;
+import org.osgi.framework.wiring.BundleRevision;
+
+@Command(scope = "package", name = "exports", description = "Lists exported packages and the bundles that export them")
+@Service
+public class Exports implements Action {
+
+    @Option(name = "-d", description = "Only show packages that are exported by more than one bundle", required = false, multiValued = false)
+    private boolean onlyDuplicates;
+
+    @Option(name = "--no-format", description = "Disable table rendered output", required = false, multiValued = false)
+    boolean noFormat;
+
+    @Reference
+    private PackageService packageService;
+
+    @Reference
+    private BundleContext bundleContext;
+
+    @Override
+    public Object execute() throws Exception {
+    	if (onlyDuplicates) {
+    		checkDuplicateExports();
+    	} else {
+    		showExports();
+    	}
+        return null;
+    }
+
+	private void showExports() {
+		SortedMap<String, PackageVersion> exports = packageService.getExports();
+        ShellTable table = new ShellTable();
+        table.column(new Col("Package Name"));
+        table.column(new Col("Version"));
+        table.column(new Col("ID"));
+        table.column(new Col("Bundle Name"));
+        
+        for (String key : exports.keySet()) {
+            PackageVersion pVer = exports.get(key);
+            for (Bundle bundle : pVer.getBundles()) {
+                table.addRow().addContent(pVer.getPackageName(),pVer.getVersion().toString(), bundle.getBundleId(), bundle.getSymbolicName());
+            }
+        }
+        table.print(System.out, !noFormat);
+	}
+    
+    private void checkDuplicateExports() {
+        Bundle[] bundles = bundleContext.getBundles();
+        SortedMap<String, PackageVersion> packageVersionMap = getDuplicatePackages(bundles);
+        ShellTable table = new ShellTable();
+        table.column(new Col("Package Name"));
+        table.column(new Col("Version"));
+        table.column(new Col("Exporting bundles (ID)"));
+       
+        for (String key : packageVersionMap.keySet()) {
+            PackageVersion pVer = packageVersionMap.get(key);
+            if (pVer.getBundles().size() > 1) {
+            	String pBundles = getBundlesSt(pVer.getBundles());
+            	table.addRow().addContent(pVer.getPackageName(), pVer.getVersion().toString(), pBundles); 
+            }
+        }
+        table.print(System.out, !noFormat);
+    }
+
+	private String getBundlesSt(Set<Bundle> bundles) {
+		StringBuilder st = new StringBuilder();
+		for (Bundle bundle : bundles) {
+            st.append(bundle.getBundleId() + " ");
+        }
+		return st.toString();
+	}
+
+	private SortedMap<String, PackageVersion> getDuplicatePackages(
+			Bundle[] bundles) {
+		SortedMap<String, PackageVersion> packageVersionMap = new TreeMap<String, PackageVersion>();
+        for (Bundle bundle : bundles) {
+            BundleRevision rev = bundle.adapt(BundleRevision.class);
+            if (rev!=null) {
+                List<BundleCapability> caps = rev.getDeclaredCapabilities(BundleRevision.PACKAGE_NAMESPACE);
+                for (BundleCapability cap : caps) {
+                    Map<String, Object> attr = cap.getAttributes();
+                    String packageName = (String)attr.get(BundleRevision.PACKAGE_NAMESPACE);
+                    Version version = (Version)attr.get("version");
+                    String key = packageName + ":" + version.toString();
+                    PackageVersion pVer = packageVersionMap.get(key);
+                    if (pVer == null) {
+                        pVer = new PackageVersion(packageName, version);
+                        packageVersionMap.put(key, pVer);
+                    }
+                    pVer.addBundle(bundle);
+                }
+            }
+        }
+		return packageVersionMap;
+	}
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/91232f80/package/src/main/java/org/apache/karaf/packages/command/Imports.java
----------------------------------------------------------------------
diff --git a/package/src/main/java/org/apache/karaf/packages/command/Imports.java b/package/src/main/java/org/apache/karaf/packages/command/Imports.java
new file mode 100644
index 0000000..3d086e9
--- /dev/null
+++ b/package/src/main/java/org/apache/karaf/packages/command/Imports.java
@@ -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.karaf.packages.command;
+
+import java.util.SortedMap;
+
+import org.apache.karaf.packages.core.PackageRequirement;
+import org.apache.karaf.packages.core.PackageService;
+import org.apache.karaf.shell.api.action.Action;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.Option;
+import org.apache.karaf.shell.api.action.lifecycle.Reference;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.apache.karaf.shell.support.table.Col;
+import org.apache.karaf.shell.support.table.ShellTable;
+import org.osgi.framework.Bundle;
+
+@Command(scope = "package", name = "imports", description = "Lists imported packages and the bundles that import them")
+@Service
+public class Imports implements Action {
+    
+    @Option(name = "-p", description = "Only show package instead of full filter", required = false, multiValued = false)
+    boolean onlyPackage;
+
+    @Option(name = "--no-format", description = "Disable table rendered output", required = false, multiValued = false)
+    boolean noFormat;
+
+    @Reference
+    private PackageService packageService;
+
+    @Override
+    public Object execute() throws Exception {
+        SortedMap<String, PackageRequirement> imports = packageService.getImports();
+        ShellTable table = new ShellTable();
+        table.column(new Col(onlyPackage ? "Package name" : "Filter"));
+        table.column(new Col("Optional"));
+        table.column(new Col("ID"));
+        table.column(new Col("Bundle Name"));
+        table.column(new Col("Resolveable"));
+        
+        for (String filter : imports.keySet()) {
+            PackageRequirement req = imports.get(filter);
+            Bundle bundle = req.getBundle();
+            String firstCol = onlyPackage ? req.getPackageName() : req.getFilter();
+            table.addRow().addContent(firstCol, req.isOptional() ? "optional" : "", bundle.getBundleId(), bundle.getSymbolicName(), req.isResolveable());
+        }
+        table.print(System.out, !noFormat);
+        return null;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/91232f80/package/src/main/java/org/apache/karaf/packages/core/PackageRequirement.java
----------------------------------------------------------------------
diff --git a/package/src/main/java/org/apache/karaf/packages/core/PackageRequirement.java b/package/src/main/java/org/apache/karaf/packages/core/PackageRequirement.java
new file mode 100644
index 0000000..ed8550b
--- /dev/null
+++ b/package/src/main/java/org/apache/karaf/packages/core/PackageRequirement.java
@@ -0,0 +1,64 @@
+/*
+ * 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.karaf.packages.core;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.osgi.framework.Bundle;
+
+public class PackageRequirement {
+    private String filter;
+    private boolean optional;
+    private Bundle bundle;
+    private boolean resolveable;
+    private static Pattern packagePattern  = Pattern.compile(".*" + Pattern.quote("(osgi.wiring.package=") + "(.*?)\\).*");
+    
+    public PackageRequirement(String filter, boolean optional, Bundle bundle, boolean resolveable) {
+        super();
+        this.filter = filter;
+        this.optional = optional;
+        this.bundle = bundle;
+        this.resolveable = resolveable;
+    }
+    
+    public Bundle getBundle() {
+        return bundle;
+    }
+
+    public String getFilter() {
+        return filter;
+    }
+    public boolean isOptional() {
+        return optional;
+    }
+
+    public boolean isResolveable() {
+        return resolveable;
+    }
+
+    public String getPackageName() {
+        return getPackageName(filter);
+    }
+    
+    public static String getPackageName(String filter) {
+        Matcher matcher = packagePattern.matcher(filter);
+        matcher.matches();
+        return matcher.group(1);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/91232f80/package/src/main/java/org/apache/karaf/packages/core/PackageService.java
----------------------------------------------------------------------
diff --git a/package/src/main/java/org/apache/karaf/packages/core/PackageService.java b/package/src/main/java/org/apache/karaf/packages/core/PackageService.java
new file mode 100644
index 0000000..d6ccc65
--- /dev/null
+++ b/package/src/main/java/org/apache/karaf/packages/core/PackageService.java
@@ -0,0 +1,51 @@
+/*
+ * 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.karaf.packages.core;
+
+import java.util.List;
+import java.util.SortedMap;
+
+public interface PackageService {
+
+	/**
+	 * Gets the simplified package exports of a bundle. This does not show the 
+	 * package versions.
+	 * 
+	 * @param bundleId
+	 * @return
+	 */
+    List<String> getExports(long bundleId);
+
+    List<String> getImports(long bundleId);
+
+	/**
+	 * Gets a map of all exported packages with their version and the bundles that exprot them
+	 * The key is in the form packagename:version.
+	 * 
+	 * @return 
+	 */
+    SortedMap<String, PackageVersion> getExports();
+
+    /**
+     * Gets a map of all package imports. 
+     * The key is the import filter.
+     *  
+     * @return
+     */
+    SortedMap<String, PackageRequirement> getImports();
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/91232f80/package/src/main/java/org/apache/karaf/packages/core/PackageVersion.java
----------------------------------------------------------------------
diff --git a/package/src/main/java/org/apache/karaf/packages/core/PackageVersion.java b/package/src/main/java/org/apache/karaf/packages/core/PackageVersion.java
new file mode 100644
index 0000000..aed0c48
--- /dev/null
+++ b/package/src/main/java/org/apache/karaf/packages/core/PackageVersion.java
@@ -0,0 +1,52 @@
+/*
+ * 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.karaf.packages.core;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.osgi.framework.Bundle;
+import org.osgi.framework.Version;
+
+public class PackageVersion {
+
+    private String packageName;
+    private Version version;
+    private Set<Bundle> bundles = new HashSet<Bundle>();
+    
+    public PackageVersion(String packageName, Version version) {
+        this.packageName = packageName;
+        this.version = version;
+    }
+    
+    public String getPackageName() {
+        return packageName;
+    }
+
+    public Version getVersion() {
+        return version;
+    }
+    
+    public void addBundle(Bundle bundle) {
+        this.bundles.add(bundle);
+    }
+    
+    public Set<Bundle> getBundles() {
+        return this.bundles;
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/karaf/blob/91232f80/package/src/main/java/org/apache/karaf/packages/core/PackagesMBean.java
----------------------------------------------------------------------
diff --git a/package/src/main/java/org/apache/karaf/packages/core/PackagesMBean.java b/package/src/main/java/org/apache/karaf/packages/core/PackagesMBean.java
new file mode 100644
index 0000000..9f07546
--- /dev/null
+++ b/package/src/main/java/org/apache/karaf/packages/core/PackagesMBean.java
@@ -0,0 +1,32 @@
+/*
+ * 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.karaf.packages.core;
+
+import java.util.List;
+
+import javax.management.openmbean.TabularData;
+
+/**
+ * Packages MBean.
+ */
+public interface PackagesMBean {
+
+    TabularData getExports();
+    TabularData getImports();
+    List<String> getExports(long bundleId);
+    List<String> getImports(long bundleId);
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/91232f80/package/src/main/java/org/apache/karaf/packages/core/internal/PackageServiceImpl.java
----------------------------------------------------------------------
diff --git a/package/src/main/java/org/apache/karaf/packages/core/internal/PackageServiceImpl.java b/package/src/main/java/org/apache/karaf/packages/core/internal/PackageServiceImpl.java
new file mode 100644
index 0000000..a7e7dd1
--- /dev/null
+++ b/package/src/main/java/org/apache/karaf/packages/core/internal/PackageServiceImpl.java
@@ -0,0 +1,134 @@
+/*
+ * 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.karaf.packages.core.internal;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.SortedMap;
+import java.util.TreeMap;
+
+import org.apache.karaf.packages.core.PackageRequirement;
+import org.apache.karaf.packages.core.PackageService;
+import org.apache.karaf.packages.core.PackageVersion;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Version;
+import org.osgi.framework.wiring.BundleCapability;
+import org.osgi.framework.wiring.BundleRequirement;
+import org.osgi.framework.wiring.BundleRevision;
+
+public class PackageServiceImpl implements PackageService {
+
+    private final BundleContext bundleContext;
+
+    public PackageServiceImpl(BundleContext bundleContext) {
+        this.bundleContext = bundleContext;
+    }
+
+    public SortedMap<String, PackageVersion> getExports() {
+        Bundle[] bundles = bundleContext.getBundles();
+        SortedMap<String, PackageVersion> packageVersionMap = new TreeMap<String, PackageVersion>();
+        for (Bundle bundle : bundles) {
+            BundleRevision rev = bundle.adapt(BundleRevision.class);
+            if (rev != null) {
+                List<BundleCapability> caps = rev.getDeclaredCapabilities(BundleRevision.PACKAGE_NAMESPACE);
+                for (BundleCapability cap : caps) {
+                    Map<String, Object> attr = cap.getAttributes();
+                    String packageName = (String)attr.get(BundleRevision.PACKAGE_NAMESPACE);
+                    Version version = (Version)attr.get("version");
+                    String key = packageName + ":" + version.toString();
+                    PackageVersion pVer = packageVersionMap.get(key);
+                    if (pVer == null) {
+                        pVer = new PackageVersion(packageName, version);
+                        packageVersionMap.put(key, pVer);
+                    }
+                    pVer.addBundle(bundle);
+                }
+            }
+        }
+        return packageVersionMap;
+    }
+
+    @Override
+    public SortedMap<String, PackageRequirement> getImports() {
+        Bundle[] bundles = bundleContext.getBundles();
+        SortedMap<String, PackageRequirement> filterMap = new TreeMap<String, PackageRequirement>();
+        for (Bundle bundle : bundles) {
+            BundleRevision rev = bundle.adapt(BundleRevision.class);
+            if (rev != null) {
+                List<BundleRequirement> reqs = rev.getDeclaredRequirements(BundleRevision.PACKAGE_NAMESPACE);
+                for (BundleRequirement req : reqs) {
+                    Map<String, String> attr = req.getDirectives();
+                    String filter = attr.get("filter");
+                    String resolution = attr.get("resolution");
+                    boolean optional = "optional".equals(resolution);
+                    boolean resolveable = checkResolveAble(req);
+                    PackageRequirement preq = new PackageRequirement(filter, optional, bundle, resolveable);
+                    filterMap.put(filter, preq);
+                }
+            }
+        }
+        return filterMap;
+    }
+
+    private boolean checkResolveAble(BundleRequirement req) {
+        Bundle[] bundles = bundleContext.getBundles();
+        for (Bundle bundle : bundles) {
+            BundleRevision rev = bundle.adapt(BundleRevision.class);
+            if (rev != null) {
+                List<BundleCapability> caps = rev.getDeclaredCapabilities(BundleRevision.PACKAGE_NAMESPACE);
+                for (BundleCapability cap : caps) {
+                    if (req.matches(cap)) {
+                        return true;
+                    }
+                }
+            }
+        }
+        return false;
+    }
+
+	@Override
+	public List<String> getExports(long bundleId) {
+		Bundle bundle = bundleContext.getBundle(bundleId);
+        BundleRevision rev = bundle.adapt(BundleRevision.class);
+        List<BundleCapability> caps = rev.getDeclaredCapabilities(BundleRevision.PACKAGE_NAMESPACE);
+        List<String> exports = new ArrayList<String>();
+        for (BundleCapability cap : caps) {
+            Map<String, Object> attr = cap.getAttributes();
+            String packageName = (String)attr.get(BundleRevision.PACKAGE_NAMESPACE);
+            exports.add(packageName);
+        }
+		return exports ;
+	}
+
+	@Override
+	public List<String> getImports(long bundleId) {
+		Bundle bundle = bundleContext.getBundle(bundleId);
+        BundleRevision rev = bundle.adapt(BundleRevision.class);
+        List<BundleRequirement> reqs = rev.getDeclaredRequirements(BundleRevision.PACKAGE_NAMESPACE);
+        List<String> imports = new ArrayList<String>();
+        for (BundleRequirement req : reqs) {
+            Map<String, String> attr = req.getDirectives();
+            String filter = attr.get("filter");
+            String name = PackageRequirement.getPackageName(filter);
+            imports.add(name);
+        }
+		return imports;
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/91232f80/package/src/main/java/org/apache/karaf/packages/core/internal/PackagesMBeanImpl.java
----------------------------------------------------------------------
diff --git a/package/src/main/java/org/apache/karaf/packages/core/internal/PackagesMBeanImpl.java b/package/src/main/java/org/apache/karaf/packages/core/internal/PackagesMBeanImpl.java
new file mode 100644
index 0000000..bce7b8f
--- /dev/null
+++ b/package/src/main/java/org/apache/karaf/packages/core/internal/PackagesMBeanImpl.java
@@ -0,0 +1,143 @@
+/*
+ * 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.karaf.packages.core.internal;
+
+import java.util.List;
+import java.util.SortedMap;
+
+import javax.management.NotCompliantMBeanException;
+import javax.management.StandardMBean;
+import javax.management.openmbean.CompositeData;
+import javax.management.openmbean.CompositeDataSupport;
+import javax.management.openmbean.CompositeType;
+import javax.management.openmbean.OpenDataException;
+import javax.management.openmbean.OpenType;
+import javax.management.openmbean.SimpleType;
+import javax.management.openmbean.TabularData;
+import javax.management.openmbean.TabularDataSupport;
+import javax.management.openmbean.TabularType;
+
+import org.apache.karaf.packages.core.PackageRequirement;
+import org.apache.karaf.packages.core.PackageService;
+import org.apache.karaf.packages.core.PackageVersion;
+import org.apache.karaf.packages.core.PackagesMBean;
+import org.osgi.framework.Bundle;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Implementation of the Packages MBean.
+ */
+public class PackagesMBeanImpl extends StandardMBean implements PackagesMBean {
+
+    private final static Logger LOGGER = LoggerFactory.getLogger(PackagesMBeanImpl.class);
+
+    private final PackageService packageService;
+
+    public PackagesMBeanImpl(PackageService packageService) throws NotCompliantMBeanException {
+        super(PackagesMBean.class);
+        this.packageService = packageService;
+    }
+
+    public TabularData getExports() {
+        try {
+            String[] names = new String[] {"Name", "Version", "ID", "Bundle Name"};
+            CompositeType bundleType = new CompositeType("PackageExport", "Exported packages", names,
+                                                         new String[] {"Package name", "Version of the Package",
+                                                                       "ID of the Bundle", "Bundle symbolic name"},
+                                                         new OpenType[] {SimpleType.STRING, SimpleType.STRING,
+                                                                         SimpleType.LONG, SimpleType.STRING});
+            TabularType tableType = new TabularType("PackageExports", "Exported packages", bundleType,
+                                                    new String[] {"Name", "Version", "ID"});
+            TabularData table = new TabularDataSupport(tableType);
+
+            SortedMap<String, PackageVersion> exports = packageService.getExports();
+
+            for (String key : exports.keySet()) {
+                PackageVersion export = exports.get(key);
+                for (Bundle bundle : export.getBundles()) {
+                    Object[] data = new Object[] {
+                                         export.getPackageName(),
+                                         export.getVersion().toString(), 
+                                         bundle.getBundleId(),
+                                         bundle.getSymbolicName()};
+                    CompositeData comp = new CompositeDataSupport(bundleType, names, data);
+                    LOGGER.debug("Adding CompositeDataSupport {} for key: {}", comp, key);
+                    table.put(comp);
+                }
+            }
+            return table;
+        } catch (RuntimeException e) {
+            // To avoid the exception gets swallowed by jmx
+            LOGGER.error(e.getMessage(), e);
+            throw e;
+        } catch (OpenDataException e) {
+            LOGGER.error(e.getMessage(), e);
+            throw new RuntimeException(e.getMessage(), e);
+        }
+    }
+
+    @Override
+    public TabularData getImports() {
+        try {
+            String[] names = new String[] {"PackageName", "Filter", "Optional", "ID", "Bundle Name", "Resolvable"};
+            CompositeType bundleType = new CompositeType("PackageImports", "Imported packages", 
+                                                         names,
+                                                         names,
+                                                         new OpenType[] {SimpleType.STRING, SimpleType.STRING, SimpleType.BOOLEAN,
+                                                                         SimpleType.LONG, SimpleType.STRING, SimpleType.BOOLEAN});
+            TabularType tableType = new TabularType("PackageImports", "Imported packages", bundleType,
+                                                    new String[] {"Filter", "ID"});
+            TabularData table = new TabularDataSupport(tableType);
+
+            SortedMap<String, PackageRequirement> imports = packageService.getImports();
+
+            for (String key : imports.keySet()) {
+                PackageRequirement req = imports.get(key);
+                Object[] data = new Object[] {
+                                         req.getPackageName(),
+                                         req.getFilter(),
+                                         req.isOptional(), 
+                                         req.getBundle().getBundleId(),
+                                         req.getBundle().getSymbolicName(),
+                                         req.isResolveable()};
+                CompositeData comp = new CompositeDataSupport(bundleType, names, data);
+                table.put(comp);
+             }
+            return table;
+        } catch (RuntimeException e) {
+            // To avoid the exception gets swallowed by jmx
+            LOGGER.error(e.getMessage(), e);
+            throw e;
+        } catch (OpenDataException e) {
+            LOGGER.error(e.getMessage(), e);
+            throw new RuntimeException(e.getMessage(), e);
+        }
+    }
+
+	@Override
+	public List<String> getExports(long bundleId) {
+		return packageService.getExports(bundleId);
+		
+	}
+
+	@Override
+	public List<String> getImports(long bundleId) {
+		return packageService.getImports(bundleId);
+	}
+
+}


[07/59] [abbrv] [KARAF-2852] Merge features/core and features/command

Posted by gn...@apache.org.
http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/src/main/java/org/apache/karaf/features/internal/management/FeaturesServiceMBeanImpl.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/management/FeaturesServiceMBeanImpl.java b/features/src/main/java/org/apache/karaf/features/internal/management/FeaturesServiceMBeanImpl.java
new file mode 100644
index 0000000..b1a5865
--- /dev/null
+++ b/features/src/main/java/org/apache/karaf/features/internal/management/FeaturesServiceMBeanImpl.java
@@ -0,0 +1,290 @@
+/*
+ * 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.features.internal.management;
+
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.EnumSet;
+import java.util.Hashtable;
+import java.util.List;
+
+import javax.management.MBeanNotificationInfo;
+import javax.management.MBeanRegistration;
+import javax.management.MBeanServer;
+import javax.management.NotCompliantMBeanException;
+import javax.management.Notification;
+import javax.management.ObjectName;
+import javax.management.openmbean.TabularData;
+
+import org.apache.karaf.features.*;
+import org.apache.karaf.features.management.FeaturesServiceMBean;
+import org.apache.karaf.features.management.codec.JmxFeature;
+import org.apache.karaf.features.management.codec.JmxFeatureEvent;
+import org.apache.karaf.features.management.codec.JmxRepository;
+import org.apache.karaf.features.management.codec.JmxRepositoryEvent;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceRegistration;
+
+/**
+ * Implementation of {@link FeaturesServiceMBean}.
+ */
+public class FeaturesServiceMBeanImpl extends StandardEmitterMBean implements
+        MBeanRegistration, FeaturesServiceMBean {
+
+    private ServiceRegistration<FeaturesListener> registration;
+
+    private BundleContext bundleContext;
+
+    private ObjectName objectName;
+
+    private volatile long sequenceNumber = 0;
+
+    private org.apache.karaf.features.FeaturesService featuresService;
+
+    public FeaturesServiceMBeanImpl() throws NotCompliantMBeanException {
+        super(FeaturesServiceMBean.class);
+    }
+
+    public ObjectName preRegister(MBeanServer server, ObjectName name) throws Exception {
+        objectName = name;
+        return name;
+    }
+
+    public void postRegister(Boolean registrationDone) {
+        registration = bundleContext.registerService(FeaturesListener.class,
+                getFeaturesListener(), new Hashtable<String, String>());
+    }
+
+    public void preDeregister() throws Exception {
+        registration.unregister();
+    }
+
+    public void postDeregister() {
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public TabularData getFeatures() throws Exception {
+        try {
+            List<Feature> allFeatures = Arrays.asList(featuresService.listFeatures());
+            List<Feature> insFeatures = Arrays.asList(featuresService.listInstalledFeatures());
+            ArrayList<JmxFeature> features = new ArrayList<JmxFeature>();
+            for (Feature feature : allFeatures) {
+                try {
+                    features.add(new JmxFeature(feature, insFeatures.contains(feature)));
+                } catch (Throwable t) {
+                    t.printStackTrace();
+                }
+            }
+            TabularData table = JmxFeature.tableFrom(features);
+            return table;
+        } catch (Throwable t) {
+            t.printStackTrace();
+            return null;
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public TabularData getRepositories() throws Exception {
+        try {
+            List<Repository> allRepositories = Arrays.asList(featuresService.listRepositories());
+            ArrayList<JmxRepository> repositories = new ArrayList<JmxRepository>();
+            for (Repository repository : allRepositories) {
+                try {
+                    repositories.add(new JmxRepository(repository));
+                } catch (Throwable t) {
+                    t.printStackTrace();
+                }
+            }
+            TabularData table = JmxRepository.tableFrom(repositories);
+            return table;
+        } catch (Throwable t) {
+            t.printStackTrace();
+            return null;
+        }
+    }
+
+    public void addRepository(String uri) throws Exception {
+        featuresService.addRepository(new URI(uri));
+    }
+
+    public void addRepository(String uri, boolean install) throws Exception {
+        featuresService.addRepository(new URI(uri), install);
+    }
+
+    public void removeRepository(String uri) throws Exception {
+        featuresService.removeRepository(new URI(uri));
+    }
+
+    public void removeRepository(String uri, boolean uninstall) throws Exception {
+        featuresService.removeRepository(new URI(uri), uninstall);
+    }
+
+    public void installFeature(String name) throws Exception {
+        featuresService.installFeature(name);
+    }
+
+    public void installFeature(String name, boolean noRefresh) throws Exception {
+        EnumSet<org.apache.karaf.features.FeaturesService.Option> options = EnumSet.noneOf(org.apache.karaf.features.FeaturesService.Option.class);
+        if (noRefresh) {
+            options.add(org.apache.karaf.features.FeaturesService.Option.NoAutoRefreshBundles);
+        }
+        featuresService.installFeature(name, options);
+    }
+
+    public void installFeature(String name, boolean noRefresh, boolean noStart) throws Exception {
+        EnumSet<org.apache.karaf.features.FeaturesService.Option> options = EnumSet.noneOf(org.apache.karaf.features.FeaturesService.Option.class);
+        if (noRefresh) {
+            options.add(org.apache.karaf.features.FeaturesService.Option.NoAutoRefreshBundles);
+        }
+        if (noStart) {
+            options.add(org.apache.karaf.features.FeaturesService.Option.NoAutoStartBundles);
+        }
+        featuresService.installFeature(name, options);
+    }
+
+    public void installFeature(String name, String version) throws Exception {
+        featuresService.installFeature(name, version);
+    }
+
+    public void installFeature(String name, String version, boolean noRefresh) throws Exception {
+        EnumSet<org.apache.karaf.features.FeaturesService.Option> options = EnumSet.noneOf(org.apache.karaf.features.FeaturesService.Option.class);
+        if (noRefresh) {
+            options.add(org.apache.karaf.features.FeaturesService.Option.NoAutoRefreshBundles);
+        }
+        featuresService.installFeature(name, version, options);
+    }
+
+    public void installFeature(String name, String version, boolean noRefresh, boolean noStart) throws Exception {
+        EnumSet<org.apache.karaf.features.FeaturesService.Option> options = EnumSet.noneOf(org.apache.karaf.features.FeaturesService.Option.class);
+        if (noRefresh) {
+            options.add(org.apache.karaf.features.FeaturesService.Option.NoAutoRefreshBundles);
+        }
+        if (noStart) {
+            options.add(org.apache.karaf.features.FeaturesService.Option.NoAutoStartBundles);
+        }
+        featuresService.installFeature(name, version, options);
+    }
+
+    public TabularData infoFeature(String name) throws Exception {
+        try {
+            Feature feature = featuresService.getFeature(name);
+            return infoFeature(feature);
+        } catch (Throwable t) {
+            t.printStackTrace();
+            return null;
+        }
+    }
+
+    public TabularData infoFeature(String name, String version) throws Exception {
+        try {
+            Feature feature = featuresService.getFeature(name, version);
+            return infoFeature(feature);
+        } catch (Throwable t) {
+            t.printStackTrace();
+            return null;
+        }
+    }
+
+    private TabularData infoFeature(Feature feature) throws Exception {
+        JmxFeature jmxFeature = null;
+        if (featuresService.isInstalled(feature)) {
+            jmxFeature = new JmxFeature(feature, true);
+        } else {
+            jmxFeature = new JmxFeature(feature, false);
+        }
+        ArrayList<JmxFeature> features = new ArrayList<JmxFeature>();
+        features.add(jmxFeature);
+        TabularData table = JmxFeature.tableFrom(features);
+        return table;
+    }
+
+    public void uninstallFeature(String name) throws Exception {
+        featuresService.uninstallFeature(name);
+    }
+
+    public void uninstallFeature(String name, boolean noRefresh) throws Exception {
+        EnumSet<org.apache.karaf.features.FeaturesService.Option> options = EnumSet.noneOf(org.apache.karaf.features.FeaturesService.Option.class);
+        if (noRefresh) {
+            options.add(org.apache.karaf.features.FeaturesService.Option.NoAutoRefreshBundles);
+        }
+        featuresService.uninstallFeature(name, options);
+    }
+
+    public void uninstallFeature(String name, String version) throws Exception {
+        featuresService.uninstallFeature(name, version);
+    }
+
+    public void uninstallFeature(String name, String version, boolean noRefresh) throws Exception {
+        EnumSet<org.apache.karaf.features.FeaturesService.Option> options = EnumSet.noneOf(org.apache.karaf.features.FeaturesService.Option.class);
+        if (noRefresh) {
+            options.add(org.apache.karaf.features.FeaturesService.Option.NoAutoRefreshBundles);
+        }
+        featuresService.uninstallFeature(name, version, options);
+    }
+
+    public void setBundleContext(BundleContext bundleContext) {
+        this.bundleContext = bundleContext;
+    }
+
+    public void setFeaturesService(org.apache.karaf.features.FeaturesService featuresService) {
+        this.featuresService = featuresService;
+    }
+
+    public FeaturesListener getFeaturesListener() {
+        return new FeaturesListener() {
+            public void featureEvent(FeatureEvent event) {
+                if (!event.isReplay()) {
+                    Notification notification = new Notification(FEATURE_EVENT_TYPE, objectName, sequenceNumber++);
+                    notification.setUserData(new JmxFeatureEvent(event).asCompositeData());
+                    sendNotification(notification);
+                }
+            }
+
+            public void repositoryEvent(RepositoryEvent event) {
+                if (!event.isReplay()) {
+                    Notification notification = new Notification(REPOSITORY_EVENT_TYPE, objectName, sequenceNumber++);
+                    notification.setUserData(new JmxRepositoryEvent(event).asCompositeData());
+                    sendNotification(notification);
+                }
+            }
+
+            public boolean equals(Object o) {
+                if (this == o) {
+                    return true;
+                }
+                return o.equals(this);
+            }
+
+        };
+    }
+
+    public MBeanNotificationInfo[] getNotificationInfo() {
+        return getBroadcastInfo();
+    }
+
+    private static MBeanNotificationInfo[] getBroadcastInfo() {
+        String type = Notification.class.getCanonicalName();
+        MBeanNotificationInfo info1 = new MBeanNotificationInfo(new String[]{FEATURE_EVENT_EVENT_TYPE},
+                type, "Some features notification");
+        MBeanNotificationInfo info2 = new MBeanNotificationInfo(new String[]{REPOSITORY_EVENT_EVENT_TYPE},
+                type, "Some repository notification");
+        return new MBeanNotificationInfo[]{info1, info2};
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/src/main/java/org/apache/karaf/features/internal/management/StandardEmitterMBean.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/management/StandardEmitterMBean.java b/features/src/main/java/org/apache/karaf/features/internal/management/StandardEmitterMBean.java
new file mode 100644
index 0000000..13a4b6c
--- /dev/null
+++ b/features/src/main/java/org/apache/karaf/features/internal/management/StandardEmitterMBean.java
@@ -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.features.internal.management;
+
+import javax.management.*;
+
+public class StandardEmitterMBean extends StandardMBean implements NotificationEmitter {
+
+    private final NotificationBroadcasterSupport emitter;
+
+    @SuppressWarnings("rawtypes")
+	public StandardEmitterMBean(Class mbeanInterface) throws NotCompliantMBeanException {
+        super(mbeanInterface);
+        this.emitter = new NotificationBroadcasterSupport() {
+            @Override
+            public MBeanNotificationInfo[] getNotificationInfo() {
+                return StandardEmitterMBean.this.getNotificationInfo();
+            }
+        };
+    }
+
+    public void sendNotification(Notification notification) {
+        emitter.sendNotification(notification);
+    }
+
+
+    public void removeNotificationListener(NotificationListener listener, NotificationFilter filter, Object handback) throws ListenerNotFoundException {
+        emitter.removeNotificationListener(listener, filter, handback);
+    }
+
+    public void addNotificationListener(NotificationListener listener, NotificationFilter filter, Object handback) throws IllegalArgumentException {
+        emitter.addNotificationListener(listener, filter, handback);
+    }
+
+    public void removeNotificationListener(NotificationListener listener) throws ListenerNotFoundException {
+        emitter.removeNotificationListener(listener);
+    }
+
+    public MBeanNotificationInfo[] getNotificationInfo() {
+        return new MBeanNotificationInfo[0];
+    }
+
+    @Override
+    public MBeanInfo getMBeanInfo() {
+        MBeanInfo mbeanInfo = super.getMBeanInfo();
+        if (mbeanInfo != null) {
+            MBeanNotificationInfo[] notificationInfo = getNotificationInfo();
+            mbeanInfo = new MBeanInfo(mbeanInfo.getClassName(), mbeanInfo.getDescription(), mbeanInfo.getAttributes(),
+                    mbeanInfo.getConstructors(), mbeanInfo.getOperations(), notificationInfo);
+        }
+        return mbeanInfo;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/src/main/java/org/apache/karaf/features/internal/model/Bundle.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/model/Bundle.java b/features/src/main/java/org/apache/karaf/features/internal/model/Bundle.java
new file mode 100644
index 0000000..7eebbe5
--- /dev/null
+++ b/features/src/main/java/org/apache/karaf/features/internal/model/Bundle.java
@@ -0,0 +1,198 @@
+/*
+ * 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.karaf.features.internal.model;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlSchemaType;
+import javax.xml.bind.annotation.XmlType;
+import javax.xml.bind.annotation.XmlValue;
+import org.apache.karaf.features.BundleInfo;
+
+
+/**
+ * 
+ * Deployable element to install.
+ *             
+ * 
+ * <p>Java class for bundle complex type.
+ * 
+ * <p>The following schema fragment specifies the expected content contained within this class.
+ * 
+ * <pre>
+ * &lt;complexType name="bundle">
+ *   &lt;simpleContent>
+ *     &lt;extension base="&lt;http://www.w3.org/2001/XMLSchema>anyURI">
+ *       &lt;attribute name="start-level" type="{http://www.w3.org/2001/XMLSchema}int" />
+ *       &lt;attribute name="start" type="{http://www.w3.org/2001/XMLSchema}boolean" />
+ *       &lt;attribute name="dependency" type="{http://www.w3.org/2001/XMLSchema}boolean" />
+ *     &lt;/extension>
+ *   &lt;/simpleContent>
+ * &lt;/complexType>
+ * </pre>
+ * 
+ * 
+ */
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "bundle", propOrder = {
+    "value"
+})
+public class Bundle implements BundleInfo {
+
+    @XmlValue
+    @XmlSchemaType(name = "anyURI")
+    protected String value;
+    @XmlAttribute(name = "start-level")
+    protected Integer startLevel;
+    @XmlAttribute
+    protected Boolean start;// = true;
+    @XmlAttribute
+    protected Boolean dependency;
+
+
+    public Bundle() {
+    }
+
+    public Bundle(String value) {
+        this.value = value;
+    }
+
+    /**
+     * Gets the value of the value property.
+     * 
+     * @return
+     *     possible object is
+     *     {@link String }
+     *     
+     */
+    public String getLocation() {
+        return value;
+    }
+
+    /**
+     * Sets the value of the value property.
+     * 
+     * @param value
+     *     allowed object is
+     *     {@link String }
+     *     
+     */
+    public void setLocation(String value) {
+        this.value = value;
+    }
+
+    /**
+     * Gets the value of the startLevel property.
+     * 
+     * @return
+     *     possible object is
+     *     {@link Integer }
+     *     
+     */
+    public int getStartLevel() {
+        return startLevel == null? 0: startLevel;
+    }
+
+    /**
+     * Sets the value of the startLevel property.
+     * 
+     * @param value
+     *     allowed object is
+     *     {@link Integer }
+     *     
+     */
+    public void setStartLevel(Integer value) {
+        this.startLevel = value;
+    }
+
+    /**
+     * Gets the value of the start property.
+     * 
+     * @return
+     *     possible object is
+     *     {@link Boolean }
+     *     
+     */
+    public boolean isStart() {
+        return start == null? true: start;
+    }
+
+    /**
+     * Sets the value of the start property.
+     * 
+     * @param value
+     *     allowed object is
+     *     {@link Boolean }
+     *     
+     */
+    public void setStart(Boolean value) {
+        this.start = value;
+    }
+
+    /**
+     * Gets the value of the dependency property.
+     * 
+     * @return
+     *     possible object is
+     *     {@link Boolean }
+     *     
+     */
+    public boolean isDependency() {
+        return dependency == null? false: dependency;
+    }
+
+    /**
+     * Sets the value of the dependency property.
+     * 
+     * @param value
+     *     allowed object is
+     *     {@link Boolean }
+     *     
+     */
+    public void setDependency(Boolean value) {
+        this.dependency = value;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        Bundle bundle = (Bundle) o;
+
+        if (dependency != bundle.dependency) return false;
+        if (start != bundle.start) return false;
+        if (startLevel != bundle.startLevel) return false;
+        if (value != null ? !value.equals(bundle.value) : bundle.value != null) return false;
+
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        int result = value != null ? value.hashCode() : 0;
+        result = 31 * result + getStartLevel();
+        result = 31 * result + (isStart() ? 1 : 0);
+        result = 31 * result + (isDependency() ? 1 : 0);
+        return result;
+    }
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/src/main/java/org/apache/karaf/features/internal/model/Capability.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/model/Capability.java b/features/src/main/java/org/apache/karaf/features/internal/model/Capability.java
new file mode 100644
index 0000000..ef60454
--- /dev/null
+++ b/features/src/main/java/org/apache/karaf/features/internal/model/Capability.java
@@ -0,0 +1,89 @@
+/*
+ * 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.karaf.features.internal.model;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlType;
+import javax.xml.bind.annotation.XmlValue;
+
+import org.apache.karaf.features.BundleInfo;
+
+
+/**
+ * 
+ * Additional capability for a feature.
+ *             
+ * 
+ * <p>Java class for bundle complex type.
+ * 
+ * <p>The following schema fragment specifies the expected content contained within this class.
+ * 
+ * <pre>
+ * &lt;complexType name="capability">
+ *   &lt;simpleContent>
+ *     &lt;extension base="&lt;http://www.w3.org/2001/XMLSchema>string">
+ *     &lt;/extension>
+ *   &lt;/simpleContent>
+ * &lt;/complexType>
+ * </pre>
+ * 
+ * 
+ */
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "capability", propOrder = {
+    "value"
+})
+public class Capability implements org.apache.karaf.features.Capability {
+
+    @XmlValue
+    protected String value;
+
+
+    public Capability() {
+    }
+
+    public Capability(String value) {
+        this.value = value;
+    }
+
+    public String getValue() {
+        return value;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        Capability bundle = (Capability) o;
+
+        if (value != null ? !value.equals(bundle.value) : bundle.value != null) return false;
+
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        int result = value != null ? value.hashCode() : 0;
+        return result;
+    }
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/src/main/java/org/apache/karaf/features/internal/model/Conditional.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/model/Conditional.java b/features/src/main/java/org/apache/karaf/features/internal/model/Conditional.java
new file mode 100644
index 0000000..5bc0b95
--- /dev/null
+++ b/features/src/main/java/org/apache/karaf/features/internal/model/Conditional.java
@@ -0,0 +1,71 @@
+/*
+ * 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.karaf.features.internal.model;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlType;
+import org.apache.karaf.features.Feature;
+
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "conditional", propOrder = {
+        "condition",
+        "config",
+        "configfile",
+        "feature",
+        "bundle"
+})
+public class Conditional extends Content implements org.apache.karaf.features.Conditional {
+
+    @XmlElement(name = "condition")
+    protected List<Dependency> condition;
+
+    public List<Dependency> getCondition() {
+        if (condition == null) {
+            this.condition = new ArrayList<Dependency>();
+        }
+        return condition;
+    }
+
+    @Override
+    public Feature asFeature(String name, String version) {
+        String conditionName = name + "-condition-" + getConditionId().replaceAll("[^A-Za-z0-9 ]", "_");
+        org.apache.karaf.features.internal.model.Feature f = new org.apache.karaf.features.internal.model.Feature(conditionName, version);
+        f.getBundle().addAll(getBundle());
+        f.getConfig().addAll(getConfig());
+        f.getConfigfile().addAll(getConfigfile());
+        f.getFeature().addAll(getFeature());
+        return f;
+    }
+
+    private String getConditionId() {
+        StringBuffer sb = new StringBuffer();
+        Iterator<Dependency> di = getCondition().iterator();
+        while (di.hasNext()) {
+            Dependency dependency = di.next();
+            sb.append(dependency.getName() + "_" + dependency.getVersion());
+            if (di.hasNext()) {
+                sb.append("_");
+            }
+        }
+        return sb.toString();
+    }
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/src/main/java/org/apache/karaf/features/internal/model/Config.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/model/Config.java b/features/src/main/java/org/apache/karaf/features/internal/model/Config.java
new file mode 100644
index 0000000..a2c6674
--- /dev/null
+++ b/features/src/main/java/org/apache/karaf/features/internal/model/Config.java
@@ -0,0 +1,110 @@
+/*
+ * 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.karaf.features.internal.model;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlType;
+import javax.xml.bind.annotation.XmlValue;
+
+
+/**
+ * 
+ * Configuration entries which should be created during feature installation. This
+ * configuration may be used with OSGi Configuration Admin.
+ *             
+ * 
+ * <p>Java class for config complex type.
+ * 
+ * <p>The following schema fragment specifies the expected content contained within this class.
+ * 
+ * <pre>
+ * &lt;complexType name="config">
+ *   &lt;simpleContent>
+ *     &lt;extension base="&lt;http://www.w3.org/2001/XMLSchema>string">
+ *       &lt;attribute name="name" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
+ *     &lt;/extension>
+ *   &lt;/simpleContent>
+ * &lt;/complexType>
+ * </pre>
+ * 
+ * 
+ */
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "config", propOrder = {
+    "value"
+})
+public class Config {
+
+    @XmlValue
+    protected String value;
+    @XmlAttribute(required = true)
+    protected String name;
+
+    /**
+     * Gets the value of the value property.
+     * 
+     * @return
+     *     possible object is
+     *     {@link String }
+     *     
+     */
+    public String getValue() {
+        return value;
+    }
+
+    /**
+     * Sets the value of the value property.
+     * 
+     * @param value
+     *     allowed object is
+     *     {@link String }
+     *     
+     */
+    public void setValue(String value) {
+        this.value = value;
+    }
+
+    /**
+     * Gets the value of the name property.
+     * 
+     * @return
+     *     possible object is
+     *     {@link String }
+     *     
+     */
+    public String getName() {
+        return name;
+    }
+
+    /**
+     * Sets the value of the name property.
+     * 
+     * @param value
+     *     allowed object is
+     *     {@link String }
+     *     
+     */
+    public void setName(String value) {
+        this.name = value;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/src/main/java/org/apache/karaf/features/internal/model/ConfigFile.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/model/ConfigFile.java b/features/src/main/java/org/apache/karaf/features/internal/model/ConfigFile.java
new file mode 100644
index 0000000..e5d9d94
--- /dev/null
+++ b/features/src/main/java/org/apache/karaf/features/internal/model/ConfigFile.java
@@ -0,0 +1,136 @@
+/*
+ * 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.karaf.features.internal.model;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlType;
+import javax.xml.bind.annotation.XmlValue;
+import org.apache.karaf.features.ConfigFileInfo;
+
+
+/**
+ * 
+ * Additional configuration files which should be created during feature installation.
+ *             
+ * 
+ * <p>Java class for configFile complex type.
+ * 
+ * <p>The following schema fragment specifies the expected content contained within this class.
+ * 
+ * <pre>
+ * &lt;complexType name="configFile">
+ *   &lt;simpleContent>
+ *     &lt;extension base="&lt;http://www.w3.org/2001/XMLSchema>string">
+ *       &lt;attribute name="finalname" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
+ *       &lt;attribute name="override" type="{http://www.w3.org/2001/XMLSchema}boolean" />
+ *     &lt;/extension>
+ *   &lt;/simpleContent>
+ * &lt;/complexType>
+ * </pre>
+ * 
+ * 
+ */
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "configFile", propOrder = {
+    "value"
+})
+public class ConfigFile implements ConfigFileInfo {
+
+    @XmlValue
+    protected String value;
+    @XmlAttribute(required = true)
+    protected String finalname;
+    @XmlAttribute
+    protected Boolean override;
+
+    /**
+     * Gets the value of the value property.
+     * 
+     * @return
+     *     possible object is
+     *     {@link String }
+     *     
+     */
+    public String getLocation() {
+        return value;
+    }
+
+    /**
+     * Sets the value of the value property.
+     * 
+     * @param value
+     *     allowed object is
+     *     {@link String }
+     *     
+     */
+    public void setLocation(String value) {
+        this.value = value;
+    }
+
+    /**
+     * Gets the value of the finalname property.
+     * 
+     * @return
+     *     possible object is
+     *     {@link String }
+     *     
+     */
+    public String getFinalname() {
+        return finalname;
+    }
+
+    /**
+     * Sets the value of the finalname property.
+     * 
+     * @param value
+     *     allowed object is
+     *     {@link String }
+     *     
+     */
+    public void setFinalname(String value) {
+    	this.finalname = value;
+    }
+
+    /**
+     * Gets the value of the override property.
+     * 
+     * @return
+     *     possible object is
+     *     {@link Boolean }
+     *     
+     */
+    public boolean isOverride() {
+        return override == null? false: override;
+    }
+
+    /**
+     * Sets the value of the override property.
+     * 
+     * @param value
+     *     allowed object is
+     *     {@link Boolean }
+     *     
+     */
+    public void setOverride(Boolean value) {
+    	this.override = value;
+    }
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/src/main/java/org/apache/karaf/features/internal/model/Content.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/model/Content.java b/features/src/main/java/org/apache/karaf/features/internal/model/Content.java
new file mode 100644
index 0000000..756e4c1
--- /dev/null
+++ b/features/src/main/java/org/apache/karaf/features/internal/model/Content.java
@@ -0,0 +1,199 @@
+/*
+ * 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.karaf.features.internal.model;
+
+import java.io.IOException;
+import java.io.StringReader;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import javax.xml.bind.annotation.XmlTransient;
+import org.apache.karaf.features.BundleInfo;
+import org.apache.karaf.features.ConfigFileInfo;
+
+@XmlTransient
+public class Content {
+
+    protected List<Config> config;
+    protected List<ConfigFile> configfile;
+    protected List<Dependency> feature;
+    protected List<Bundle> bundle;
+
+    /**
+     * Gets the value of the config property.
+     * <p/>
+     * <p/>
+     * This accessor method returns a reference to the live list,
+     * not a snapshot. Therefore any modification you make to the
+     * returned list will be present inside the JAXB object.
+     * This is why there is not a <CODE>set</CODE> method for the config property.
+     * <p/>
+     * <p/>
+     * For example, to add a new item, do as follows:
+     * <pre>
+     *    getConfig().add(newItem);
+     * </pre>
+     * <p/>
+     * <p/>
+     * <p/>
+     * Objects of the following type(s) are allowed in the list
+     * {@link Config }
+     */
+    public List<Config> getConfig() {
+        if (config == null) {
+            config = new ArrayList<Config>();
+        }
+        return this.config;
+    }
+
+    /**
+     * Gets the value of the configfile property.
+     * <p/>
+     * <p/>
+     * This accessor method returns a reference to the live list,
+     * not a snapshot. Therefore any modification you make to the
+     * returned list will be present inside the JAXB object.
+     * This is why there is not a <CODE>set</CODE> method for the configfile property.
+     * <p/>
+     * <p/>
+     * For example, to add a new item, do as follows:
+     * <pre>
+     *    getConfigfile().add(newItem);
+     * </pre>
+     * <p/>
+     * <p/>
+     * <p/>
+     * Objects of the following type(s) are allowed in the list
+     * {@link ConfigFile }
+     */
+    public List<ConfigFile> getConfigfile() {
+        if (configfile == null) {
+            configfile = new ArrayList<ConfigFile>();
+        }
+        return this.configfile;
+    }
+
+    /**
+     * Gets the value of the feature property.
+     * <p/>
+     * <p/>
+     * This accessor method returns a reference to the live list,
+     * not a snapshot. Therefore any modification you make to the
+     * returned list will be present inside the JAXB object.
+     * This is why there is not a <CODE>set</CODE> method for the feature property.
+     * <p/>
+     * <p/>
+     * For example, to add a new item, do as follows:
+     * <pre>
+     *    getFeature().add(newItem);
+     * </pre>
+     * <p/>
+     * <p/>
+     * <p/>
+     * Objects of the following type(s) are allowed in the list
+     * {@link Dependency }
+     */
+    public List<Dependency> getFeature() {
+        if (feature == null) {
+            feature = new ArrayList<Dependency>();
+        }
+        return this.feature;
+    }
+
+    /**
+     * Gets the value of the bundle property.
+     * <p/>
+     * <p/>
+     * This accessor method returns a reference to the live list,
+     * not a snapshot. Therefore any modification you make to the
+     * returned list will be present inside the JAXB object.
+     * This is why there is not a <CODE>set</CODE> method for the bundle property.
+     * <p/>
+     * <p/>
+     * For example, to add a new item, do as follows:
+     * <pre>
+     *    getBundle().add(newItem);
+     * </pre>
+     * <p/>
+     * <p/>
+     * <p/>
+     * Objects of the following type(s) are allowed in the list
+     * {@link Bundle }
+     */
+    public List<Bundle> getBundle() {
+        if (bundle == null) {
+            bundle = new ArrayList<Bundle>();
+        }
+        return this.bundle;
+    }
+
+    public List<org.apache.karaf.features.Dependency> getDependencies() {
+        return Collections.<org.apache.karaf.features.Dependency>unmodifiableList(getFeature());
+    }
+
+    public List<BundleInfo> getBundles() {
+        return Collections.<BundleInfo>unmodifiableList(getBundle());
+    }
+
+    public Map<String, Map<String, String>> getConfigurations() {
+        Map<String, Map<String, String>> result = new HashMap<String, Map<String, String>>();
+        for (Config config : getConfig()) {
+            String name = config.getName();
+            StringReader propStream = new StringReader(config.getValue());
+            Properties props = new Properties();
+            try {
+                props.load(propStream);
+            } catch (IOException e) {
+                //ignore??
+            }
+            interpolation(props);
+            Map<String, String> propMap = new HashMap<String, String>();
+            for (Map.Entry<Object, Object> entry : props.entrySet()) {
+                propMap.put((String) entry.getKey(), (String) entry.getValue());
+            }
+            result.put(name, propMap);
+        }
+        return result;
+    }
+
+    public List<ConfigFileInfo> getConfigurationFiles() {
+        return Collections.<ConfigFileInfo>unmodifiableList(getConfigfile());
+    }
+
+    @SuppressWarnings("rawtypes")
+	protected void interpolation(Properties properties) {
+        for (Enumeration e = properties.propertyNames(); e.hasMoreElements(); ) {
+            String key = (String) e.nextElement();
+            String val = properties.getProperty(key);
+            Matcher matcher = Pattern.compile("\\$\\{([^}]+)\\}").matcher(val);
+            while (matcher.find()) {
+                String rep = System.getProperty(matcher.group(1));
+                if (rep != null) {
+                    val = val.replace(matcher.group(0), rep);
+                    matcher.reset(val);
+                }
+            }
+            properties.put(key, val);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/src/main/java/org/apache/karaf/features/internal/model/Dependency.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/model/Dependency.java b/features/src/main/java/org/apache/karaf/features/internal/model/Dependency.java
new file mode 100644
index 0000000..9c92a93
--- /dev/null
+++ b/features/src/main/java/org/apache/karaf/features/internal/model/Dependency.java
@@ -0,0 +1,121 @@
+/*
+ * 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.karaf.features.internal.model;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlType;
+import javax.xml.bind.annotation.XmlValue;
+
+
+/**
+ * 
+ * Dependency of feature.
+ *             
+ * 
+ * <p>Java class for dependency complex type.
+ * 
+ * <p>The following schema fragment specifies the expected content contained within this class.
+ * 
+ * <pre>
+ * &lt;complexType name="dependency">
+ *   &lt;simpleContent>
+ *     &lt;extension base="&lt;http://karaf.apache.org/xmlns/features/v1.0.0>featureName">
+ *       &lt;attribute name="version" type="{http://www.w3.org/2001/XMLSchema}string" default="0.0.0" />
+ *     &lt;/extension>
+ *   &lt;/simpleContent>
+ * &lt;/complexType>
+ * </pre>
+ * 
+ * 
+ */
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "dependency", propOrder = {
+    "value"
+})
+public class Dependency implements org.apache.karaf.features.Dependency {
+
+    @XmlValue
+    protected String value;
+    @XmlAttribute
+    protected String version;
+
+    /**
+     * 
+     * Feature name should be non empty string.
+     *             
+     * 
+     * @return
+     *     possible object is
+     *     {@link String }
+     *     
+     */
+    public String getName() {
+        return value;
+    }
+
+    /**
+     * Sets the value of the value property.
+     * 
+     * @param value
+     *     allowed object is
+     *     {@link String }
+     *     
+     */
+    public void setName(String value) {
+        this.value = value;
+    }
+
+    /**
+     * Gets the value of the version property.
+     * 
+     * @return
+     *     possible object is
+     *     {@link String }
+     *     
+     */
+    public String getVersion() {
+        if (version == null) {
+            return "0.0.0";
+        } else {
+            return version;
+        }
+    }
+
+    /**
+     * Sets the value of the version property.
+     * 
+     * @param value
+     *     allowed object is
+     *     {@link String }
+     *     
+     */
+    public void setVersion(String value) {
+        this.version = value;
+    }
+
+    public String toString() {
+    	String ret = getName() + Feature.SPLIT_FOR_NAME_AND_VERSION + getVersion();
+    	return ret;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/src/main/java/org/apache/karaf/features/internal/model/Feature.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/model/Feature.java b/features/src/main/java/org/apache/karaf/features/internal/model/Feature.java
new file mode 100644
index 0000000..46580da
--- /dev/null
+++ b/features/src/main/java/org/apache/karaf/features/internal/model/Feature.java
@@ -0,0 +1,374 @@
+/*
+ * 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.karaf.features.internal.model;
+
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.Properties;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlType;
+
+
+/**
+ * 
+ * Definition of the Feature.
+ *             
+ * 
+ * <p>Java class for feature complex type.
+ * 
+ * <p>The following schema fragment specifies the expected content contained within this class.
+ * 
+ * <pre>
+ * &lt;complexType name="feature">
+ *   &lt;complexContent>
+ *     &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       &lt;sequence>
+ *         &lt;element name="details" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/>
+ *         &lt;element name="config" type="{http://karaf.apache.org/xmlns/features/v1.0.0}config" maxOccurs="unbounded" minOccurs="0"/>
+ *         &lt;element name="configfile" type="{http://karaf.apache.org/xmlns/features/v1.0.0}configFile" maxOccurs="unbounded" minOccurs="0"/>
+ *         &lt;element name="feature" type="{http://karaf.apache.org/xmlns/features/v1.0.0}dependency" maxOccurs="unbounded" minOccurs="0"/>
+ *         &lt;element name="bundle" type="{http://karaf.apache.org/xmlns/features/v1.0.0}bundle" maxOccurs="unbounded" minOccurs="0"/>
+ *         &lt;element name="conditional" type="{http://karaf.apache.org/xmlns/features/v1.0.0}conditional" maxOccurs="unbounded" minOccurs="0"/>
+ *         &lt;element name="capability" type="{http://karaf.apache.org/xmlns/features/v1.0.0}capability" maxOccurs="unbounded" minOccurs="0"/>
+ *         &lt;element name="requirement" type="{http://karaf.apache.org/xmlns/features/v1.0.0}requirement" maxOccurs="unbounded" minOccurs="0"/>
+ *       &lt;/sequence>
+ *       &lt;attribute name="name" use="required" type="{http://karaf.apache.org/xmlns/features/v1.0.0}featureName" />
+ *       &lt;attribute name="version" type="{http://www.w3.org/2001/XMLSchema}string" default="0.0.0" />
+ *       &lt;attribute name="description" type="{http://www.w3.org/2001/XMLSchema}string" />
+ *       &lt;attribute name="resolver" type="{http://karaf.apache.org/xmlns/features/v1.0.0}resolver" />
+ *     &lt;/restriction>
+ *   &lt;/complexContent>
+ * &lt;/complexType>
+ * </pre>
+ * 
+ * 
+ */
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "feature", propOrder = {
+    "details",
+    "config",
+    "configfile",
+    "feature",
+    "bundle",
+    "conditional",
+    "capability",
+    "requirement"
+})
+public class Feature extends Content implements org.apache.karaf.features.Feature {
+    public static String SPLIT_FOR_NAME_AND_VERSION = "/";
+    public static String DEFAULT_VERSION = "0.0.0";
+
+
+    protected String details;
+    @XmlAttribute(required = true)
+    protected String name;
+    @XmlAttribute
+    protected String version;
+    @XmlAttribute
+    protected String description;
+    @XmlAttribute
+    protected String resolver;
+    @XmlAttribute
+    protected String install;
+    @XmlAttribute(name = "start-level")
+    protected Integer startLevel;
+    @XmlAttribute
+    protected String region;
+    protected List<Conditional> conditional;
+    protected List<Capability> capability;
+    protected List<Requirement> requirement;
+
+    public Feature() {
+    }
+
+    public Feature(String name) {
+        this.name = name;
+    }
+
+    public Feature(String name, String version) {
+        this.name = name;
+        this.version = version;
+    }
+
+
+    public static org.apache.karaf.features.Feature valueOf(String str) {
+    	if (str.contains(SPLIT_FOR_NAME_AND_VERSION)) {
+    		String strName = str.substring(0, str.indexOf(SPLIT_FOR_NAME_AND_VERSION));
+        	String strVersion = str.substring(str.indexOf(SPLIT_FOR_NAME_AND_VERSION)
+        			+ SPLIT_FOR_NAME_AND_VERSION.length(), str.length());
+        	return new Feature(strName, strVersion);
+    	} else {
+    		return new Feature(str);
+    	}
+
+
+    }
+
+
+    public String getId() {
+        return getName() + SPLIT_FOR_NAME_AND_VERSION + getVersion();
+    }
+
+    /**
+     * Gets the value of the name property.
+     * 
+     * @return
+     *     possible object is
+     *     {@link String }
+     *     
+     */
+    public String getName() {
+        return name;
+    }
+
+    /**
+     * Sets the value of the name property.
+     * 
+     * @param value
+     *     allowed object is
+     *     {@link String }
+     *     
+     */
+    public void setName(String value) {
+        this.name = value;
+    }
+
+    /**
+     * Gets the value of the version property.
+     * 
+     * @return
+     *     possible object is
+     *     {@link String }
+     *     
+     */
+    public String getVersion() {
+        if (version == null) {
+            return DEFAULT_VERSION;
+        } else {
+            return version;
+        }
+    }
+
+    /**
+     * Sets the value of the version property.
+     * 
+     * @param value
+     *     allowed object is
+     *     {@link String }
+     *     
+     */
+    public void setVersion(String value) {
+        this.version = value;
+    }
+
+    /**
+     * Since version has a default value ("0.0.0"), returns
+     * whether or not the version has been set.
+     */
+    public boolean hasVersion() {
+        return this.version != null;
+    }
+
+    /**
+     * Gets the value of the description property.
+     * 
+     * @return
+     *     possible object is
+     *     {@link String }
+     *     
+     */
+    public String getDescription() {
+        return description;
+    }
+
+    /**
+     * Sets the value of the description property.
+     * 
+     * @param value
+     *     allowed object is
+     *     {@link String }
+     *     
+     */
+    public void setDescription(String value) {
+        this.description = value;
+    }
+
+    public String getDetails() {
+        return details;
+    }
+
+    public void setDetails(String details) {
+        this.details = details;
+    }
+
+    /**
+     * Gets the value of the resolver property.
+     * 
+     * @return
+     *     possible object is
+     *     {@link String }
+     *     
+     */
+    public String getResolver() {
+        return resolver;
+    }
+
+    public String getInstall() {
+        return install;
+    }
+
+    public void setInstall(String install) {
+        this.install = install;
+    }
+
+    /**
+     * Sets the value of the resolver property.
+     * 
+     * @param value
+     *     allowed object is
+     *     {@link String }
+     *     
+     */
+    public void setResolver(String value) {
+        this.resolver = value;
+    }
+    
+    /**
+     * Gets the value of the startLevel property.
+     * 
+     * @return
+     *     possible object is
+     *     {@link Integer }
+     *     
+     */
+    public int getStartLevel() {
+        return startLevel == null? 0: startLevel;
+    }
+
+    /**
+     * Sets the value of the startLevel property.
+     * 
+     * @param value
+     *     allowed object is
+     *     {@link Integer }
+     *     
+     */
+    public void setStartLevel(Integer value) {
+        this.startLevel = value;
+    }
+
+
+    public String getRegion() {
+        return region;
+    }
+
+    public void setRegion(String region) {
+        this.region = region;
+    }
+
+    /**
+     * Gets the value of the conditional property.
+     * <p/>
+     * <p/>
+     * This accessor method returns a reference to the live list,
+     * not a snapshot. Therefore any modification you make to the
+     * returned list will be present inside the JAXB object.
+     * This is why there is not a <CODE>set</CODE> method for the feature property.
+     * <p/>
+     * <p/>
+     * For example, to add a new item, do as follows:
+     * <pre>
+     *    getConditionals().add(newItem);
+     * </pre>
+     * <p/>
+     * <p/>
+     * <p/>
+     * Objects of the following type(s) are allowed in the list
+     * {@link Conditional }
+     */
+    public List<Conditional> getConditional() {
+        if (conditional == null) {
+            conditional = new ArrayList<Conditional>();
+        }
+        return this.conditional;
+    }
+
+    public List<Capability> getCapabilities() {
+        if (capability == null) {
+            capability = new ArrayList<Capability>();
+        }
+        return this.capability;
+    }
+
+    public List<Requirement> getRequirements() {
+        if (requirement == null) {
+            requirement = new ArrayList<Requirement>();
+        }
+        return this.requirement;
+    }
+
+    public String toString() {
+    	return getId();
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        Feature feature = (Feature) o;
+
+        if (name != null ? !name.equals(feature.name) : feature.name != null) return false;
+        if (version != null ? !version.equals(feature.version) : feature.version != null) return false;
+
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        int result = name != null ? name.hashCode() : 0;
+        result = 31 * result + (version != null ? version.hashCode() : 0);
+        return result;
+    }
+
+    @SuppressWarnings("rawtypes")
+	protected void interpolation(Properties properties) {
+        for (Enumeration e = properties.propertyNames(); e.hasMoreElements();) {
+            String key = (String) e.nextElement();
+            String val = properties.getProperty(key);
+            Matcher matcher = Pattern.compile("\\$\\{([^}]+)\\}").matcher(val);
+            while (matcher.find()) {
+                String rep = System.getProperty(matcher.group(1));
+                if (rep != null) {
+                    val = val.replace(matcher.group(0), rep);
+                    matcher.reset(val);
+                }
+            }
+            properties.put(key, val);
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/src/main/java/org/apache/karaf/features/internal/model/Features.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/model/Features.java b/features/src/main/java/org/apache/karaf/features/internal/model/Features.java
new file mode 100644
index 0000000..e116f31
--- /dev/null
+++ b/features/src/main/java/org/apache/karaf/features/internal/model/Features.java
@@ -0,0 +1,155 @@
+/*
+ * 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.karaf.features.internal.model;
+
+import java.util.ArrayList;
+import java.util.List;
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlSchemaType;
+import javax.xml.bind.annotation.XmlType;
+
+
+/**
+ * 
+ * Root element of Feature definition. It contains optional attribute which allow
+ * name of repository. This name will be used in shell to display source repository
+ * of given feature.
+ *             
+ * 
+ * <p>Java class for featuresRoot complex type.
+ * 
+ * <p>The following schema fragment specifies the expected content contained within this class.
+ * 
+ * <pre>
+ * &lt;complexType name="features">
+ *   &lt;complexContent>
+ *     &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       &lt;sequence>
+ *         &lt;element name="repository" type="{http://www.w3.org/2001/XMLSchema}anyURI" maxOccurs="unbounded" minOccurs="0"/>
+ *         &lt;element name="feature" type="{http://karaf.apache.org/xmlns/features/v1.0.0}feature" maxOccurs="unbounded" minOccurs="0"/>
+ *       &lt;/sequence>
+ *       &lt;attribute name="name" type="{http://www.w3.org/2001/XMLSchema}string" />
+ *     &lt;/restriction>
+ *   &lt;/complexContent>
+ * &lt;/complexType>
+ * </pre>
+ * 
+ * 
+ */
+@XmlRootElement(name = "features")
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "features", propOrder = {
+    "repository",
+    "feature"
+})
+public class Features {
+
+    @XmlSchemaType(name = "anyURI")
+    protected List<String> repository;
+    protected List<Feature> feature;
+    @XmlAttribute
+    protected String name;
+
+    /**
+     * Gets the value of the repository property.
+     * 
+     * <p>
+     * This accessor method returns a reference to the live list,
+     * not a snapshot. Therefore any modification you make to the
+     * returned list will be present inside the JAXB object.
+     * This is why there is not a <CODE>set</CODE> method for the repository property.
+     * 
+     * <p>
+     * For example, to add a new item, do as follows:
+     * <pre>
+     *    getRepository().add(newItem);
+     * </pre>
+     * 
+     * 
+     * <p>
+     * Objects of the following type(s) are allowed in the list
+     * {@link String }
+     * 
+     * 
+     */
+    public List<String> getRepository() {
+        if (repository == null) {
+            repository = new ArrayList<String>();
+        }
+        return this.repository;
+    }
+
+    /**
+     * Gets the value of the feature property.
+     * 
+     * <p>
+     * This accessor method returns a reference to the live list,
+     * not a snapshot. Therefore any modification you make to the
+     * returned list will be present inside the JAXB object.
+     * This is why there is not a <CODE>set</CODE> method for the feature property.
+     * 
+     * <p>
+     * For example, to add a new item, do as follows:
+     * <pre>
+     *    getFeature().add(newItem);
+     * </pre>
+     * 
+     * 
+     * <p>
+     * Objects of the following type(s) are allowed in the list
+     * {@link Feature }
+     * 
+     * 
+     */
+    public List<Feature> getFeature() {
+        if (feature == null) {
+            feature = new ArrayList<Feature>();
+        }
+        return this.feature;
+    }
+
+    /**
+     * Gets the value of the name property.
+     * 
+     * @return
+     *     possible object is
+     *     {@link String }
+     *     
+     */
+    public String getName() {
+        return name;
+    }
+
+    /**
+     * Sets the value of the name property.
+     * 
+     * @param value
+     *     allowed object is
+     *     {@link String }
+     *     
+     */
+    public void setName(String value) {
+        this.name = value;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/src/main/java/org/apache/karaf/features/internal/model/JaxbUtil.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/model/JaxbUtil.java b/features/src/main/java/org/apache/karaf/features/internal/model/JaxbUtil.java
new file mode 100644
index 0000000..39c057a
--- /dev/null
+++ b/features/src/main/java/org/apache/karaf/features/internal/model/JaxbUtil.java
@@ -0,0 +1,149 @@
+/*
+ * 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.karaf.features.internal.model;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.Writer;
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Marshaller;
+import javax.xml.bind.Unmarshaller;
+import javax.xml.bind.ValidationEvent;
+import javax.xml.bind.ValidationEventHandler;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+import javax.xml.stream.XMLInputFactory;
+import javax.xml.transform.sax.SAXSource;
+
+import org.apache.karaf.features.FeaturesNamespaces;
+import org.xml.sax.Attributes;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.XMLFilter;
+import org.xml.sax.XMLReader;
+import org.xml.sax.helpers.XMLFilterImpl;
+
+public class JaxbUtil {
+
+    public static final XMLInputFactory XMLINPUT_FACTORY = XMLInputFactory.newInstance();
+    private static final JAXBContext FEATURES_CONTEXT;
+    static {
+        try {
+            FEATURES_CONTEXT = JAXBContext.newInstance(Features.class);
+        } catch (JAXBException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    public static void marshal(Features features, OutputStream out) throws JAXBException {
+        Marshaller marshaller = FEATURES_CONTEXT.createMarshaller();
+
+        marshaller.setProperty("jaxb.formatted.output", true);
+
+        marshaller.marshal(features, out);
+    }
+
+    public static void marshal(Features features, Writer out) throws JAXBException {
+        Marshaller marshaller = FEATURES_CONTEXT.createMarshaller();
+
+        marshaller.setProperty("jaxb.formatted.output", true);
+
+        marshaller.marshal(features, out);
+    }
+
+
+    /**
+     * Read in a Features from the input stream.
+     *
+     * @param in       input stream to read
+     * @param validate whether to validate the input.
+     * @return a Features read from the input stream
+     * @throws ParserConfigurationException is the SAX parser can not be configured
+     * @throws SAXException                 if there is an xml problem
+     * @throws JAXBException                if the xml cannot be marshalled into a T.
+     */
+    public static Features unmarshal(InputStream in, boolean validate) {
+        InputSource inputSource = new InputSource(in);
+
+        SAXParserFactory factory = SAXParserFactory.newInstance();
+        factory.setNamespaceAware(true);
+        factory.setValidating(validate);
+        SAXParser parser;
+        try {
+            parser = factory.newSAXParser();
+        
+
+        Unmarshaller unmarshaller = FEATURES_CONTEXT.createUnmarshaller();
+        unmarshaller.setEventHandler(new ValidationEventHandler() {
+            public boolean handleEvent(ValidationEvent validationEvent) {
+                System.out.println(validationEvent);
+                return false;
+            }
+        });
+
+        XMLFilter xmlFilter = new NoSourceAndNamespaceFilter(parser.getXMLReader());
+        xmlFilter.setContentHandler(unmarshaller.getUnmarshallerHandler());
+
+        SAXSource source = new SAXSource(xmlFilter, inputSource);
+
+        return (Features)unmarshaller.unmarshal(source);
+        
+        } catch (ParserConfigurationException e) {
+            throw new RuntimeException(e);
+        } catch (JAXBException e) {
+            throw new RuntimeException(e);
+        } catch (SAXException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * Provides an empty inputsource for the entity resolver.
+     * Converts all elements to the features namespace to make old feature files
+     * compatible to the new format
+     */
+    public static class NoSourceAndNamespaceFilter extends XMLFilterImpl {        
+        private static final InputSource EMPTY_INPUT_SOURCE = new InputSource(new ByteArrayInputStream(new byte[0]));
+
+        public NoSourceAndNamespaceFilter(XMLReader xmlReader) {
+            super(xmlReader);
+        }
+
+        @Override
+        public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException {
+            return EMPTY_INPUT_SOURCE;
+        }
+
+        @Override
+        public void startElement(String uri, String localName, String qName, Attributes atts) throws SAXException {
+            super.startElement(FeaturesNamespaces.URI_CURRENT, localName, qName, atts);
+        }
+
+        @Override
+        public void endElement(String uri, String localName, String qName) throws SAXException {
+            super.endElement(FeaturesNamespaces.URI_CURRENT, localName, qName);
+        }
+    }
+
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/src/main/java/org/apache/karaf/features/internal/model/ObjectFactory.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/model/ObjectFactory.java b/features/src/main/java/org/apache/karaf/features/internal/model/ObjectFactory.java
new file mode 100644
index 0000000..96fbb0f
--- /dev/null
+++ b/features/src/main/java/org/apache/karaf/features/internal/model/ObjectFactory.java
@@ -0,0 +1,111 @@
+/*
+ * 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.karaf.features.internal.model;
+
+import javax.xml.bind.JAXBElement;
+import javax.xml.bind.annotation.XmlElementDecl;
+import javax.xml.bind.annotation.XmlRegistry;
+import javax.xml.namespace.QName;
+
+
+/**
+ * This object contains factory methods for each 
+ * Java content interface and Java element interface 
+ * generated in the org.apache.karaf.features.wrapper package.
+ * <p>An ObjectFactory allows you to programatically 
+ * construct new instances of the Java representation 
+ * for XML content. The Java representation of XML 
+ * content can consist of schema derived interfaces 
+ * and classes representing the binding of schema 
+ * type definitions, element declarations and model 
+ * groups.  Factory methods for each of these are 
+ * provided in this class.
+ * 
+ */
+@XmlRegistry
+public class ObjectFactory {
+
+    private final static QName _Features_QNAME = new QName("http://karaf.apache.org/xmlns/features/v1.0.0", "features");
+
+    /**
+     * Create a new ObjectFactory that can be used to create new instances of schema derived classes for package: org.apache.karaf.features.wrapper
+     * 
+     */
+    public ObjectFactory() {
+    }
+
+    /**
+     * Create an instance of {@link ConfigFile }
+     * 
+     */
+    public ConfigFile createConfigFile() {
+        return new ConfigFile();
+    }
+
+    /**
+     * Create an instance of {@link Dependency }
+     * 
+     */
+    public Dependency createDependency() {
+        return new Dependency();
+    }
+
+    /**
+     * Create an instance of {@link Bundle }
+     * 
+     */
+    public Bundle createBundle() {
+        return new Bundle();
+    }
+
+    /**
+     * Create an instance of {@link Features }
+     * 
+     */
+    public Features createFeaturesRoot() {
+        return new Features();
+    }
+
+    /**
+     * Create an instance of {@link Config }
+     * 
+     */
+    public Config createConfig() {
+        return new Config();
+    }
+
+    /**
+     * Create an instance of {@link Feature }
+     * 
+     */
+    public Feature createFeature() {
+        return new Feature();
+    }
+
+    /**
+     * Create an instance of {@link JAXBElement }{@code <}{@link Features }{@code >}}
+     * 
+     */
+    @XmlElementDecl(namespace = "http://karaf.apache.org/xmlns/features/v1.0.0", name = "features")
+    public JAXBElement<Features> createFeatures(Features value) {
+        return new JAXBElement<Features>(_Features_QNAME, Features.class, null, value);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/src/main/java/org/apache/karaf/features/internal/model/Requirement.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/model/Requirement.java b/features/src/main/java/org/apache/karaf/features/internal/model/Requirement.java
new file mode 100644
index 0000000..f7b5775
--- /dev/null
+++ b/features/src/main/java/org/apache/karaf/features/internal/model/Requirement.java
@@ -0,0 +1,87 @@
+/*
+ * 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.karaf.features.internal.model;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlType;
+import javax.xml.bind.annotation.XmlValue;
+
+
+/**
+ * 
+ * Additional requirement for a feature.
+ *             
+ * 
+ * <p>Java class for bundle complex type.
+ * 
+ * <p>The following schema fragment specifies the expected content contained within this class.
+ * 
+ * <pre>
+ * &lt;complexType name="capability">
+ *   &lt;simpleContent>
+ *     &lt;extension base="&lt;http://www.w3.org/2001/XMLSchema>string">
+ *     &lt;/extension>
+ *   &lt;/simpleContent>
+ * &lt;/complexType>
+ * </pre>
+ * 
+ * 
+ */
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "requirement", propOrder = {
+    "value"
+})
+public class Requirement implements org.apache.karaf.features.Requirement {
+
+    @XmlValue
+    protected String value;
+
+
+    public Requirement() {
+    }
+
+    public Requirement(String value) {
+        this.value = value;
+    }
+
+    public String getValue() {
+        return value;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        Requirement bundle = (Requirement) o;
+
+        if (value != null ? !value.equals(bundle.value) : bundle.value != null) return false;
+
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        int result = value != null ? value.hashCode() : 0;
+        return result;
+    }
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/src/main/java/org/apache/karaf/features/internal/model/package-info.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/model/package-info.java b/features/src/main/java/org/apache/karaf/features/internal/model/package-info.java
new file mode 100644
index 0000000..c86a58c
--- /dev/null
+++ b/features/src/main/java/org/apache/karaf/features/internal/model/package-info.java
@@ -0,0 +1,21 @@
+/*
+ * 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.
+ */
+
+@javax.xml.bind.annotation.XmlSchema(namespace = org.apache.karaf.features.FeaturesNamespaces.URI_CURRENT, elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED)
+package org.apache.karaf.features.internal.model;

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/src/main/java/org/apache/karaf/features/internal/osgi/Activator.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/osgi/Activator.java b/features/src/main/java/org/apache/karaf/features/internal/osgi/Activator.java
new file mode 100644
index 0000000..be0da05
--- /dev/null
+++ b/features/src/main/java/org/apache/karaf/features/internal/osgi/Activator.java
@@ -0,0 +1,208 @@
+/*
+ * 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.karaf.features.internal.osgi;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Dictionary;
+import java.util.Hashtable;
+import java.util.Properties;
+
+import org.apache.karaf.features.FeaturesListener;
+import org.apache.karaf.features.FeaturesService;
+import org.apache.karaf.features.internal.service.EventAdminListener;
+import org.apache.karaf.features.internal.service.FeatureConfigInstaller;
+import org.apache.karaf.features.internal.service.FeatureFinder;
+import org.apache.karaf.features.internal.service.BootFeaturesInstaller;
+import org.apache.karaf.features.internal.service.FeaturesServiceImpl;
+import org.apache.karaf.features.internal.service.StateStorage;
+import org.apache.karaf.features.internal.management.FeaturesServiceMBeanImpl;
+import org.apache.karaf.features.RegionsPersistence;
+import org.apache.karaf.util.tracker.BaseActivator;
+import org.apache.karaf.util.tracker.SingleServiceTracker;
+import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.cm.ConfigurationAdmin;
+import org.osgi.service.cm.ManagedService;
+import org.osgi.service.url.URLStreamHandlerService;
+import org.osgi.util.tracker.ServiceTracker;
+import org.osgi.util.tracker.ServiceTrackerCustomizer;
+
+public class Activator extends BaseActivator {
+
+    public static final String FEATURES_REPOS_PID = "org.apache.karaf.features.repos";
+    public static final String FEATURES_SERVICE_CONFIG_FILE = "org.apache.karaf.features.cfg";
+
+    private ServiceTracker<FeaturesListener, FeaturesListener> featuresListenerTracker;
+    private FeaturesServiceImpl featuresService;
+    private SingleServiceTracker<RegionsPersistence> regionsTracker;
+
+    public Activator() {
+        // Special case here, as we don't want the activator to wait for current job to finish,
+        // else it would forbid the features service to refresh itself
+        setSchedulerStopTimeout(0);
+    }
+
+    @Override
+    protected void doOpen() throws Exception {
+        trackService(URLStreamHandlerService.class, "(url.handler.protocol=mvn)");
+        trackService(ConfigurationAdmin.class);
+
+        Properties configuration = new Properties();
+        File configFile = new File(System.getProperty("karaf.etc"), FEATURES_SERVICE_CONFIG_FILE);
+        if (configFile.isFile() && configFile.canRead()) {
+            try {
+                configuration.load(new FileReader(configFile));
+            } catch (IOException e) {
+                logger.warn("Error reading configuration file " + configFile.toString(), e);
+            }
+        }
+        updated((Dictionary) configuration);
+    }
+
+    protected void doStart() throws Exception {
+        ConfigurationAdmin configurationAdmin = getTrackedService(ConfigurationAdmin.class);
+        URLStreamHandlerService mvnUrlHandler = getTrackedService(URLStreamHandlerService.class);
+
+        if (configurationAdmin == null || mvnUrlHandler == null) {
+            return;
+        }
+
+        FeatureFinder featureFinder = new FeatureFinder();
+        Hashtable<String, Object> props = new Hashtable<String, Object>();
+        props.put(Constants.SERVICE_PID, FEATURES_REPOS_PID);
+        register(ManagedService.class, featureFinder, props);
+
+        // TODO: region support
+//        final BundleManager bundleManager = new BundleManager(bundleContext);
+//        regionsTracker = new SingleServiceTracker<RegionsPersistence>(bundleContext, RegionsPersistence.class,
+//                new SingleServiceTracker.SingleServiceListener() {
+//                    @Override
+//                    public void serviceFound() {
+//                        bundleManager.setRegionsPersistence(regionsTracker.getService());
+//                    }
+//                    @Override
+//                    public void serviceLost() {
+//                        serviceFound();
+//                    }
+//                    @Override
+//                    public void serviceReplaced() {
+//                        serviceFound();
+//                    }
+//                });
+//        regionsTracker.open();
+
+
+        FeatureConfigInstaller configInstaller = new FeatureConfigInstaller(configurationAdmin);
+        // TODO: honor respectStartLvlDuringFeatureStartup and respectStartLvlDuringFeatureUninstall
+//        boolean respectStartLvlDuringFeatureStartup = getBoolean("respectStartLvlDuringFeatureStartup", true);
+//        boolean respectStartLvlDuringFeatureUninstall = getBoolean("respectStartLvlDuringFeatureUninstall", true);
+        String overrides = getString("overrides", new File(System.getProperty("karaf.etc"), "overrides.properties").toURI().toString());
+        String featureResolutionRange = getString("featureResolutionRange", FeaturesServiceImpl.DEFAULT_FEATURE_RESOLUTION_RANGE);
+        String bundleUpdateRange = getString("bundleUpdateRange", FeaturesServiceImpl.DEFAULT_BUNDLE_UPDATE_RANGE);
+        String updateSnapshots = getString("updateSnapshots", FeaturesServiceImpl.DEFAULT_UPDATE_SNAPSHOTS);
+        StateStorage stateStorage = new StateStorage() {
+            @Override
+            protected InputStream getInputStream() throws IOException {
+                File file = bundleContext.getDataFile("FeaturesServiceState.properties");
+                if (file.exists()) {
+                    return new FileInputStream(file);
+                } else {
+                    return null;
+                }
+            }
+
+            @Override
+            protected OutputStream getOutputStream() throws IOException {
+                File file = bundleContext.getDataFile("FeaturesServiceState.properties");
+                return new FileOutputStream(file);
+            }
+        };
+        EventAdminListener eventAdminListener;
+        try {
+            eventAdminListener = new EventAdminListener(bundleContext);
+        } catch (Throwable t) {
+            eventAdminListener = null;
+        }
+        featuresService = new FeaturesServiceImpl(
+                                bundleContext.getBundle(),
+                                bundleContext.getBundle(0).getBundleContext(),
+                                stateStorage,
+                                featureFinder,
+                                eventAdminListener,
+                                configInstaller,
+                                overrides,
+                                featureResolutionRange,
+                                bundleUpdateRange,
+                                updateSnapshots);
+        register(FeaturesService.class, featuresService);
+
+        featuresListenerTracker = new ServiceTracker<FeaturesListener, FeaturesListener>(
+                bundleContext, FeaturesListener.class, new ServiceTrackerCustomizer<FeaturesListener, FeaturesListener>() {
+            @Override
+            public FeaturesListener addingService(ServiceReference<FeaturesListener> reference) {
+                FeaturesListener service = bundleContext.getService(reference);
+                featuresService.registerListener(service);
+                return service;
+            }
+            @Override
+            public void modifiedService(ServiceReference<FeaturesListener> reference, FeaturesListener service) {
+            }
+            @Override
+            public void removedService(ServiceReference<FeaturesListener> reference, FeaturesListener service) {
+                featuresService.unregisterListener(service);
+                bundleContext.ungetService(reference);
+            }
+        }
+        );
+        featuresListenerTracker.open();
+
+        String featuresRepositories = getString("featuresRepositories", "");
+        String featuresBoot = getString("featuresBoot", "");
+        boolean featuresBootAsynchronous = getBoolean("featuresBootAsynchronous", false);
+        BootFeaturesInstaller bootFeaturesInstaller = new BootFeaturesInstaller(
+                bundleContext, featuresService,
+                featuresRepositories, featuresBoot, featuresBootAsynchronous);
+        bootFeaturesInstaller.start();
+
+        FeaturesServiceMBeanImpl featuresServiceMBean = new FeaturesServiceMBeanImpl();
+        featuresServiceMBean.setBundleContext(bundleContext);
+        featuresServiceMBean.setFeaturesService(featuresService);
+        registerMBean(featuresServiceMBean, "type=feature");
+    }
+
+    protected void doStop() {
+        if (regionsTracker != null) {
+            regionsTracker.close();
+            regionsTracker = null;
+        }
+        if (featuresListenerTracker != null) {
+            featuresListenerTracker.close();
+            featuresListenerTracker = null;
+        }
+        super.doStop();
+        if (featuresService != null) {
+            featuresService = null;
+        }
+    }
+
+}


[56/59] [abbrv] git commit: [KARAF-2852] Merge region/core and region/command

Posted by gn...@apache.org.
[KARAF-2852] Merge region/core and region/command


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

Branch: refs/heads/master
Commit: 1bcdb173169e899deebd91654eb1a14b24a6f584
Parents: 2b7e96d
Author: Guillaume Nodet <gn...@gmail.com>
Authored: Thu Apr 10 10:16:41 2014 +0200
Committer: Guillaume Nodet <gn...@gmail.com>
Committed: Thu Apr 10 16:03:02 2014 +0200

----------------------------------------------------------------------
 .../standard/src/main/feature/feature.xml       |   2 +-
 region/NOTICE                                   |  71 ++
 region/command/NOTICE                           |  71 --
 region/command/pom.xml                          | 100 ---
 .../karaf/region/commands/AddBundleCommand.java |  52 --
 .../karaf/region/commands/AddFilterCommand.java | 169 -----
 .../karaf/region/commands/AddRegionCommand.java |  38 --
 .../karaf/region/commands/InfoCommand.java      | 117 ----
 .../region/commands/RegionCommandSupport.java   |  79 ---
 .../karaf/region/commands/util/FileUtil.java    | 177 -----
 .../src/main/resources/OSGI-INF/bundle.info     |  18 -
 region/core/NOTICE                              |  71 --
 region/core/pom.xml                             | 122 ----
 .../region/persist/internal/Activator.java      |  91 ---
 .../persist/internal/RegionsBundleTracker.java  |  77 ---
 .../internal/RegionsPersistenceImpl.java        | 203 ------
 .../internal/model/FilterAttributeType.java     |  94 ---
 .../internal/model/FilterBundleType.java        | 156 -----
 .../internal/model/FilterNamespaceType.java     | 102 ---
 .../internal/model/FilterPackageType.java       | 129 ----
 .../persist/internal/model/FilterType.java      | 195 ------
 .../persist/internal/model/ObjectFactory.java   | 116 ----
 .../internal/model/RegionBundleType.java        |  94 ---
 .../persist/internal/model/RegionType.java      | 106 ---
 .../persist/internal/model/RegionsType.java     | 112 ----
 .../persist/internal/model/package-info.java    |   9 -
 .../internal/util/ManifestHeaderProcessor.java  | 661 -------------------
 .../internal/util/ManifestHeaderUtils.java      |  85 ---
 .../persist/internal/util/VersionRange.java     | 456 -------------
 .../org/apache/karaf/region/persist/region.xsd  | 109 ---
 region/pom.xml                                  | 190 +++---
 .../karaf/region/commands/AddBundleCommand.java |  52 ++
 .../karaf/region/commands/AddFilterCommand.java | 169 +++++
 .../karaf/region/commands/AddRegionCommand.java |  38 ++
 .../karaf/region/commands/InfoCommand.java      | 117 ++++
 .../region/commands/RegionCommandSupport.java   |  79 +++
 .../karaf/region/commands/util/FileUtil.java    | 177 +++++
 .../region/persist/internal/Activator.java      |  91 +++
 .../persist/internal/RegionsBundleTracker.java  |  77 +++
 .../internal/RegionsPersistenceImpl.java        | 203 ++++++
 .../internal/model/FilterAttributeType.java     |  94 +++
 .../internal/model/FilterBundleType.java        | 156 +++++
 .../internal/model/FilterNamespaceType.java     | 102 +++
 .../internal/model/FilterPackageType.java       | 129 ++++
 .../persist/internal/model/FilterType.java      | 195 ++++++
 .../persist/internal/model/ObjectFactory.java   | 116 ++++
 .../internal/model/RegionBundleType.java        |  94 +++
 .../persist/internal/model/RegionType.java      | 106 +++
 .../persist/internal/model/RegionsType.java     | 112 ++++
 .../persist/internal/model/package-info.java    |   9 +
 .../internal/util/ManifestHeaderProcessor.java  | 661 +++++++++++++++++++
 .../internal/util/ManifestHeaderUtils.java      |  85 +++
 .../persist/internal/util/VersionRange.java     | 456 +++++++++++++
 .../org/apache/karaf/region/persist/region.xsd  | 109 +++
 54 files changed, 3603 insertions(+), 3896 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/karaf/blob/1bcdb173/assemblies/features/standard/src/main/feature/feature.xml
----------------------------------------------------------------------
diff --git a/assemblies/features/standard/src/main/feature/feature.xml b/assemblies/features/standard/src/main/feature/feature.xml
index fb3dd93..4d06455 100644
--- a/assemblies/features/standard/src/main/feature/feature.xml
+++ b/assemblies/features/standard/src/main/feature/feature.xml
@@ -146,9 +146,9 @@
     </feature>
 
     <feature name="region" description="Provide Region Support" version="${project.version}">
+        <bundle dependency="true" start-level="20">mvn:org.apache.aries/org.apache.aries.util/${aries.util.version}</bundle>
         <bundle start-level="30">mvn:org.eclipse.equinox/region/${equinox.region.version}</bundle>
         <bundle start-level="30">mvn:org.apache.karaf.region/org.apache.karaf.region.core/${project.version}</bundle>
-        <bundle start-level="30">mvn:org.apache.karaf.region/org.apache.karaf.region.command/${project.version}</bundle>
     </feature>
 
     <feature name="package" version="${project.version}" resolver="(obr)" description="Package commands and mbeans">

http://git-wip-us.apache.org/repos/asf/karaf/blob/1bcdb173/region/NOTICE
----------------------------------------------------------------------
diff --git a/region/NOTICE b/region/NOTICE
new file mode 100644
index 0000000..b70f1f9
--- /dev/null
+++ b/region/NOTICE
@@ -0,0 +1,71 @@
+Apache Karaf
+Copyright 2010-2014 The Apache Software Foundation
+
+
+I. Included Software
+
+This product includes software developed at
+The Apache Software Foundation (http://www.apache.org/).
+Licensed under the Apache License 2.0.
+
+This product uses software developed at
+The OSGi Alliance (http://www.osgi.org/).
+Copyright (c) OSGi Alliance (2000, 2010).
+Licensed under the Apache License 2.0.
+
+This product includes software developed at
+OW2 (http://www.ow2.org/).
+Licensed under the BSD License.
+
+This product includes software developed at
+OPS4J (http://www.ops4j.org/).
+Licensed under the Apache License 2.0.
+
+This product includes software developed at
+Eclipse Foundation (http://www.eclipse.org/).
+Licensed under the EPL.
+
+This product includes software written by
+Antony Lesuisse.
+Licensed under Public Domain.
+
+
+II. Used Software
+
+This product uses software developed at
+FUSE Source (http://www.fusesource.org/).
+Licensed under the Apache License 2.0.
+
+This product uses software developed at
+AOP Alliance (http://aopalliance.sourceforge.net/).
+Licensed under the Public Domain.
+
+This product uses software developed at
+Tanuki Software (http://www.tanukisoftware.com/).
+Licensed under the Apache License 2.0.
+
+This product uses software developed at
+Jasypt (http://jasypt.sourceforge.net/).
+Licensed under the Apache License 2.0.
+
+This product uses software developed at
+JLine (http://jline.sourceforge.net).
+Licensed under the BSD License.
+
+This product uses software developed at
+SLF4J (http://www.slf4j.org/).
+Licensed under the MIT License.
+
+This product uses software developed at
+SpringSource (http://www.springsource.org/).
+Licensed under the Apache License 2.0.
+
+This product includes software from http://www.json.org.
+Copyright (c) 2002 JSON.org
+
+
+III. License Summary
+- Apache License 2.0
+- BSD License
+- EPL License
+- MIT License

http://git-wip-us.apache.org/repos/asf/karaf/blob/1bcdb173/region/command/NOTICE
----------------------------------------------------------------------
diff --git a/region/command/NOTICE b/region/command/NOTICE
deleted file mode 100644
index b70f1f9..0000000
--- a/region/command/NOTICE
+++ /dev/null
@@ -1,71 +0,0 @@
-Apache Karaf
-Copyright 2010-2014 The Apache Software Foundation
-
-
-I. Included Software
-
-This product includes software developed at
-The Apache Software Foundation (http://www.apache.org/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-The OSGi Alliance (http://www.osgi.org/).
-Copyright (c) OSGi Alliance (2000, 2010).
-Licensed under the Apache License 2.0.
-
-This product includes software developed at
-OW2 (http://www.ow2.org/).
-Licensed under the BSD License.
-
-This product includes software developed at
-OPS4J (http://www.ops4j.org/).
-Licensed under the Apache License 2.0.
-
-This product includes software developed at
-Eclipse Foundation (http://www.eclipse.org/).
-Licensed under the EPL.
-
-This product includes software written by
-Antony Lesuisse.
-Licensed under Public Domain.
-
-
-II. Used Software
-
-This product uses software developed at
-FUSE Source (http://www.fusesource.org/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-AOP Alliance (http://aopalliance.sourceforge.net/).
-Licensed under the Public Domain.
-
-This product uses software developed at
-Tanuki Software (http://www.tanukisoftware.com/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-Jasypt (http://jasypt.sourceforge.net/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-JLine (http://jline.sourceforge.net).
-Licensed under the BSD License.
-
-This product uses software developed at
-SLF4J (http://www.slf4j.org/).
-Licensed under the MIT License.
-
-This product uses software developed at
-SpringSource (http://www.springsource.org/).
-Licensed under the Apache License 2.0.
-
-This product includes software from http://www.json.org.
-Copyright (c) 2002 JSON.org
-
-
-III. License Summary
-- Apache License 2.0
-- BSD License
-- EPL License
-- MIT License

http://git-wip-us.apache.org/repos/asf/karaf/blob/1bcdb173/region/command/pom.xml
----------------------------------------------------------------------
diff --git a/region/command/pom.xml b/region/command/pom.xml
deleted file mode 100644
index e5382a3..0000000
--- a/region/command/pom.xml
+++ /dev/null
@@ -1,100 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-
-    <!--
-
-        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.
-    -->
-
-    <modelVersion>4.0.0</modelVersion>
-
-    <parent>
-        <groupId>org.apache.karaf.region</groupId>
-        <artifactId>region</artifactId>
-        <version>4.0.0-SNAPSHOT</version>
-    </parent>
-
-    <artifactId>org.apache.karaf.region.command</artifactId>
-    <packaging>bundle</packaging>
-    <name>Apache Karaf :: Region :: Shell Commands</name>
-    <description>This bundle provides Karaf shell commands to manipulate the Region service.</description>
-
-    <properties>
-        <appendedResourcesDirectory>${basedir}/../../etc/appended-resources</appendedResourcesDirectory>
-    </properties>
-
-    <dependencies>
-        <dependency>
-            <groupId>org.osgi</groupId>
-            <artifactId>org.osgi.core</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.karaf.shell</groupId>
-            <artifactId>org.apache.karaf.shell.core</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.aries</groupId>
-            <artifactId>org.apache.aries.util</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.eclipse.equinox</groupId>
-            <artifactId>region</artifactId>
-            <version>1.0.0.v20110506</version>
-        </dependency>
-
-        <dependency>
-            <groupId>org.easymock</groupId>
-            <artifactId>easymock</artifactId>
-            <scope>test</scope>
-        </dependency>
-		<dependency>
-            <groupId>org.slf4j</groupId>
-            <artifactId>slf4j-jdk14</artifactId>
-            <scope>test</scope>
-        </dependency>
-    </dependencies>
-
-    <build>
-        <resources>
-            <resource>
-                <directory>${project.basedir}/src/main/resources</directory>
-                <includes>
-                    <include>**/*</include>
-                </includes>
-            </resource>
-            <resource>
-                <directory>${project.basedir}/src/main/resources</directory>
-                <filtering>true</filtering>
-                <includes>
-                    <include>**/*.info</include>
-                </includes>
-            </resource>
-        </resources>
-        <plugins>
-            <plugin>
-                <groupId>org.apache.felix</groupId>
-                <artifactId>maven-bundle-plugin</artifactId>
-                <configuration>
-                    <instructions>
-                        <Karaf-Commands>*</Karaf-Commands>
-                    </instructions>
-                </configuration>
-            </plugin>
-        </plugins>
-    </build>
-
-</project>

http://git-wip-us.apache.org/repos/asf/karaf/blob/1bcdb173/region/command/src/main/java/org/apache/karaf/region/commands/AddBundleCommand.java
----------------------------------------------------------------------
diff --git a/region/command/src/main/java/org/apache/karaf/region/commands/AddBundleCommand.java b/region/command/src/main/java/org/apache/karaf/region/commands/AddBundleCommand.java
deleted file mode 100644
index 30af1e0..0000000
--- a/region/command/src/main/java/org/apache/karaf/region/commands/AddBundleCommand.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * 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.karaf.region.commands;
-
-import java.util.List;
-
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.eclipse.equinox.region.Region;
-import org.eclipse.equinox.region.RegionDigraph;
-import org.osgi.framework.Bundle;
-
-@Command(scope = "region", name = "bundle-add", description = "Adds a list of known bundles by id to a specified region.")
-@Service
-public class AddBundleCommand extends RegionCommandSupport {
-
-    @Argument(index = 0, name = "region", description = "Region to add the bundles to", required = true, multiValued = false)
-    String region;
-
-    @Argument(index = 1, name = "bundles", description = "Bundles by id to add to the region", required = true, multiValued = true)
-    List<Long> ids;
-
-    protected void doExecute(RegionDigraph regionDigraph) throws Exception {
-        Region r = getRegion(regionDigraph, region);
-        for (Long id : ids) {
-            for (Region existing: regionDigraph.getRegions()) {
-                if (existing.contains(id)) {
-                    Bundle b = bundleContext.getBundle(id);
-                    System.out.println("Removing bundle " + id + " from region " + existing.getName());
-                    existing.removeBundle(b);
-                    break;
-                }
-            }
-            r.addBundle(id);
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/1bcdb173/region/command/src/main/java/org/apache/karaf/region/commands/AddFilterCommand.java
----------------------------------------------------------------------
diff --git a/region/command/src/main/java/org/apache/karaf/region/commands/AddFilterCommand.java b/region/command/src/main/java/org/apache/karaf/region/commands/AddFilterCommand.java
deleted file mode 100644
index ec3766d..0000000
--- a/region/command/src/main/java/org/apache/karaf/region/commands/AddFilterCommand.java
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- * 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.karaf.region.commands;
-
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import org.apache.aries.util.VersionRange;
-import org.apache.aries.util.manifest.ManifestHeaderProcessor;
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.eclipse.equinox.region.Region;
-import org.eclipse.equinox.region.RegionDigraph;
-import org.eclipse.equinox.region.RegionFilter;
-import org.eclipse.equinox.region.RegionFilterBuilder;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.Constants;
-
-@Command(scope = "region", name = "filter-add", description = "Adds a filter between two regions.")
-@Service
-public class AddFilterCommand extends RegionCommandSupport {
-
-    @Argument(index = 0, name = "from", description = "The from region.", required = true, multiValued = false)
-    String fromRegion;
-
-    @Argument(index = 1, name = "to", description = "The to region.", required = true, multiValued = false)
-    String toRegion;
-
-    @Argument(index = 2, name = "items", description = "The bundles by id and packages with version to allow.", required = false, multiValued = true)
-    List<String> items;
-
-    protected void doExecute(RegionDigraph regionDigraph) throws Exception {
-        Region rFrom = getRegion(regionDigraph, fromRegion);
-        Region rTo = getRegion(regionDigraph, toRegion);
-        RegionFilterBuilder builder = regionDigraph.createRegionFilterBuilder();
-        BundleContext framework = bundleContext.getBundle(0).getBundleContext();
-        if (items != null) {
-            for (String item : items) {
-                try {
-                    long id = Long.parseLong(item);
-                    Bundle b = framework.getBundle(id);
-                    builder.allow("osgi.wiring.bundle", "(osgi.wiring.bundle=" + b.getSymbolicName() + ")");
-                } catch (NumberFormatException e) {
-                    for (Map.Entry<String, Map<String, String>> parsed: ManifestHeaderProcessor.parseImportString(item).entrySet()) {
-                        String packageName = parsed.getKey();
-                        Map<String, String> attributes = new HashMap<String, String>(parsed.getValue());
-                        attributes.put("osgi.wiring.package", packageName);
-                        String filter = generateFilter(attributes);
-                        System.out.println("adding filter " + filter);
-                        builder.allow("osgi.wiring.package", filter);
-                    }
-                }
-
-            }
-        }
-        RegionFilter f = builder.build();
-        regionDigraph.connect(rFrom, f, rTo);
-    }
-
-    //from aries util, with obr specific weirdness removed
-    public static String generateFilter(Map<String, String> attribs) {
-        StringBuilder filter = new StringBuilder("(&");
-        boolean realAttrib = false;
-        StringBuffer realAttribs = new StringBuffer();
-
-        if (attribs == null) {
-            attribs = new HashMap<String, String>();
-        }
-
-        for (Map.Entry<String, String> attrib : attribs.entrySet()) {
-            String attribName = attrib.getKey();
-
-            if (attribName.endsWith(":")) {
-                // skip all directives. It is used to affect the attribs on the
-                // filter xml.
-            } else if ((Constants.VERSION_ATTRIBUTE.equals(attribName))
-                    || (Constants.BUNDLE_VERSION_ATTRIBUTE.equals(attribName))) {
-                // version and bundle-version attrib requires special
-                // conversion.
-                realAttrib = true;
-
-                VersionRange vr = ManifestHeaderProcessor
-                        .parseVersionRange(attrib.getValue());
-
-                filter.append("(" + attribName + ">=" + vr.getMinimumVersion());
-
-                if (vr.getMaximumVersion() != null) {
-                    filter.append(")(" + attribName + "<=");
-                    filter.append(vr.getMaximumVersion());
-                }
-
-                if (vr.getMaximumVersion() != null && vr.isMinimumExclusive()) {
-                    filter.append(")(!(" + attribName + "=");
-                    filter.append(vr.getMinimumVersion());
-                    filter.append(")");
-                }
-
-                if (vr.getMaximumVersion() != null && vr.isMaximumExclusive()) {
-                    filter.append(")(!(" + attribName + "=");
-                    filter.append(vr.getMaximumVersion());
-                    filter.append(")");
-                }
-                filter.append(")");
-
-            } else if (Constants.OBJECTCLASS.equals(attribName)) {
-                realAttrib = true;
-                // objectClass has a "," separated list of interfaces
-                String[] values = attrib.getValue().split(",");
-                for (String s : values)
-                    filter.append("(" + Constants.OBJECTCLASS + "=" + s + ")");
-
-            } else {
-                // attribName was not version..
-                realAttrib = true;
-
-                filter.append("(" + attribName + "=" + attrib.getValue() + ")");
-                // store all attributes in order to build up the mandatory
-                // filter and separate them with ", "
-                // skip bundle-symbolic-name in the mandatory directive query
-                if (!!!Constants.BUNDLE_SYMBOLICNAME_ATTRIBUTE
-                        .equals(attribName)) {
-                    realAttribs.append(attribName);
-                    realAttribs.append(", ");
-                }
-            }
-        }
-
-        // Prune (& off the front and ) off end
-        String filterString = filter.toString();
-        int openBraces = 0;
-        for (int i = 0; openBraces < 3; i++) {
-            i = filterString.indexOf('(', i);
-            if (i == -1) {
-                break;
-            } else {
-                openBraces++;
-            }
-        }
-        if (openBraces < 3 && filterString.length() > 2) {
-            filter.delete(0, 2);
-        } else {
-            filter.append(")");
-        }
-
-        String result = "";
-        if (realAttrib != false) {
-            result = filter.toString();
-        }
-        return result;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/1bcdb173/region/command/src/main/java/org/apache/karaf/region/commands/AddRegionCommand.java
----------------------------------------------------------------------
diff --git a/region/command/src/main/java/org/apache/karaf/region/commands/AddRegionCommand.java b/region/command/src/main/java/org/apache/karaf/region/commands/AddRegionCommand.java
deleted file mode 100644
index 22c817b..0000000
--- a/region/command/src/main/java/org/apache/karaf/region/commands/AddRegionCommand.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * 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.karaf.region.commands;
-
-import java.util.List;
-
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.eclipse.equinox.region.RegionDigraph;
-
-@Command(scope = "region", name = "region-add", description = "Adds a list of regions to the region digraph service.")
-@Service
-public class AddRegionCommand extends RegionCommandSupport {
-
-    @Argument(index = 0, name = "name", description = "Regions to add to the region digraph service separated by whitespaces.", required = true, multiValued = true)
-    List<String> regions;
-
-    protected void doExecute(RegionDigraph regionDigraph) throws Exception {
-        for (String region : regions) {
-            regionDigraph.createRegion(region);
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/1bcdb173/region/command/src/main/java/org/apache/karaf/region/commands/InfoCommand.java
----------------------------------------------------------------------
diff --git a/region/command/src/main/java/org/apache/karaf/region/commands/InfoCommand.java b/region/command/src/main/java/org/apache/karaf/region/commands/InfoCommand.java
deleted file mode 100644
index 7c71e36..0000000
--- a/region/command/src/main/java/org/apache/karaf/region/commands/InfoCommand.java
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * 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.karaf.region.commands;
-
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Option;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.eclipse.equinox.region.Region;
-import org.eclipse.equinox.region.RegionDigraph;
-import org.eclipse.equinox.region.RegionFilter;
-import org.osgi.framework.Bundle;
-
-@Command(scope = "region", name = "info", description = "Prints information about region digraph.")
-@Service
-public class InfoCommand extends RegionCommandSupport {
-
-    @Option(name = "-v", aliases = "--verbose", required = false, description = "Show all info.")
-    boolean verbose;
-
-    @Option(name = "-b", aliases = "--bundles", required = false, description = "Show bundles in each region.")
-    boolean bundles;
-
-    @Option(name = "-f", aliases = "--filters", required = false, description = "Show filters.")
-    boolean filters;
-
-    @Option(name = "-n", aliases = "--namespaces", required = false, description = "Show namespaces in each filter.")
-    boolean namespaces;
-
-    @Argument(index = 0, name = "regions", description = "Regions to provide detailed info for.", required = false, multiValued = true)
-    List<String> regions;
-
-    protected void doExecute(RegionDigraph regionDigraph) throws Exception {
-        System.out.println("Regions");
-        if (regions == null) {
-            for (Region region : regionDigraph.getRegions()) {
-                showRegion(region);
-            }
-        } else {
-            bundles = true;
-            filters = true;
-            namespaces = true;
-            for (String regionName : regions) {
-                Region region = regionDigraph.getRegion(regionName);
-                if (region == null) {
-                    System.out.println("No region " + regionName);
-                } else {
-                    showRegion(region);
-                }
-            }
-        }
-    }
-
-    private void showRegion(Region region) {
-        System.out.println(region.getName());
-        if (verbose || bundles) {
-            for (Long id : region.getBundleIds()) {
-                Bundle b = bundleContext.getBundle(id);
-                System.out.println("  " + id + "  " + getStateString(b) + b);
-            }
-        }
-        if (verbose || filters || namespaces) {
-            for (RegionDigraph.FilteredRegion f : region.getEdges()) {
-                System.out.println("  filter to " + f.getRegion().getName());
-                if (verbose || namespaces) {
-                    RegionFilter rf = f.getFilter();
-                    for (Map.Entry<String, Collection<String>> policy : rf.getSharingPolicy().entrySet()) {
-                        String namespace = policy.getKey();
-                        System.out.println("  namespace: " + namespace);
-                        for (String e : policy.getValue()) {
-                            System.out.println("    " + e);
-                        }
-                    }
-                }
-            }
-        }
-    }
-
-    public String getStateString(Bundle bundle) {
-        if (bundle == null) {
-            return "Bundle null";
-        }
-        int state = bundle.getState();
-        if (state == Bundle.ACTIVE) {
-            return "Active     ";
-        } else if (state == Bundle.INSTALLED) {
-            return "Installed  ";
-        } else if (state == Bundle.RESOLVED) {
-            return "Resolved   ";
-        } else if (state == Bundle.STARTING) {
-            return "Starting   ";
-        } else if (state == Bundle.STOPPING) {
-            return "Stopping   ";
-        } else {
-            return "Unknown    ";
-        }
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/1bcdb173/region/command/src/main/java/org/apache/karaf/region/commands/RegionCommandSupport.java
----------------------------------------------------------------------
diff --git a/region/command/src/main/java/org/apache/karaf/region/commands/RegionCommandSupport.java b/region/command/src/main/java/org/apache/karaf/region/commands/RegionCommandSupport.java
deleted file mode 100644
index bcdfb6c..0000000
--- a/region/command/src/main/java/org/apache/karaf/region/commands/RegionCommandSupport.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * 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.karaf.region.commands;
-
-import java.io.PrintStream;
-
-import org.apache.karaf.shell.api.action.Action;
-import org.apache.karaf.shell.api.action.lifecycle.Reference;
-import org.eclipse.equinox.region.Region;
-import org.eclipse.equinox.region.RegionDigraph;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.BundleException;
-import org.osgi.framework.ServiceReference;
-
-public abstract class RegionCommandSupport implements Action {
-
-    protected static final char VERSION_DELIM = ',';
-
-    @Reference
-    BundleContext bundleContext;
-
-    @Override
-    public Object execute() throws Exception {
-        // Get repository instance service.
-        ServiceReference ref = bundleContext.getServiceReference(RegionDigraph.class.getName());
-        if (ref == null) {
-            System.out.println("RegionDigraph service is unavailable.");
-            return null;
-        }
-        try {
-            RegionDigraph admin = (RegionDigraph) bundleContext.getService(ref);
-            if (admin == null) {
-                System.out.println("RegionDigraph service is unavailable.");
-                return null;
-            }
-
-            doExecute(admin);
-        }
-        finally {
-            bundleContext.ungetService(ref);
-        }
-        return null;
-    }
-
-    abstract void doExecute(RegionDigraph admin) throws Exception;
-
-    protected void printUnderline(PrintStream out, int length)
-    {
-        for (int i = 0; i < length; i++)
-        {
-            out.print('-');
-        }
-        out.println("");
-    }
-
-
-    protected Region getRegion(RegionDigraph regionDigraph, String region) throws BundleException {
-        Region r = regionDigraph.getRegion(region);
-        if (r == null) {
-            System.out.println("No region: " + region + ", creating it");
-            r = regionDigraph.createRegion(region);
-        }
-        return r;
-    }
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/1bcdb173/region/command/src/main/java/org/apache/karaf/region/commands/util/FileUtil.java
----------------------------------------------------------------------
diff --git a/region/command/src/main/java/org/apache/karaf/region/commands/util/FileUtil.java b/region/command/src/main/java/org/apache/karaf/region/commands/util/FileUtil.java
deleted file mode 100644
index 07c39e9..0000000
--- a/region/command/src/main/java/org/apache/karaf/region/commands/util/FileUtil.java
+++ /dev/null
@@ -1,177 +0,0 @@
-/*
- * 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.karaf.region.commands.util;
-
-import java.io.BufferedOutputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.PrintStream;
-import java.net.URL;
-import java.net.URLConnection;
-import java.util.jar.JarEntry;
-import java.util.jar.JarInputStream;
-
-public class FileUtil
-{
-    public static void downloadSource(
-        PrintStream out, PrintStream err,
-        URL srcURL, String dirStr, boolean extract)
-    {
-        // Get the file name from the URL.
-        String fileName = (srcURL.getFile().lastIndexOf('/') > 0)
-            ? srcURL.getFile().substring(srcURL.getFile().lastIndexOf('/') + 1)
-            : srcURL.getFile();
-
-        try
-        {
-            out.println("Connecting...");
-
-            File dir = new File(dirStr);
-            if (!dir.exists())
-            {
-                err.println("Destination directory does not exist.");
-            }
-            File file = new File(dir, fileName);
-
-            OutputStream os = new FileOutputStream(file);
-            URLConnection conn = srcURL.openConnection();
-            int total = conn.getContentLength();
-            InputStream is = conn.getInputStream();
-
-            if (total > 0)
-            {
-                out.println("Downloading " + fileName
-                    + " ( " + total + " bytes ).");
-            }
-            else
-            {
-                out.println("Downloading " + fileName + ".");
-            }
-            byte[] buffer = new byte[4096];
-            int count = 0;
-            for (int len = is.read(buffer); len > 0; len = is.read(buffer))
-            {
-                count += len;
-                os.write(buffer, 0, len);
-            }
-
-            os.close();
-            is.close();
-
-            if (extract)
-            {
-                is = new FileInputStream(file);
-                JarInputStream jis = new JarInputStream(is);
-                out.println("Extracting...");
-                unjar(jis, dir);
-                jis.close();
-                file.delete();
-            }
-        }
-        catch (Exception ex)
-        {
-            err.println(ex);
-        }
-    }
-
-    public static void unjar(JarInputStream jis, File dir)
-        throws IOException
-    {
-        // Reusable buffer.
-        byte[] buffer = new byte[4096];
-
-        // Loop through JAR entries.
-        for (JarEntry je = jis.getNextJarEntry();
-             je != null;
-             je = jis.getNextJarEntry())
-        {
-            if (je.getName().startsWith("/"))
-            {
-                throw new IOException("JAR resource cannot contain absolute paths.");
-            }
-
-            File target = new File(dir, je.getName());
-
-            // Check to see if the JAR entry is a directory.
-            if (je.isDirectory())
-            {
-                if (!target.exists())
-                {
-                    if (!target.mkdirs())
-                    {
-                        throw new IOException("Unable to create target directory: "
-                            + target);
-                    }
-                }
-                // Just continue since directories do not have content to copy.
-                continue;
-            }
-
-            int lastIndex = je.getName().lastIndexOf('/');
-            String name = (lastIndex >= 0) ?
-                je.getName().substring(lastIndex + 1) : je.getName();
-            String destination = (lastIndex >= 0) ?
-                je.getName().substring(0, lastIndex) : "";
-
-            // JAR files use '/', so convert it to platform separator.
-            destination = destination.replace('/', File.separatorChar);
-            copy(jis, dir, name, destination, buffer);
-        }
-    }
-
-    public static void copy(
-        InputStream is, File dir, String destName, String destDir, byte[] buffer)
-        throws IOException
-    {
-        if (destDir == null)
-        {
-            destDir = "";
-        }
-
-        // Make sure the target directory exists and
-        // that is actually a directory.
-        File targetDir = new File(dir, destDir);
-        if (!targetDir.exists())
-        {
-            if (!targetDir.mkdirs())
-            {
-                throw new IOException("Unable to create target directory: "
-                    + targetDir);
-            }
-        }
-        else if (!targetDir.isDirectory())
-        {
-            throw new IOException("Target is not a directory: "
-                + targetDir);
-        }
-
-        BufferedOutputStream bos = new BufferedOutputStream(
-            new FileOutputStream(new File(targetDir, destName)));
-        int count = 0;
-        while ((count = is.read(buffer)) > 0)
-        {
-            bos.write(buffer, 0, count);
-        }
-        bos.close();
-    }
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/1bcdb173/region/command/src/main/resources/OSGI-INF/bundle.info
----------------------------------------------------------------------
diff --git a/region/command/src/main/resources/OSGI-INF/bundle.info b/region/command/src/main/resources/OSGI-INF/bundle.info
deleted file mode 100644
index 0005414..0000000
--- a/region/command/src/main/resources/OSGI-INF/bundle.info
+++ /dev/null
@@ -1,18 +0,0 @@
-h1. Synopsis
-
-${project.name}
-
-${project.description}
-
-Maven URL:
-[mvn:${project.groupId}/${project.artifactId}/${project.version}]
-
-h1. Description
-
-This bundle provides Karaf shell commands to manipulate the Karaf embedded Region service.
-
-The following commands are available:
-* region:addbundle - Adds specified bundles (by id) to a region.
-* region:addfilter - Adds a filter between two regions containing bundles (by id) and packages (with attributes including version).
-* region:addregion - adds regions.
-* region:info - Prints information about region digraph.
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/karaf/blob/1bcdb173/region/core/NOTICE
----------------------------------------------------------------------
diff --git a/region/core/NOTICE b/region/core/NOTICE
deleted file mode 100644
index b70f1f9..0000000
--- a/region/core/NOTICE
+++ /dev/null
@@ -1,71 +0,0 @@
-Apache Karaf
-Copyright 2010-2014 The Apache Software Foundation
-
-
-I. Included Software
-
-This product includes software developed at
-The Apache Software Foundation (http://www.apache.org/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-The OSGi Alliance (http://www.osgi.org/).
-Copyright (c) OSGi Alliance (2000, 2010).
-Licensed under the Apache License 2.0.
-
-This product includes software developed at
-OW2 (http://www.ow2.org/).
-Licensed under the BSD License.
-
-This product includes software developed at
-OPS4J (http://www.ops4j.org/).
-Licensed under the Apache License 2.0.
-
-This product includes software developed at
-Eclipse Foundation (http://www.eclipse.org/).
-Licensed under the EPL.
-
-This product includes software written by
-Antony Lesuisse.
-Licensed under Public Domain.
-
-
-II. Used Software
-
-This product uses software developed at
-FUSE Source (http://www.fusesource.org/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-AOP Alliance (http://aopalliance.sourceforge.net/).
-Licensed under the Public Domain.
-
-This product uses software developed at
-Tanuki Software (http://www.tanukisoftware.com/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-Jasypt (http://jasypt.sourceforge.net/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-JLine (http://jline.sourceforge.net).
-Licensed under the BSD License.
-
-This product uses software developed at
-SLF4J (http://www.slf4j.org/).
-Licensed under the MIT License.
-
-This product uses software developed at
-SpringSource (http://www.springsource.org/).
-Licensed under the Apache License 2.0.
-
-This product includes software from http://www.json.org.
-Copyright (c) 2002 JSON.org
-
-
-III. License Summary
-- Apache License 2.0
-- BSD License
-- EPL License
-- MIT License

http://git-wip-us.apache.org/repos/asf/karaf/blob/1bcdb173/region/core/pom.xml
----------------------------------------------------------------------
diff --git a/region/core/pom.xml b/region/core/pom.xml
deleted file mode 100644
index f1a792a..0000000
--- a/region/core/pom.xml
+++ /dev/null
@@ -1,122 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-
-    <!--
-
-        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.
-    -->
-
-    <modelVersion>4.0.0</modelVersion>
-
-    <parent>
-        <groupId>org.apache.karaf.region</groupId>
-        <artifactId>region</artifactId>
-        <version>4.0.0-SNAPSHOT</version>
-    </parent>
-
-    <artifactId>org.apache.karaf.region.core</artifactId>
-    <packaging>bundle</packaging>
-    <name>Apache Karaf :: Region :: Persistence</name>
-    <description>This bundle provides an xml regions model and install/dump actions.</description>
-
-    <properties>
-        <appendedResourcesDirectory>${basedir}/../../etc/appended-resources</appendedResourcesDirectory>
-    </properties>
-
-    <dependencies>
-        <dependency>
-            <groupId>org.osgi</groupId>
-            <artifactId>org.osgi.core</artifactId>
-            <scope>provided</scope>
-        </dependency>
-
-        <dependency>
-            <groupId>org.apache.karaf</groupId>
-            <artifactId>org.apache.karaf.util</artifactId>
-            <scope>provided</scope>
-        </dependency>
-
-        <dependency>
-            <groupId>org.osgi</groupId>
-            <artifactId>org.osgi.compendium</artifactId>
-            <scope>provided</scope>
-        </dependency>
-
-        <dependency>
-            <groupId>org.slf4j</groupId>
-            <artifactId>slf4j-api</artifactId>
-            <scope>provided</scope>
-        </dependency>
-
-        <dependency>
-            <groupId>org.apache.karaf.features</groupId>
-            <artifactId>org.apache.karaf.features.core</artifactId>
-        </dependency>
-
-        <dependency>
-            <groupId>org.eclipse.equinox</groupId>
-            <artifactId>region</artifactId>
-            <version>1.0.0.v20110506</version>
-        </dependency>
-
-        <dependency>
-            <groupId>org.easymock</groupId>
-            <artifactId>easymock</artifactId>
-            <scope>test</scope>
-        </dependency>
-		<dependency>
-            <groupId>org.slf4j</groupId>
-            <artifactId>slf4j-jdk14</artifactId>
-            <scope>test</scope>
-        </dependency>
-    </dependencies>
-
-    <build>
-        <resources>
-            <resource>
-                <directory>${project.basedir}/src/main/resources</directory>
-                <includes>
-                    <include>**/*</include>
-                </includes>
-            </resource>
-            <resource>
-                <directory>${project.basedir}/src/main/resources</directory>
-                <filtering>true</filtering>
-                <includes>
-                    <include>**/*.info</include>
-                </includes>
-            </resource>
-        </resources>
-        <plugins>
-            <plugin>
-                <groupId>org.apache.felix</groupId>
-                <artifactId>maven-bundle-plugin</artifactId>
-                <configuration>
-                    <instructions>
-                        <Bundle-Activator>
-                            org.apache.karaf.region.persist.internal.Activator
-                        </Bundle-Activator>
-                        <Private-Package>
-                            org.apache.karaf.region.persist.internal.*,
-                            org.apache.karaf.util.tracker
-                        </Private-Package>
-                    </instructions>
-                </configuration>
-            </plugin>
-        </plugins>
-    </build>
-
-</project>

http://git-wip-us.apache.org/repos/asf/karaf/blob/1bcdb173/region/core/src/main/java/org/apache/karaf/region/persist/internal/Activator.java
----------------------------------------------------------------------
diff --git a/region/core/src/main/java/org/apache/karaf/region/persist/internal/Activator.java b/region/core/src/main/java/org/apache/karaf/region/persist/internal/Activator.java
deleted file mode 100644
index aa7215f..0000000
--- a/region/core/src/main/java/org/apache/karaf/region/persist/internal/Activator.java
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * 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.karaf.region.persist.internal;
-
-import java.util.concurrent.atomic.AtomicReference;
-
-import org.apache.karaf.features.RegionsPersistence;
-import org.apache.karaf.util.tracker.SingleServiceTracker;
-import org.eclipse.equinox.region.RegionDigraph;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.BundleActivator;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.ServiceRegistration;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class Activator implements BundleActivator {
-
-    private static final Logger log = LoggerFactory.getLogger(Activator.class);
-
-    private SingleServiceTracker<RegionDigraph> tracker;
-    private final AtomicReference<RegionsPersistenceImpl> persistence = new AtomicReference<RegionsPersistenceImpl>();
-    private final AtomicReference<RegionsBundleTracker> bundleTracker = new AtomicReference<RegionsBundleTracker>();
-    private ServiceRegistration<RegionsPersistence> reg;
-
-    @Override
-    public void start(final BundleContext bundleContext) throws Exception {
-        tracker = new SingleServiceTracker<RegionDigraph>(bundleContext, RegionDigraph.class, new SingleServiceTracker.SingleServiceListener() {
-            public void serviceFound() {
-                log.debug("Found RegionDigraph service, initializing");
-                RegionDigraph regionDigraph = tracker.getService();
-                Bundle framework = bundleContext.getBundle(0);
-                RegionsPersistenceImpl persistence = null;
-                try {
-                    persistence = new RegionsPersistenceImpl(regionDigraph, framework);
-                    reg = bundleContext.registerService(RegionsPersistence.class, persistence, null);
-
-                    RegionsBundleTracker bundleTracker = new RegionsBundleTracker();
-                    bundleTracker.start(bundleContext, persistence);
-                    Activator.this.bundleTracker.set(bundleTracker);
-                } catch (Exception e) {
-                    log.info("Could not create RegionsPersistenceImpl", e);
-                }
-                Activator.this.persistence.set(persistence);
-            }
-
-            public void serviceLost() {
-                if (reg != null) {
-                    reg.unregister();
-                    reg = null;
-                }
-                Activator.this.persistence.set(null);
-                Activator.this.bundleTracker.set(null);
-            }
-
-            public void serviceReplaced() {
-                //??
-            }
-        });
-        tracker.open();
-    }
-
-    @Override
-    public void stop(BundleContext bundleContext) throws Exception {
-        tracker.close();
-        persistence.set(null);
-        RegionsBundleTracker tracker = bundleTracker.getAndSet(null);
-        if (tracker != null) {
-            tracker.stop();
-        }
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/1bcdb173/region/core/src/main/java/org/apache/karaf/region/persist/internal/RegionsBundleTracker.java
----------------------------------------------------------------------
diff --git a/region/core/src/main/java/org/apache/karaf/region/persist/internal/RegionsBundleTracker.java b/region/core/src/main/java/org/apache/karaf/region/persist/internal/RegionsBundleTracker.java
deleted file mode 100644
index 7035303..0000000
--- a/region/core/src/main/java/org/apache/karaf/region/persist/internal/RegionsBundleTracker.java
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * 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.karaf.region.persist.internal;
-
-import org.apache.karaf.features.RegionsPersistence;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.BundleEvent;
-import org.osgi.framework.BundleException;
-import org.osgi.util.tracker.BundleTracker;
-import org.osgi.util.tracker.BundleTrackerCustomizer;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class RegionsBundleTracker {
-    private static final Logger log = LoggerFactory.getLogger(RegionsBundleTracker.class);
-
-    private BundleTracker bundleTracker;
-    private RegionsPersistence regionsPersistence;
-
-    void start(BundleContext bundleContext, RegionsPersistence regionsPersistence) {
-        this.regionsPersistence = regionsPersistence;
-        int stateMask = Bundle.INSTALLED;
-        bundleTracker = new BundleTracker<Bundle>(bundleContext, stateMask, new BundleTrackerCustomizer<Bundle>() {
-            @Override
-            public Bundle addingBundle(Bundle bundle, BundleEvent bundleEvent) {
-                return RegionsBundleTracker.this.addingBundle(bundle);
-            }
-
-            @Override
-            public void modifiedBundle(Bundle bundle, BundleEvent bundleEvent, Bundle o) {
-            }
-
-            @Override
-            public void removedBundle(Bundle bundle, BundleEvent bundleEvent, Bundle o) {
-            }
-        });
-        bundleTracker.open();
-    }
-
-    private Bundle addingBundle(Bundle bundle) {
-        String region = bundle.getHeaders().get("Region");
-        if (region != null) {
-            try {
-                regionsPersistence.install(bundle, region);
-                log.debug("Installed bundle " + bundle + " in region " + region);
-                return bundle;
-            } catch (BundleException e) {
-                log.info("Could not install bundle " + bundle + " in region " + region, e);
-            }
-        }
-        return null;
-    }
-
-    void stop() {
-        bundleTracker.close();
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/1bcdb173/region/core/src/main/java/org/apache/karaf/region/persist/internal/RegionsPersistenceImpl.java
----------------------------------------------------------------------
diff --git a/region/core/src/main/java/org/apache/karaf/region/persist/internal/RegionsPersistenceImpl.java b/region/core/src/main/java/org/apache/karaf/region/persist/internal/RegionsPersistenceImpl.java
deleted file mode 100644
index dcf5d26..0000000
--- a/region/core/src/main/java/org/apache/karaf/region/persist/internal/RegionsPersistenceImpl.java
+++ /dev/null
@@ -1,203 +0,0 @@
-/*
- * 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.karaf.region.persist.internal;
-
-import java.io.File;
-import java.io.FileReader;
-import java.io.IOException;
-import java.io.Reader;
-import java.io.Writer;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import javax.xml.bind.JAXBContext;
-import javax.xml.bind.JAXBException;
-import javax.xml.bind.Marshaller;
-import javax.xml.bind.Unmarshaller;
-
-import org.apache.karaf.features.RegionsPersistence;
-import org.apache.karaf.region.persist.internal.model.FilterAttributeType;
-import org.apache.karaf.region.persist.internal.model.FilterBundleType;
-import org.apache.karaf.region.persist.internal.model.FilterNamespaceType;
-import org.apache.karaf.region.persist.internal.model.FilterPackageType;
-import org.apache.karaf.region.persist.internal.model.FilterType;
-import org.apache.karaf.region.persist.internal.model.RegionBundleType;
-import org.apache.karaf.region.persist.internal.model.RegionType;
-import org.apache.karaf.region.persist.internal.model.RegionsType;
-import org.apache.karaf.region.persist.internal.util.ManifestHeaderProcessor;
-import org.eclipse.equinox.region.Region;
-import org.eclipse.equinox.region.RegionDigraph;
-import org.eclipse.equinox.region.RegionFilterBuilder;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.BundleException;
-import org.osgi.framework.InvalidSyntaxException;
-import org.osgi.framework.wiring.BundleCapability;
-import org.osgi.framework.wiring.BundleRevision;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class RegionsPersistenceImpl implements RegionsPersistence {
-
-    private static final Logger log = LoggerFactory.getLogger(RegionsPersistenceImpl.class);
-
-    private JAXBContext jaxbContext;
-    private RegionDigraph regionDigraph;
-    private Region kernel;
-    private Bundle framework;
-
-    public RegionsPersistenceImpl(RegionDigraph regionDigraph, Bundle framework) throws JAXBException, BundleException, IOException, InvalidSyntaxException {
-        log.info("Loading region digraph persistence");
-        this.framework = framework;
-        this.regionDigraph = regionDigraph;
-        kernel = regionDigraph.getRegion(0);
-        jaxbContext = JAXBContext.newInstance(RegionsType.class);
-        load();
-    }
-
-    @Override
-    public void install(Bundle b, String regionName) throws BundleException {
-        Region region = regionDigraph.getRegion(regionName);
-        if (region == null) {
-            region = regionDigraph.createRegion(regionName);
-        }
-        kernel.removeBundle(b);
-        region.addBundle(b);
-    }
-
-    void save(RegionsType regionsType, Writer out) throws JAXBException {
-        Marshaller marshaller = jaxbContext.createMarshaller();
-        marshaller.marshal(regionsType, out);
-    }
-
-    void load() throws IOException, BundleException, JAXBException, InvalidSyntaxException {
-        if (this.regionDigraph.getRegions().size() <= 1) {
-            File etc = new File(System.getProperty("karaf.etc"));
-            File regionsConfig = new File(etc, "regions-config.xml");
-            if (regionsConfig.exists()) {
-                log.info("initializing region digraph from etc/regions-config.xml");
-                Reader in = new FileReader(regionsConfig);
-                try {
-                        load(this.regionDigraph, in);
-                    } finally {
-                        in.close();
-                    }
-            } else {
-                log.info("no regions config file");
-            }
-        }
-
-    }
-
-    void  load(RegionDigraph regionDigraph, Reader in) throws JAXBException, BundleException, InvalidSyntaxException {
-        RegionsType regionsType = load(in);
-        load(regionsType, regionDigraph);
-    }
-
-    RegionsType load(Reader in) throws JAXBException {
-        Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
-        return (RegionsType) unmarshaller.unmarshal(in);
-    }
-
-    void load(RegionsType regionsType, RegionDigraph regionDigraph) throws BundleException, InvalidSyntaxException {
-        BundleContext frameworkContext = framework.getBundleContext();
-        for (RegionType regionType: regionsType.getRegion()) {
-            String name = regionType.getName();
-            log.debug("Creating region: " + name);
-            Region region = regionDigraph.createRegion(name);
-            for (RegionBundleType bundleType: regionType.getBundle()) {
-                if (bundleType.getId() != null) {
-                    region.addBundle(bundleType.getId());
-                } else {
-                    Bundle b = frameworkContext.getBundle(bundleType.getLocation());
-                    region.addBundle(b);
-                }
-            }
-        }
-        for (FilterType filterType: regionsType.getFilter()) {
-            Region from = regionDigraph.getRegion(filterType.getFrom());
-            Region to = regionDigraph.getRegion(filterType.getTo());
-            log.debug("Creating filter between " + from.getName() + " to " + to.getName());
-            RegionFilterBuilder builder = regionDigraph.createRegionFilterBuilder();
-            for (FilterBundleType bundleType: filterType.getBundle()) {
-                String symbolicName = bundleType.getSymbolicName();
-                String version = bundleType.getVersion();
-                if (bundleType.getId() != null) {
-                    Bundle b = frameworkContext.getBundle(bundleType.getId());
-                    symbolicName = b.getSymbolicName();
-                    version = b.getVersion().toString();
-                }
-                String namespace = BundleRevision.BUNDLE_NAMESPACE;
-                List<FilterAttributeType> attributeTypes = bundleType.getAttribute();
-                buildFilter(symbolicName, version, namespace, attributeTypes, builder);
-            }
-            for (FilterPackageType packageType: filterType.getPackage()) {
-                String packageName = packageType.getName();
-                String version = packageType.getVersion();
-                String namespace = BundleRevision.PACKAGE_NAMESPACE;
-                List<FilterAttributeType> attributeTypes = packageType.getAttribute();
-                buildFilter(packageName, version, namespace, attributeTypes, builder);
-            }
-            if (to == kernel) {
-                //add framework exports
-                BundleRevision rev = framework.adapt(BundleRevision.class);
-                List<BundleCapability> caps = rev.getDeclaredCapabilities(BundleRevision.PACKAGE_NAMESPACE);
-                for (BundleCapability cap : caps) {
-                    String filter = ManifestHeaderProcessor.generateFilter(filter(cap.getAttributes()));
-                    builder.allow(BundleRevision.PACKAGE_NAMESPACE, filter);
-                }
-            }
-            //TODO explicit services?
-            for (FilterNamespaceType namespaceType: filterType.getNamespace()) {
-                String namespace = namespaceType.getName();
-                HashMap<String, Object> attributes = new HashMap<String, Object>();
-                for (FilterAttributeType attributeType: namespaceType.getAttribute()) {
-                    attributes.put(attributeType.getName(), attributeType.getValue());
-                }
-                String filter = ManifestHeaderProcessor.generateFilter(attributes);
-                builder.allow(namespace, filter);
-            }
-            regionDigraph.connect(from, builder.build(), to);
-        }
-    }
-
-    private Map<String, Object> filter(Map<String, Object> attributes) {
-        Map<String, Object> result = new HashMap<String, Object>(attributes);
-        result.remove("bundle-version");
-        result.remove("bundle-symbolic-name");
-        return result;
-    }
-
-    private void buildFilter(String packageName, String version, String namespace, List<FilterAttributeType> attributeTypes, RegionFilterBuilder builder) throws InvalidSyntaxException {
-        HashMap<String, Object> attributes = new HashMap<String, Object>();
-        if (namespace != null) {
-            attributes.put(namespace, packageName);
-        }
-        if (version != null) {
-            attributes.put("version", version);
-        }
-        for (FilterAttributeType attributeType: attributeTypes) {
-            attributes.put(attributeType.getName(), attributeType.getValue());
-        }
-        String filter = ManifestHeaderProcessor.generateFilter(attributes);
-        builder.allow(namespace, filter);
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/1bcdb173/region/core/src/main/java/org/apache/karaf/region/persist/internal/model/FilterAttributeType.java
----------------------------------------------------------------------
diff --git a/region/core/src/main/java/org/apache/karaf/region/persist/internal/model/FilterAttributeType.java b/region/core/src/main/java/org/apache/karaf/region/persist/internal/model/FilterAttributeType.java
deleted file mode 100644
index 857c2b3..0000000
--- a/region/core/src/main/java/org/apache/karaf/region/persist/internal/model/FilterAttributeType.java
+++ /dev/null
@@ -1,94 +0,0 @@
-//
-// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, vhudson-jaxb-ri-2.1-833 
-// See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a> 
-// Any modifications to this file will be lost upon recompilation of the source schema. 
-// Generated on: 2011.10.28 at 03:20:55 PM PDT 
-//
-
-
-package org.apache.karaf.region.persist.internal.model;
-
-import javax.xml.bind.annotation.XmlAccessType;
-import javax.xml.bind.annotation.XmlAccessorType;
-import javax.xml.bind.annotation.XmlAttribute;
-import javax.xml.bind.annotation.XmlType;
-
-
-/**
- * <p>Java class for filterAttributeType complex type.
- * 
- * <p>The following schema fragment specifies the expected content contained within this class.
- * 
- * <pre>
- * &lt;complexType name="filterAttributeType">
- *   &lt;complexContent>
- *     &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
- *       &lt;sequence>
- *       &lt;/sequence>
- *       &lt;attribute name="name" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
- *       &lt;attribute name="value" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
- *     &lt;/restriction>
- *   &lt;/complexContent>
- * &lt;/complexType>
- * </pre>
- * 
- * 
- */
-@XmlAccessorType(XmlAccessType.FIELD)
-@XmlType(name = "filterAttributeType")
-public class FilterAttributeType {
-
-    @XmlAttribute(required = true)
-    protected String name;
-    @XmlAttribute(required = true)
-    protected String value;
-
-    /**
-     * Gets the value of the name property.
-     * 
-     * @return
-     *     possible object is
-     *     {@link String }
-     *     
-     */
-    public String getName() {
-        return name;
-    }
-
-    /**
-     * Sets the value of the name property.
-     * 
-     * @param value
-     *     allowed object is
-     *     {@link String }
-     *     
-     */
-    public void setName(String value) {
-        this.name = value;
-    }
-
-    /**
-     * Gets the value of the value property.
-     * 
-     * @return
-     *     possible object is
-     *     {@link String }
-     *     
-     */
-    public String getValue() {
-        return value;
-    }
-
-    /**
-     * Sets the value of the value property.
-     * 
-     * @param value
-     *     allowed object is
-     *     {@link String }
-     *     
-     */
-    public void setValue(String value) {
-        this.value = value;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/1bcdb173/region/core/src/main/java/org/apache/karaf/region/persist/internal/model/FilterBundleType.java
----------------------------------------------------------------------
diff --git a/region/core/src/main/java/org/apache/karaf/region/persist/internal/model/FilterBundleType.java b/region/core/src/main/java/org/apache/karaf/region/persist/internal/model/FilterBundleType.java
deleted file mode 100644
index a9a9fbb..0000000
--- a/region/core/src/main/java/org/apache/karaf/region/persist/internal/model/FilterBundleType.java
+++ /dev/null
@@ -1,156 +0,0 @@
-//
-// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, vhudson-jaxb-ri-2.1-833 
-// See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a> 
-// Any modifications to this file will be lost upon recompilation of the source schema. 
-// Generated on: 2011.10.28 at 03:20:55 PM PDT 
-//
-
-
-package org.apache.karaf.region.persist.internal.model;
-
-import java.util.ArrayList;
-import java.util.List;
-import javax.xml.bind.annotation.XmlAccessType;
-import javax.xml.bind.annotation.XmlAccessorType;
-import javax.xml.bind.annotation.XmlAttribute;
-import javax.xml.bind.annotation.XmlType;
-
-
-/**
- * <p>Java class for filterBundleType complex type.
- * 
- * <p>The following schema fragment specifies the expected content contained within this class.
- * 
- * <pre>
- * &lt;complexType name="filterBundleType">
- *   &lt;complexContent>
- *     &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
- *       &lt;sequence>
- *         &lt;element name="attribute" type="{http://karaf.apache.org/xmlns/region/v1.0.0}filterAttributeType" maxOccurs="unbounded" minOccurs="0"/>
- *       &lt;/sequence>
- *       &lt;attribute name="id" type="{http://www.w3.org/2001/XMLSchema}long" />
- *       &lt;attribute name="symbolic-name" type="{http://www.w3.org/2001/XMLSchema}string" />
- *       &lt;attribute name="version" type="{http://www.w3.org/2001/XMLSchema}string" />
- *     &lt;/restriction>
- *   &lt;/complexContent>
- * &lt;/complexType>
- * </pre>
- * 
- * 
- */
-@XmlAccessorType(XmlAccessType.FIELD)
-@XmlType(name = "filterBundleType", propOrder = {
-    "attribute"
-})
-public class FilterBundleType {
-
-    protected List<FilterAttributeType> attribute;
-    @XmlAttribute
-    protected Long id;
-    @XmlAttribute(name = "symbolic-name")
-    protected String symbolicName;
-    @XmlAttribute
-    protected String version;
-
-    /**
-     * Gets the value of the attribute property.
-     * 
-     * <p>
-     * This accessor method returns a reference to the live list,
-     * not a snapshot. Therefore any modification you make to the
-     * returned list will be present inside the JAXB object.
-     * This is why there is not a <CODE>set</CODE> method for the attribute property.
-     * 
-     * <p>
-     * For example, to add a new item, do as follows:
-     * <pre>
-     *    getAttribute().add(newItem);
-     * </pre>
-     * 
-     * 
-     * <p>
-     * Objects of the following type(s) are allowed in the list
-     * {@link FilterAttributeType }
-     * 
-     * 
-     */
-    public List<FilterAttributeType> getAttribute() {
-        if (attribute == null) {
-            attribute = new ArrayList<FilterAttributeType>();
-        }
-        return this.attribute;
-    }
-
-    /**
-     * Gets the value of the id property.
-     * 
-     * @return
-     *     possible object is
-     *     {@link Long }
-     *     
-     */
-    public Long getId() {
-        return id;
-    }
-
-    /**
-     * Sets the value of the id property.
-     * 
-     * @param value
-     *     allowed object is
-     *     {@link Long }
-     *     
-     */
-    public void setId(Long value) {
-        this.id = value;
-    }
-
-    /**
-     * Gets the value of the symbolicName property.
-     * 
-     * @return
-     *     possible object is
-     *     {@link String }
-     *     
-     */
-    public String getSymbolicName() {
-        return symbolicName;
-    }
-
-    /**
-     * Sets the value of the symbolicName property.
-     * 
-     * @param value
-     *     allowed object is
-     *     {@link String }
-     *     
-     */
-    public void setSymbolicName(String value) {
-        this.symbolicName = value;
-    }
-
-    /**
-     * Gets the value of the version property.
-     * 
-     * @return
-     *     possible object is
-     *     {@link String }
-     *     
-     */
-    public String getVersion() {
-        return version;
-    }
-
-    /**
-     * Sets the value of the version property.
-     * 
-     * @param value
-     *     allowed object is
-     *     {@link String }
-     *     
-     */
-    public void setVersion(String value) {
-        this.version = value;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/1bcdb173/region/core/src/main/java/org/apache/karaf/region/persist/internal/model/FilterNamespaceType.java
----------------------------------------------------------------------
diff --git a/region/core/src/main/java/org/apache/karaf/region/persist/internal/model/FilterNamespaceType.java b/region/core/src/main/java/org/apache/karaf/region/persist/internal/model/FilterNamespaceType.java
deleted file mode 100644
index 52b937a..0000000
--- a/region/core/src/main/java/org/apache/karaf/region/persist/internal/model/FilterNamespaceType.java
+++ /dev/null
@@ -1,102 +0,0 @@
-//
-// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, vhudson-jaxb-ri-2.1-833 
-// See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a> 
-// Any modifications to this file will be lost upon recompilation of the source schema. 
-// Generated on: 2011.10.28 at 03:20:55 PM PDT 
-//
-
-
-package org.apache.karaf.region.persist.internal.model;
-
-import java.util.ArrayList;
-import java.util.List;
-import javax.xml.bind.annotation.XmlAccessType;
-import javax.xml.bind.annotation.XmlAccessorType;
-import javax.xml.bind.annotation.XmlAttribute;
-import javax.xml.bind.annotation.XmlType;
-
-
-/**
- * <p>Java class for filterNamespaceType complex type.
- * 
- * <p>The following schema fragment specifies the expected content contained within this class.
- * 
- * <pre>
- * &lt;complexType name="filterNamespaceType">
- *   &lt;complexContent>
- *     &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
- *       &lt;sequence>
- *         &lt;element name="attribute" type="{http://karaf.apache.org/xmlns/region/v1.0.0}filterAttributeType" maxOccurs="unbounded" minOccurs="0"/>
- *       &lt;/sequence>
- *       &lt;attribute name="name" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
- *     &lt;/restriction>
- *   &lt;/complexContent>
- * &lt;/complexType>
- * </pre>
- * 
- * 
- */
-@XmlAccessorType(XmlAccessType.FIELD)
-@XmlType(name = "filterNamespaceType", propOrder = {
-    "attribute"
-})
-public class FilterNamespaceType {
-
-    protected List<FilterAttributeType> attribute;
-    @XmlAttribute(required = true)
-    protected String name;
-
-    /**
-     * Gets the value of the attribute property.
-     * 
-     * <p>
-     * This accessor method returns a reference to the live list,
-     * not a snapshot. Therefore any modification you make to the
-     * returned list will be present inside the JAXB object.
-     * This is why there is not a <CODE>set</CODE> method for the attribute property.
-     * 
-     * <p>
-     * For example, to add a new item, do as follows:
-     * <pre>
-     *    getAttribute().add(newItem);
-     * </pre>
-     * 
-     * 
-     * <p>
-     * Objects of the following type(s) are allowed in the list
-     * {@link FilterAttributeType }
-     * 
-     * 
-     */
-    public List<FilterAttributeType> getAttribute() {
-        if (attribute == null) {
-            attribute = new ArrayList<FilterAttributeType>();
-        }
-        return this.attribute;
-    }
-
-    /**
-     * Gets the value of the name property.
-     * 
-     * @return
-     *     possible object is
-     *     {@link String }
-     *     
-     */
-    public String getName() {
-        return name;
-    }
-
-    /**
-     * Sets the value of the name property.
-     * 
-     * @param value
-     *     allowed object is
-     *     {@link String }
-     *     
-     */
-    public void setName(String value) {
-        this.name = value;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/1bcdb173/region/core/src/main/java/org/apache/karaf/region/persist/internal/model/FilterPackageType.java
----------------------------------------------------------------------
diff --git a/region/core/src/main/java/org/apache/karaf/region/persist/internal/model/FilterPackageType.java b/region/core/src/main/java/org/apache/karaf/region/persist/internal/model/FilterPackageType.java
deleted file mode 100644
index b4216ee..0000000
--- a/region/core/src/main/java/org/apache/karaf/region/persist/internal/model/FilterPackageType.java
+++ /dev/null
@@ -1,129 +0,0 @@
-//
-// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, vhudson-jaxb-ri-2.1-833 
-// See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a> 
-// Any modifications to this file will be lost upon recompilation of the source schema. 
-// Generated on: 2011.10.28 at 03:20:55 PM PDT 
-//
-
-
-package org.apache.karaf.region.persist.internal.model;
-
-import java.util.ArrayList;
-import java.util.List;
-import javax.xml.bind.annotation.XmlAccessType;
-import javax.xml.bind.annotation.XmlAccessorType;
-import javax.xml.bind.annotation.XmlAttribute;
-import javax.xml.bind.annotation.XmlType;
-
-
-/**
- * <p>Java class for filterPackageType complex type.
- * 
- * <p>The following schema fragment specifies the expected content contained within this class.
- * 
- * <pre>
- * &lt;complexType name="filterPackageType">
- *   &lt;complexContent>
- *     &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
- *       &lt;sequence>
- *         &lt;element name="attribute" type="{http://karaf.apache.org/xmlns/region/v1.0.0}filterAttributeType" maxOccurs="unbounded" minOccurs="0"/>
- *       &lt;/sequence>
- *       &lt;attribute name="name" type="{http://www.w3.org/2001/XMLSchema}string" />
- *       &lt;attribute name="version" type="{http://www.w3.org/2001/XMLSchema}string" />
- *     &lt;/restriction>
- *   &lt;/complexContent>
- * &lt;/complexType>
- * </pre>
- * 
- * 
- */
-@XmlAccessorType(XmlAccessType.FIELD)
-@XmlType(name = "filterPackageType", propOrder = {
-    "attribute"
-})
-public class FilterPackageType {
-
-    protected List<FilterAttributeType> attribute;
-    @XmlAttribute
-    protected String name;
-    @XmlAttribute
-    protected String version;
-
-    /**
-     * Gets the value of the attribute property.
-     * 
-     * <p>
-     * This accessor method returns a reference to the live list,
-     * not a snapshot. Therefore any modification you make to the
-     * returned list will be present inside the JAXB object.
-     * This is why there is not a <CODE>set</CODE> method for the attribute property.
-     * 
-     * <p>
-     * For example, to add a new item, do as follows:
-     * <pre>
-     *    getAttribute().add(newItem);
-     * </pre>
-     * 
-     * 
-     * <p>
-     * Objects of the following type(s) are allowed in the list
-     * {@link FilterAttributeType }
-     * 
-     * 
-     */
-    public List<FilterAttributeType> getAttribute() {
-        if (attribute == null) {
-            attribute = new ArrayList<FilterAttributeType>();
-        }
-        return this.attribute;
-    }
-
-    /**
-     * Gets the value of the name property.
-     * 
-     * @return
-     *     possible object is
-     *     {@link String }
-     *     
-     */
-    public String getName() {
-        return name;
-    }
-
-    /**
-     * Sets the value of the name property.
-     * 
-     * @param value
-     *     allowed object is
-     *     {@link String }
-     *     
-     */
-    public void setName(String value) {
-        this.name = value;
-    }
-
-    /**
-     * Gets the value of the version property.
-     * 
-     * @return
-     *     possible object is
-     *     {@link String }
-     *     
-     */
-    public String getVersion() {
-        return version;
-    }
-
-    /**
-     * Sets the value of the version property.
-     * 
-     * @param value
-     *     allowed object is
-     *     {@link String }
-     *     
-     */
-    public void setVersion(String value) {
-        this.version = value;
-    }
-
-}


[50/59] [abbrv] git commit: [KARAF-2833] Make obr independent of blueprint

Posted by gn...@apache.org.
[KARAF-2833] Make obr independent of blueprint


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

Branch: refs/heads/master
Commit: 04afd9029a156a66d9ad5a241bf69d41cff72939
Parents: 4182735
Author: Guillaume Nodet <gn...@gmail.com>
Authored: Thu Apr 10 09:54:47 2014 +0200
Committer: Guillaume Nodet <gn...@gmail.com>
Committed: Thu Apr 10 16:02:54 2014 +0200

----------------------------------------------------------------------
 .../standard/src/main/feature/feature.xml       |  1 -
 obr/pom.xml                                     | 11 ++++++
 .../karaf/obr/core/internal/osgi/Activator.java | 36 ++++++++++++++++++++
 .../resources/OSGI-INF/blueprint/blueprint.xml  | 34 ------------------
 4 files changed, 47 insertions(+), 35 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/karaf/blob/04afd902/assemblies/features/standard/src/main/feature/feature.xml
----------------------------------------------------------------------
diff --git a/assemblies/features/standard/src/main/feature/feature.xml b/assemblies/features/standard/src/main/feature/feature.xml
index 6813d27..b6f8dea 100644
--- a/assemblies/features/standard/src/main/feature/feature.xml
+++ b/assemblies/features/standard/src/main/feature/feature.xml
@@ -109,7 +109,6 @@
     </feature>
 
     <feature name="obr" description="Provide OSGi Bundle Repository (OBR) support" version="${project.version}">
-        <feature>aries-blueprint</feature>
         <bundle start-level="30">mvn:org.apache.felix/org.osgi.service.obr/${felix.obr.version}</bundle>
         <bundle start-level="30">mvn:org.apache.felix/org.apache.felix.bundlerepository/${felix.bundlerepository.version}</bundle>
         <bundle start-level="30">mvn:org.apache.karaf.obr/org.apache.karaf.obr.core/${project.version}</bundle>

http://git-wip-us.apache.org/repos/asf/karaf/blob/04afd902/obr/pom.xml
----------------------------------------------------------------------
diff --git a/obr/pom.xml b/obr/pom.xml
index e0498c7..1e9b381 100644
--- a/obr/pom.xml
+++ b/obr/pom.xml
@@ -50,6 +50,11 @@
             <scope>provided</scope>
         </dependency>
         <dependency>
+            <groupId>org.apache.karaf</groupId>
+            <artifactId>org.apache.karaf.util</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
             <groupId>org.apache.karaf.shell</groupId>
             <artifactId>org.apache.karaf.shell.core</artifactId>
             <optional>true</optional>
@@ -83,8 +88,14 @@
                         </Export-Package>
                         <Private-Package>
                             org.apache.karaf.obr.command,
+                            org.apache.karaf.obr.command.util,
                             org.apache.karaf.obr.core.internal,
+                            org.apache.karaf.obr.core.internal.osgi,
+                            org.apache.karaf.util.tracker
                         </Private-Package>
+                        <Bundle-Activator>
+                            org.apache.karaf.obr.core.internal.osgi.Activator
+                        </Bundle-Activator>
                         <Karaf-Commands>*</Karaf-Commands>
                     </instructions>
                 </configuration>

http://git-wip-us.apache.org/repos/asf/karaf/blob/04afd902/obr/src/main/java/org/apache/karaf/obr/core/internal/osgi/Activator.java
----------------------------------------------------------------------
diff --git a/obr/src/main/java/org/apache/karaf/obr/core/internal/osgi/Activator.java b/obr/src/main/java/org/apache/karaf/obr/core/internal/osgi/Activator.java
new file mode 100644
index 0000000..183508e
--- /dev/null
+++ b/obr/src/main/java/org/apache/karaf/obr/core/internal/osgi/Activator.java
@@ -0,0 +1,36 @@
+/*
+ * 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.karaf.obr.core.internal.osgi;
+
+import org.apache.felix.bundlerepository.RepositoryAdmin;
+import org.apache.karaf.obr.core.internal.ObrMBeanImpl;
+import org.apache.karaf.util.tracker.BaseActivator;
+
+public class Activator extends BaseActivator {
+
+    @Override
+    protected void doOpen() throws Exception {
+        trackService(RepositoryAdmin.class);
+    }
+
+    @Override
+    protected void doStart() throws Exception {
+        RepositoryAdmin admin = getTrackedService(RepositoryAdmin.class);
+        ObrMBeanImpl mbean = new ObrMBeanImpl(bundleContext, admin);
+        registerMBean(mbean, "type=obr");
+    }
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/04afd902/obr/src/main/resources/OSGI-INF/blueprint/blueprint.xml
----------------------------------------------------------------------
diff --git a/obr/src/main/resources/OSGI-INF/blueprint/blueprint.xml b/obr/src/main/resources/OSGI-INF/blueprint/blueprint.xml
deleted file mode 100644
index 4fbe9fb..0000000
--- a/obr/src/main/resources/OSGI-INF/blueprint/blueprint.xml
+++ /dev/null
@@ -1,34 +0,0 @@
-<?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"
-    xmlns:cm="http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.1.0"
-    xmlns:ext="http://aries.apache.org/blueprint/xmlns/blueprint-ext/v1.0.0">
-
-    <ext:property-placeholder />
-
-    <reference id="repositoryAdmin" interface="org.apache.felix.bundlerepository.RepositoryAdmin"/>
-
-    <bean id="obrMBean" class="org.apache.karaf.obr.core.internal.ObrMBeanImpl">
-        <argument ref="blueprintBundleContext"/>
-        <argument ref="repositoryAdmin"/>
-    </bean>
-
-    <service ref="obrMBean" auto-export="interfaces">
-        <service-properties>
-            <entry key="jmx.objectname" value="org.apache.karaf:type=obr,name=${karaf.name}"/>
-        </service-properties>
-    </service>
-
-</blueprint>
\ No newline at end of file


[59/59] [abbrv] git commit: [KARAF-2833] Make jndi independent of blueprint

Posted by gn...@apache.org.
[KARAF-2833] Make jndi independent of blueprint


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

Branch: refs/heads/master
Commit: 48ef3aa0146bf891fbefa70172ed5377fb6d4fd9
Parents: 85c65dd
Author: Guillaume Nodet <gn...@gmail.com>
Authored: Thu Apr 10 10:36:46 2014 +0200
Committer: Guillaume Nodet <gn...@gmail.com>
Committed: Thu Apr 10 16:03:22 2014 +0200

----------------------------------------------------------------------
 .../enterprise/src/main/feature/feature.xml     |  3 +-
 jndi/pom.xml                                    | 13 ++++-
 .../karaf/jndi/internal/osgi/Activator.java     | 53 ++++++++++++++++++++
 .../resources/OSGI-INF/blueprint/jndi-core.xml  | 53 --------------------
 4 files changed, 66 insertions(+), 56 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/karaf/blob/48ef3aa0/assemblies/features/enterprise/src/main/feature/feature.xml
----------------------------------------------------------------------
diff --git a/assemblies/features/enterprise/src/main/feature/feature.xml b/assemblies/features/enterprise/src/main/feature/feature.xml
index 823d3ba..0a57038 100644
--- a/assemblies/features/enterprise/src/main/feature/feature.xml
+++ b/assemblies/features/enterprise/src/main/feature/feature.xml
@@ -174,14 +174,13 @@
     <feature name="jndi" description="OSGi Service Registry JNDI access" version="${project.version}" resolver="(obr)">
         <details>JNDI support provided by Apache Aries JNDI ${aries.jndi.version}, including additional service, commands, and MBean.</details>
         <feature>aries-proxy</feature>
-        <feature>aries-blueprint</feature>
         <bundle start-level="30">mvn:org.apache.xbean/xbean-naming/${xbean.version}</bundle>
-        <bundle start-level="30">mvn:org.apache.karaf.jndi/org.apache.karaf.jndi.core/${project.version}</bundle>
         <bundle start-level="30">mvn:org.apache.aries.jndi/org.apache.aries.jndi.api/${aries.jndi.api.version}</bundle>
         <bundle start-level="30">mvn:org.apache.aries.jndi/org.apache.aries.jndi.core/${aries.jndi.version}</bundle>
         <bundle start-level="30">mvn:org.apache.aries.jndi/org.apache.aries.jndi.rmi/${aries.jndi.version}</bundle>
         <bundle start-level="30">mvn:org.apache.aries.jndi/org.apache.aries.jndi.url/${aries.jndi.version}</bundle>
         <bundle start-level="30">mvn:org.apache.aries.jndi/org.apache.aries.jndi.legacy.support/${aries.jndi.version}</bundle>
+        <bundle start-level="30">mvn:org.apache.karaf.jndi/org.apache.karaf.jndi.core/${project.version}</bundle>
     </feature>
 
     <feature name="jdbc" description="JDBC service and commands" version="${project.version}" resolver="(obr)">

http://git-wip-us.apache.org/repos/asf/karaf/blob/48ef3aa0/jndi/pom.xml
----------------------------------------------------------------------
diff --git a/jndi/pom.xml b/jndi/pom.xml
index f2db373..1b01030 100644
--- a/jndi/pom.xml
+++ b/jndi/pom.xml
@@ -52,6 +52,11 @@
             <artifactId>org.apache.aries.proxy.api</artifactId>
         </dependency>
         <dependency>
+            <groupId>org.apache.karaf</groupId>
+            <artifactId>org.apache.karaf.util</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
             <groupId>org.apache.karaf.shell</groupId>
             <artifactId>org.apache.karaf.shell.core</artifactId>
             <optional>true</optional>
@@ -85,9 +90,15 @@
                         </Export-Package>
                         <Private-Package>
                             org.apache.karaf.jndi.command,
-                            org.apache.karaf.jndi.internal
+                            org.apache.karaf.jndi.command.completers,
+                            org.apache.karaf.jndi.internal,
+                            org.apache.karaf.jndi.internal.osgi,
+                            org.apache.karaf.util.tracker
                         </Private-Package>
                         <Karaf-Commands>*</Karaf-Commands>
+                        <Bundle-Activator>
+                            org.apache.karaf.jndi.internal.osgi.Activator
+                        </Bundle-Activator>
                     </instructions>
                 </configuration>
             </plugin>

http://git-wip-us.apache.org/repos/asf/karaf/blob/48ef3aa0/jndi/src/main/java/org/apache/karaf/jndi/internal/osgi/Activator.java
----------------------------------------------------------------------
diff --git a/jndi/src/main/java/org/apache/karaf/jndi/internal/osgi/Activator.java b/jndi/src/main/java/org/apache/karaf/jndi/internal/osgi/Activator.java
new file mode 100644
index 0000000..5470e7e
--- /dev/null
+++ b/jndi/src/main/java/org/apache/karaf/jndi/internal/osgi/Activator.java
@@ -0,0 +1,53 @@
+/*
+ * 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.karaf.jndi.internal.osgi;
+
+import java.util.Hashtable;
+
+import javax.naming.spi.InitialContextFactory;
+
+import org.apache.aries.proxy.ProxyManager;
+import org.apache.karaf.jndi.JndiService;
+import org.apache.karaf.jndi.KarafInitialContextFactory;
+import org.apache.karaf.jndi.internal.JndiMBeanImpl;
+import org.apache.karaf.jndi.internal.JndiServiceImpl;
+import org.apache.karaf.util.tracker.BaseActivator;
+
+public class Activator extends BaseActivator {
+    @Override
+    protected void doOpen() throws Exception {
+        trackService(ProxyManager.class);
+    }
+
+    @Override
+    protected void doStart() throws Exception {
+        ProxyManager proxyManager = getTrackedService(ProxyManager.class);
+
+        register(InitialContextFactory.class, new KarafInitialContextFactory());
+
+        JndiServiceImpl service = new JndiServiceImpl();
+        service.setBundleContext(bundleContext);
+        service.setProxyManager(proxyManager);
+        Hashtable<String, String> props = new Hashtable<String, String>();
+        // bind the JNDI service itself in the JNDI context
+        props.put("osgi.jndi.service.name", "jndi");
+        register(JndiService.class, service, props);
+        JndiMBeanImpl mbean = new JndiMBeanImpl();
+        mbean.setJndiService(service);
+        registerMBean(mbean, "type=jndi");
+    }
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/48ef3aa0/jndi/src/main/resources/OSGI-INF/blueprint/jndi-core.xml
----------------------------------------------------------------------
diff --git a/jndi/src/main/resources/OSGI-INF/blueprint/jndi-core.xml b/jndi/src/main/resources/OSGI-INF/blueprint/jndi-core.xml
deleted file mode 100644
index e6be3b1..0000000
--- a/jndi/src/main/resources/OSGI-INF/blueprint/jndi-core.xml
+++ /dev/null
@@ -1,53 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-
-        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.
-    -->
-<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
-           xmlns:ext="http://aries.apache.org/blueprint/xmlns/blueprint-ext/v1.0.0"
-           default-activation="lazy">
-
-    <ext:property-placeholder placeholder-prefix="$[" placeholder-suffix="]"/>
-
-    <bean id="karafInitialContextFactory" class="org.apache.karaf.jndi.KarafInitialContextFactory"/>
-
-    <reference id="proxyManager" interface="org.apache.aries.proxy.ProxyManager"/>
-
-    <service ref="karafInitialContextFactory" interface="javax.naming.spi.InitialContextFactory"/>
-
-    <bean id="jndiService" class="org.apache.karaf.jndi.internal.JndiServiceImpl">
-        <property name="bundleContext" ref="blueprintBundleContext"/>
-        <property name="proxyManager" ref="proxyManager"/>
-    </bean>
-
-    <service ref="jndiService" interface="org.apache.karaf.jndi.JndiService">
-        <service-properties>
-            <!-- bind the JNDI service itself in the JNDI context -->
-            <entry key="osgi.jndi.service.name" value="jndi"/>
-        </service-properties>
-    </service>
-
-    <!-- Management -->
-    <bean id="jndiMBeanImpl" class="org.apache.karaf.jndi.internal.JndiMBeanImpl">
-        <property name="jndiService" ref="jndiService"/>
-    </bean>
-
-    <service ref="jndiMBeanImpl" auto-export="interfaces">
-        <service-properties>
-            <entry key="jmx.objectname" value="org.apache.karaf:type=jndi,name=$[karaf.name]"/>
-        </service-properties>
-    </service>
-
-</blueprint>
\ No newline at end of file


[10/59] [abbrv] [KARAF-2852] Merge features/core and features/command

Posted by gn...@apache.org.
http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/core/src/main/resources/org/apache/karaf/features/karaf-features-1.0.0.xsd
----------------------------------------------------------------------
diff --git a/features/core/src/main/resources/org/apache/karaf/features/karaf-features-1.0.0.xsd b/features/core/src/main/resources/org/apache/karaf/features/karaf-features-1.0.0.xsd
deleted file mode 100644
index 9536ba1..0000000
--- a/features/core/src/main/resources/org/apache/karaf/features/karaf-features-1.0.0.xsd
+++ /dev/null
@@ -1,239 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-    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.
-
--->
-<xs:schema elementFormDefault="qualified"
-    targetNamespace="http://karaf.apache.org/xmlns/features/v1.0.0"
-    xmlns:tns="http://karaf.apache.org/xmlns/features/v1.0.0"
-    xmlns:xs="http://www.w3.org/2001/XMLSchema">
-
-    <xs:annotation>
-        <xs:documentation><![CDATA[
-Karaf features mechanism. For documentation please visit the
-<a href="http://karaf.apache.org/">Karaf website</a>.
-        ]]></xs:documentation>
-    </xs:annotation>
-
-    <xs:complexType name="features">
-        <xs:annotation>
-            <xs:documentation><![CDATA[
-Root element of the Feature definition. It contains an optional attribute for
-designating the name of the repository of this feature. The Karaf shell will
-show the repository name when displaying information about the feature.
-            ]]></xs:documentation>
-        </xs:annotation>
-        <xs:choice minOccurs="0" maxOccurs="unbounded">
-            <xs:element name="repository" type="xs:anyURI">
-                <xs:annotation>
-                    <xs:documentation><![CDATA[
-Additional repositories where dependencies are stored.
-                    ]]></xs:documentation>
-                </xs:annotation>
-            </xs:element>
-            <xs:element name="feature" type="tns:feature">
-                <xs:annotation>
-                    <xs:documentation><![CDATA[
-Feature definition.
-                    ]]></xs:documentation>
-                </xs:annotation>
-            </xs:element>
-        </xs:choice>
-        <xs:attribute name="name" type="xs:string" />
-    </xs:complexType>
-
-    <xs:complexType name="feature">
-        <xs:annotation>
-            <xs:documentation><![CDATA[
-Definition of the Feature.
-            ]]></xs:documentation>
-        </xs:annotation>
-        <xs:choice minOccurs="0" maxOccurs="unbounded">
-            <xs:element name="details" minOccurs="0" type="xs:string">
-                <xs:annotation>
-                    <xs:documentation><![CDATA[
-The help text shown for this feature when using the feature:info console command.
-                    ]]>
-                    </xs:documentation>
-                </xs:annotation>
-            </xs:element>
-            <xs:element name="config" type="tns:config" />
-            <xs:element name="configfile" type="tns:configFile" />
-            <xs:element name="feature" type="tns:dependency" />
-            <xs:element name="bundle" type="tns:bundle" />
-        </xs:choice>
-        <xs:attribute name="name" type="tns:featureName" use="required" />
-        <xs:attribute name="version" type="xs:string" default="0.0.0" />
-        <xs:attribute name="description" type="xs:string" />
-        <xs:attribute name="resolver" type="tns:resolver">
-            <xs:annotation>
-                <xs:documentation><![CDATA[
-Optional alternative resolver to use for determining the list of bundles to install for a given feature.
-                ]]>
-                </xs:documentation>
-            </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="install" type="tns:install">
-            <xs:annotation>
-                <xs:documentation><![CDATA[
-If true, marks that the feature should start automatically when placed in the deploy folder.
-                ]]>
-                </xs:documentation>
-            </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="start-level" type="xs:int">
-             <xs:annotation>
-                <xs:documentation><![CDATA[
-Set this attribute to have an OSGi start level for the bundles in this feature different
-from the default start level defined in Karaf's config.properties.
-                ]]>
-                </xs:documentation>
-             </xs:annotation>
-         </xs:attribute>
-         <xs:attribute name="region" type="xs:string"/>
-    </xs:complexType>
-
-    <xs:complexType name="bundle">
-        <xs:annotation>
-            <xs:documentation><![CDATA[
-Deployable element to install.
-            ]]></xs:documentation>
-        </xs:annotation>
-        <xs:simpleContent>
-            <xs:extension base="xs:anyURI">
-                <xs:attribute name="start-level" type="xs:int">
-                    <xs:annotation>
-                        <xs:documentation><![CDATA[
-Set this attribute to have an OSGi start level for this bundle different
-from the default start level defined in Karaf's config.properties.
-
-                        ]]>
-                        </xs:documentation>
-                    </xs:annotation>
-                </xs:attribute>
-                <xs:attribute name="start" type="xs:boolean" default="true">
-                    <xs:annotation>
-                        <xs:documentation><![CDATA[
-If false, leaves the bundle in resolved state rather than the default active state.
-                        ]]>
-                        </xs:documentation>
-                    </xs:annotation>
-                </xs:attribute>
-                <xs:attribute name="dependency" type="xs:boolean">
-                    <xs:annotation>
-                        <xs:documentation><![CDATA[
-Mark this bundle as a dependency for the resolver.
-                        ]]>
-                        </xs:documentation>
-                    </xs:annotation>
-                </xs:attribute>
-            </xs:extension>
-        </xs:simpleContent>
-    </xs:complexType>
-
-    <xs:complexType name="dependency">
-        <xs:annotation>
-            <xs:documentation><![CDATA[
-Dependency of feature.
-            ]]></xs:documentation>
-        </xs:annotation>
-        <xs:simpleContent>
-            <xs:extension base="tns:featureName">
-                <xs:attribute name="version" type="xs:string" default="0.0.0" />
-            </xs:extension>
-        </xs:simpleContent>
-    </xs:complexType>
-
-    <xs:complexType name="config">
-        <xs:annotation>
-            <xs:documentation><![CDATA[
-Configuration entries which should be created during feature installation. This
-configuration may be used with OSGi Configuration Admin. The element content is
-read in as a properties file.
-            ]]></xs:documentation>
-        </xs:annotation>
-        <xs:simpleContent>
-            <xs:extension base="xs:string">
-                <xs:attribute name="name" type="xs:string" use="required" />
-            </xs:extension>
-        </xs:simpleContent>
-    </xs:complexType>
-
-    <xs:complexType name="configFile">
-        <xs:annotation>
-            <xs:documentation><![CDATA[
-Additional configuration files which should be created during feature installation.
-            ]]></xs:documentation>
-        </xs:annotation>
-        <xs:simpleContent>
-            <xs:extension base="xs:anyURI">
-                <xs:attribute name="finalname" type="xs:string" use="required">
-                    <xs:annotation>
-                        <xs:documentation><![CDATA[
-The final destination path and name for the configuration file (relative to the KARAF_BASE).
-                        ]]></xs:documentation>
-                    </xs:annotation>
-                </xs:attribute>
-                <xs:attribute name="override" type="xs:boolean">
-                    <xs:annotation>
-                        <xs:documentation><![CDATA[
-If the configFile already exists at the finalname location, whether or not to replace it.
-                        ]]></xs:documentation>
-                    </xs:annotation>
-                </xs:attribute>
-
-            </xs:extension>
-        </xs:simpleContent>
-    </xs:complexType>
-
-    <xs:simpleType name="featureName">
-        <xs:annotation>
-            <xs:documentation><![CDATA[
-Feature name should be non empty string.
-            ]]></xs:documentation>
-        </xs:annotation>
-        <xs:restriction base="xs:string">
-            <xs:minLength value="1" />
-        </xs:restriction>
-    </xs:simpleType>
-
-    <xs:simpleType name="resolver">
-        <xs:annotation>
-            <xs:documentation><![CDATA[
-Resolver to use. Karaf will look for OSGi service which has following properties:
-objectClass: org.apache.karaf.features.Resolver
-name: the value
-            ]]></xs:documentation>
-        </xs:annotation>
-        <xs:restriction base="xs:string">
-            <xs:minLength value="1" />
-        </xs:restriction>
-    </xs:simpleType>
-    <xs:simpleType name="install">
-        <xs:annotation>
-            <xs:documentation><![CDATA[
-Installation mode. Can be either manual or auto. Specifies whether the feature should be automatically installed when
-dropped inside the deploy folder. Note: This attribute doesn't affect feature descriptors that are installed from the
-command line or as part of the org.apache.karaf.features.cfg.
-            ]]></xs:documentation>
-        </xs:annotation>
-        <xs:restriction base="xs:string">
-            <xs:minLength value="1" />
-        </xs:restriction>
-    </xs:simpleType>
-    <xs:element name="features" type="tns:features" />
-
-</xs:schema>

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/core/src/main/resources/org/apache/karaf/features/karaf-features-1.1.0.xsd
----------------------------------------------------------------------
diff --git a/features/core/src/main/resources/org/apache/karaf/features/karaf-features-1.1.0.xsd b/features/core/src/main/resources/org/apache/karaf/features/karaf-features-1.1.0.xsd
deleted file mode 100644
index 7138573..0000000
--- a/features/core/src/main/resources/org/apache/karaf/features/karaf-features-1.1.0.xsd
+++ /dev/null
@@ -1,237 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-    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.
-
--->
-<xs:schema elementFormDefault="qualified"
-    targetNamespace="http://karaf.apache.org/xmlns/features/v1.1.0"
-    xmlns:tns="http://karaf.apache.org/xmlns/features/v1.1.0"
-    xmlns:xs="http://www.w3.org/2001/XMLSchema">
-
-    <xs:annotation>
-        <xs:documentation><![CDATA[
-Karaf features mechanism. For documentation please visit the
-<a href="http://karaf.apache.org/">Karaf website</a>.
-        ]]></xs:documentation>
-    </xs:annotation>
-
-    <xs:complexType name="features">
-        <xs:annotation>
-            <xs:documentation><![CDATA[
-Root element of Feature definition. It contains an required attribute for
-designating from which repository this feature should be loaded. The Karaf
-shell will show the repository name when displaying information about the feature.
-            ]]></xs:documentation>
-        </xs:annotation>
-        <xs:choice minOccurs="0" maxOccurs="unbounded">
-            <xs:element name="repository" type="xs:anyURI">
-                <xs:annotation>
-                    <xs:documentation><![CDATA[
-Additional repositories where dependencies are stored.
-                    ]]></xs:documentation>
-                </xs:annotation>
-            </xs:element>
-            <xs:element name="feature" type="tns:feature">
-                <xs:annotation>
-                    <xs:documentation><![CDATA[
-Feature definition.
-                    ]]></xs:documentation>
-                </xs:annotation>
-            </xs:element>
-        </xs:choice>
-        <xs:attribute name="name" type="xs:string" use="required"/>
-    </xs:complexType>
-
-    <xs:complexType name="feature">
-        <xs:annotation>
-            <xs:documentation><![CDATA[
-Definition of the Feature.
-            ]]></xs:documentation>
-        </xs:annotation>
-        <xs:choice minOccurs="0" maxOccurs="unbounded">
-            <xs:element name="details" minOccurs="0" type="xs:string">
-                <xs:annotation>
-                    <xs:documentation><![CDATA[
-The help text shown for this feature when using feature:info console command.
-                    ]]>
-                    </xs:documentation>
-                </xs:annotation>
-            </xs:element>
-            <xs:element name="config" type="tns:config" />
-            <xs:element name="configfile" type="tns:configFile" />
-            <xs:element name="feature" type="tns:dependency" />
-            <xs:element name="bundle" type="tns:bundle" />
-        </xs:choice>
-        <xs:attribute name="name" type="tns:featureName" use="required" />
-        <xs:attribute name="version" type="xs:string" default="0.0.0" />
-        <xs:attribute name="description" type="xs:string" />
-        <xs:attribute name="resolver" type="tns:resolver">
-            <xs:annotation>
-                <xs:documentation><![CDATA[
-Optional alternative resolver to use for determining the list of bundles to install for a given feature.
-                ]]>
-                </xs:documentation>
-            </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="install" type="tns:install">
-            <xs:annotation>
-                <xs:documentation><![CDATA[
-Marks if the feaute will be automatically started when thrown to the deploy folder.
-                ]]>
-                </xs:documentation>
-            </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="start-level" type="xs:int">
-             <xs:annotation>
-                <xs:documentation><![CDATA[
-Set this attribute to have an OSGi start level for this feature different
-from the default start level defined in Karaf's config.properties.
-                ]]>
-                </xs:documentation>
-             </xs:annotation>
-         </xs:attribute>
-    </xs:complexType>
-
-    <xs:complexType name="bundle">
-        <xs:annotation>
-            <xs:documentation><![CDATA[
-Deployable element to install.
-            ]]></xs:documentation>
-        </xs:annotation>
-        <xs:simpleContent>
-            <xs:extension base="xs:anyURI">
-                <xs:attribute name="start-level" type="xs:int">
-                    <xs:annotation>
-                        <xs:documentation><![CDATA[
-Set this attribute to have an OSGi start level for this bundle different
-from the default start level defined in the Karaf's config.properties.
-                        ]]>
-                        </xs:documentation>
-                    </xs:annotation>
-                </xs:attribute>
-                <xs:attribute name="start" type="xs:boolean" default="true">
-                    <xs:annotation>
-                        <xs:documentation><![CDATA[
-If false, leaves bundle in resolved state rather than the default active state.
-                        ]]>
-                        </xs:documentation>
-                    </xs:annotation>
-                </xs:attribute>
-                <xs:attribute name="dependency" type="xs:boolean">
-                    <xs:annotation>
-                        <xs:documentation><![CDATA[
-Mark this bundle as a dependency for the resolver.
-                        ]]>
-                        </xs:documentation>
-                    </xs:annotation>
-                </xs:attribute>
-            </xs:extension>
-        </xs:simpleContent>
-    </xs:complexType>
-
-    <xs:complexType name="dependency">
-        <xs:annotation>
-            <xs:documentation><![CDATA[
-Dependency of feature.
-            ]]></xs:documentation>
-        </xs:annotation>
-        <xs:simpleContent>
-            <xs:extension base="tns:featureName">
-                <xs:attribute name="version" type="xs:string" default="0.0.0" />
-            </xs:extension>
-        </xs:simpleContent>
-    </xs:complexType>
-
-    <xs:complexType name="config">
-        <xs:annotation>
-            <xs:documentation><![CDATA[
-Configuration entries which should be created during feature installation. This
-configuration may be used with OSGi Configuration Admin. The element content is
-read in as a properties file.
-            ]]></xs:documentation>
-        </xs:annotation>
-        <xs:simpleContent>
-            <xs:extension base="xs:string">
-                <xs:attribute name="name" type="xs:string" use="required" />
-            </xs:extension>
-        </xs:simpleContent>
-    </xs:complexType>
-
-    <xs:complexType name="configFile">
-        <xs:annotation>
-            <xs:documentation><![CDATA[
-Additional configuration files which should be created during feature installation.
-            ]]></xs:documentation>
-        </xs:annotation>
-        <xs:simpleContent>
-            <xs:extension base="xs:anyURI">
-                <xs:attribute name="finalname" type="xs:string" use="required">
-                    <xs:annotation>
-                        <xs:documentation><![CDATA[
-The final destination path and name for the configuration file.
-                        ]]></xs:documentation>
-                    </xs:annotation>
-                </xs:attribute>
-                <xs:attribute name="override" type="xs:boolean">
-                    <xs:annotation>
-                        <xs:documentation><![CDATA[
-If the configFile already exists at the finalname location, whether or not to replace it.
-                        ]]></xs:documentation>
-                    </xs:annotation>
-                </xs:attribute>
-
-            </xs:extension>
-        </xs:simpleContent>
-    </xs:complexType>
-
-    <xs:simpleType name="featureName">
-        <xs:annotation>
-            <xs:documentation><![CDATA[
-Feature name should be non empty string.
-            ]]></xs:documentation>
-        </xs:annotation>
-        <xs:restriction base="xs:string">
-            <xs:minLength value="1" />
-        </xs:restriction>
-    </xs:simpleType>
-
-    <xs:simpleType name="resolver">
-        <xs:annotation>
-            <xs:documentation><![CDATA[
-Resolver to use. Karaf will look for OSGi service which have following properties:
-objectClass: org.apache.karaf.features.Resolver
-name: the value
-            ]]></xs:documentation>
-        </xs:annotation>
-        <xs:restriction base="xs:string">
-            <xs:minLength value="1" />
-        </xs:restriction>
-    </xs:simpleType>
-    <xs:simpleType name="install">
-        <xs:annotation>
-            <xs:documentation><![CDATA[
-Installation mode. Can be either manual or auto. Specifies whether the feature should be automatically installed when
-dropped inside the deploy folder. Note: This attribute doesn't affect feature descriptors that are installed from the
-command line or as part of the org.apache.karaf.features.cfg.
-            ]]></xs:documentation>
-        </xs:annotation>
-        <xs:restriction base="xs:string">
-            <xs:minLength value="1" />
-        </xs:restriction>
-    </xs:simpleType>
-    <xs:element name="features" type="tns:features" />
-
-</xs:schema>

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/core/src/main/resources/org/apache/karaf/features/karaf-features-1.2.0.xsd
----------------------------------------------------------------------
diff --git a/features/core/src/main/resources/org/apache/karaf/features/karaf-features-1.2.0.xsd b/features/core/src/main/resources/org/apache/karaf/features/karaf-features-1.2.0.xsd
deleted file mode 100644
index dbc4bfa..0000000
--- a/features/core/src/main/resources/org/apache/karaf/features/karaf-features-1.2.0.xsd
+++ /dev/null
@@ -1,254 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-    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.
-
--->
-<xs:schema elementFormDefault="qualified"
-    targetNamespace="http://karaf.apache.org/xmlns/features/v1.2.0"
-    xmlns:tns="http://karaf.apache.org/xmlns/features/v1.2.0"
-    xmlns:xs="http://www.w3.org/2001/XMLSchema">
-
-    <xs:annotation>
-        <xs:documentation><![CDATA[
-Karaf features mechanism. For documentation please visit the
-<a href="http://karaf.apache.org/">Karaf website</a>.
-        ]]></xs:documentation>
-    </xs:annotation>
-
-    <xs:complexType name="features">
-        <xs:annotation>
-            <xs:documentation><![CDATA[
-Root element of Feature definition. It contains an required attribute for
-designating from which repository this feature should be loaded. The Karaf
-shell will show the repository name when displaying information about the feature.
-            ]]></xs:documentation>
-        </xs:annotation>
-        <xs:choice minOccurs="0" maxOccurs="unbounded">
-            <xs:element name="repository" type="xs:anyURI">
-                <xs:annotation>
-                    <xs:documentation><![CDATA[
-Additional repositories where dependencies are stored.
-                    ]]></xs:documentation>
-                </xs:annotation>
-            </xs:element>
-            <xs:element name="feature" type="tns:feature">
-                <xs:annotation>
-                    <xs:documentation><![CDATA[
-Feature definition.
-                    ]]></xs:documentation>
-                </xs:annotation>
-            </xs:element>
-        </xs:choice>
-        <xs:attribute name="name" type="xs:string" use="required"/>
-    </xs:complexType>
-
-    <xs:complexType name="feature">
-        <xs:annotation>
-            <xs:documentation><![CDATA[
-Definition of the Feature.
-            ]]></xs:documentation>
-        </xs:annotation>
-        <xs:choice minOccurs="0" maxOccurs="unbounded">
-            <xs:element name="details" minOccurs="0" type="xs:string">
-                <xs:annotation>
-                    <xs:documentation><![CDATA[
-The help text shown for this feature when using feature:info console command.
-                    ]]>
-                    </xs:documentation>
-                </xs:annotation>
-            </xs:element>
-            <xs:element name="config" type="tns:config" />
-            <xs:element name="configfile" type="tns:configFile" />
-            <xs:element name="feature" type="tns:dependency" />
-            <xs:element name="bundle" type="tns:bundle" />
-            <xs:element name="conditional" type="tns:conditional" />
-        </xs:choice>
-        <xs:attribute name="name" type="tns:featureName" use="required" />
-        <xs:attribute name="version" type="xs:string" default="0.0.0" />
-        <xs:attribute name="description" type="xs:string" />
-        <xs:attribute name="resolver" type="tns:resolver">
-            <xs:annotation>
-                <xs:documentation><![CDATA[
-Optional alternative resolver to use for determining the list of bundles to install for a given feature.
-                ]]>
-                </xs:documentation>
-            </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="install" type="tns:install">
-            <xs:annotation>
-                <xs:documentation><![CDATA[
-Marks if the feaute will be automatically started when thrown to the deploy folder.
-                ]]>
-                </xs:documentation>
-            </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="start-level" type="xs:int">
-             <xs:annotation>
-                <xs:documentation><![CDATA[
-Set this attribute to have an OSGi start level for this feature different
-from the default start level defined in Karaf's config.properties.
-                ]]>
-                </xs:documentation>
-             </xs:annotation>
-         </xs:attribute>
-    </xs:complexType>
-
-    <xs:complexType name="conditional">
-        <xs:annotation>
-            <xs:documentation><![CDATA[
-Definition of the Conditional.
-            ]]></xs:documentation>
-        </xs:annotation>
-        <xs:choice minOccurs="0" maxOccurs="unbounded">
-            <xs:element name="config" type="tns:config" />
-            <xs:element name="configfile" type="tns:configFile" />
-            <xs:element name="feature" type="tns:dependency" />
-            <xs:element name="bundle" type="tns:bundle" />
-            <xs:element name="condition" type="tns:dependency" minOccurs="0" maxOccurs="1" />
-        </xs:choice>
-    </xs:complexType>
-
-
-    <xs:complexType name="bundle">
-        <xs:annotation>
-            <xs:documentation><![CDATA[
-Deployable element to install.
-            ]]></xs:documentation>
-        </xs:annotation>
-        <xs:simpleContent>
-            <xs:extension base="xs:anyURI">
-                <xs:attribute name="start-level" type="xs:int">
-                    <xs:annotation>
-                        <xs:documentation><![CDATA[
-Set this attribute to have an OSGi start level for this bundle different
-from the default start level defined in the Karaf's config.properties.
-                        ]]>
-                        </xs:documentation>
-                    </xs:annotation>
-                </xs:attribute>
-                <xs:attribute name="start" type="xs:boolean" default="true">
-                    <xs:annotation>
-                        <xs:documentation><![CDATA[
-If false, leaves bundle in resolved state rather than the default active state.
-                        ]]>
-                        </xs:documentation>
-                    </xs:annotation>
-                </xs:attribute>
-                <xs:attribute name="dependency" type="xs:boolean">
-                    <xs:annotation>
-                        <xs:documentation><![CDATA[
-Mark this bundle as a dependency for the resolver.
-                        ]]>
-                        </xs:documentation>
-                    </xs:annotation>
-                </xs:attribute>
-            </xs:extension>
-        </xs:simpleContent>
-    </xs:complexType>
-
-    <xs:complexType name="dependency">
-        <xs:annotation>
-            <xs:documentation><![CDATA[
-Dependency of feature.
-            ]]></xs:documentation>
-        </xs:annotation>
-        <xs:simpleContent>
-            <xs:extension base="tns:featureName">
-                <xs:attribute name="version" type="xs:string" default="0.0.0" />
-            </xs:extension>
-        </xs:simpleContent>
-    </xs:complexType>
-
-    <xs:complexType name="config">
-        <xs:annotation>
-            <xs:documentation><![CDATA[
-Configuration entries which should be created during feature installation. This
-configuration may be used with OSGi Configuration Admin. The element content is
-read in as a properties file.
-            ]]></xs:documentation>
-        </xs:annotation>
-        <xs:simpleContent>
-            <xs:extension base="xs:string">
-                <xs:attribute name="name" type="xs:string" use="required" />
-            </xs:extension>
-        </xs:simpleContent>
-    </xs:complexType>
-
-    <xs:complexType name="configFile">
-        <xs:annotation>
-            <xs:documentation><![CDATA[
-Additional configuration files which should be created during feature installation.
-            ]]></xs:documentation>
-        </xs:annotation>
-        <xs:simpleContent>
-            <xs:extension base="xs:anyURI">
-                <xs:attribute name="finalname" type="xs:string" use="required">
-                    <xs:annotation>
-                        <xs:documentation><![CDATA[
-The final destination path and name for the configuration file.
-                        ]]></xs:documentation>
-                    </xs:annotation>
-                </xs:attribute>
-                <xs:attribute name="override" type="xs:boolean">
-                    <xs:annotation>
-                        <xs:documentation><![CDATA[
-If the configFile already exists at the finalname location, whether or not to replace it.
-                        ]]></xs:documentation>
-                    </xs:annotation>
-                </xs:attribute>
-
-            </xs:extension>
-        </xs:simpleContent>
-    </xs:complexType>
-
-    <xs:simpleType name="featureName">
-        <xs:annotation>
-            <xs:documentation><![CDATA[
-Feature name should be non empty string.
-            ]]></xs:documentation>
-        </xs:annotation>
-        <xs:restriction base="xs:string">
-            <xs:minLength value="1" />
-        </xs:restriction>
-    </xs:simpleType>
-
-    <xs:simpleType name="resolver">
-        <xs:annotation>
-            <xs:documentation><![CDATA[
-Resolver to use. Karaf will look for OSGi service which have following properties:
-objectClass: org.apache.karaf.features.Resolver
-name: the value
-            ]]></xs:documentation>
-        </xs:annotation>
-        <xs:restriction base="xs:string">
-            <xs:minLength value="1" />
-        </xs:restriction>
-    </xs:simpleType>
-    <xs:simpleType name="install">
-        <xs:annotation>
-            <xs:documentation><![CDATA[
-Installation mode. Can be either manual or auto. Specifies whether the feature should be automatically installed when
-dropped inside the deploy folder. Note: This attribute doesn't affect feature descriptors that are installed from the
-command line or as part of the org.apache.karaf.features.cfg.
-            ]]></xs:documentation>
-        </xs:annotation>
-        <xs:restriction base="xs:string">
-            <xs:minLength value="1" />
-        </xs:restriction>
-    </xs:simpleType>
-    <xs:element name="features" type="tns:features" />
-
-</xs:schema>

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/core/src/main/resources/org/apache/karaf/features/karaf-features-1.3.0.xsd
----------------------------------------------------------------------
diff --git a/features/core/src/main/resources/org/apache/karaf/features/karaf-features-1.3.0.xsd b/features/core/src/main/resources/org/apache/karaf/features/karaf-features-1.3.0.xsd
deleted file mode 100644
index 60ec8d2..0000000
--- a/features/core/src/main/resources/org/apache/karaf/features/karaf-features-1.3.0.xsd
+++ /dev/null
@@ -1,280 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-    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.
-
--->
-<xs:schema elementFormDefault="qualified"
-    targetNamespace="http://karaf.apache.org/xmlns/features/v1.3.0"
-    xmlns:tns="http://karaf.apache.org/xmlns/features/v1.3.0"
-    xmlns:xs="http://www.w3.org/2001/XMLSchema">
-
-    <xs:annotation>
-        <xs:documentation><![CDATA[
-Karaf features mechanism. For documentation please visit the
-<a href="http://karaf.apache.org/">Karaf website</a>.
-        ]]></xs:documentation>
-    </xs:annotation>
-
-    <xs:complexType name="features">
-        <xs:annotation>
-            <xs:documentation><![CDATA[
-Root element of Feature definition. It contains an required attribute for
-designating from which repository this feature should be loaded. The Karaf
-shell will show the repository name when displaying information about the feature.
-            ]]></xs:documentation>
-        </xs:annotation>
-        <xs:choice minOccurs="0" maxOccurs="unbounded">
-            <xs:element name="repository" type="xs:anyURI">
-                <xs:annotation>
-                    <xs:documentation><![CDATA[
-Additional repositories where dependencies are stored.
-                    ]]></xs:documentation>
-                </xs:annotation>
-            </xs:element>
-            <xs:element name="feature" type="tns:feature">
-                <xs:annotation>
-                    <xs:documentation><![CDATA[
-Feature definition.
-                    ]]></xs:documentation>
-                </xs:annotation>
-            </xs:element>
-        </xs:choice>
-        <xs:attribute name="name" type="xs:string" use="required"/>
-    </xs:complexType>
-
-    <xs:complexType name="feature">
-        <xs:annotation>
-            <xs:documentation><![CDATA[
-Definition of the Feature.
-            ]]></xs:documentation>
-        </xs:annotation>
-        <xs:choice minOccurs="0" maxOccurs="unbounded">
-            <xs:element name="details" minOccurs="0" type="xs:string">
-                <xs:annotation>
-                    <xs:documentation><![CDATA[
-The help text shown for this feature when using feature:info console command.
-                    ]]>
-                    </xs:documentation>
-                </xs:annotation>
-            </xs:element>
-            <xs:element name="config" type="tns:config" />
-            <xs:element name="configfile" type="tns:configFile" />
-            <xs:element name="feature" type="tns:dependency" />
-            <xs:element name="bundle" type="tns:bundle" />
-            <xs:element name="conditional" type="tns:conditional" />
-            <xs:element name="requirement" type="tns:requirement" />
-            <xs:element name="capability" type="tns:capability" />
-        </xs:choice>
-        <xs:attribute name="name" type="tns:featureName" use="required" />
-        <xs:attribute name="version" type="xs:string" default="0.0.0" />
-        <xs:attribute name="description" type="xs:string" />
-        <xs:attribute name="resolver" type="tns:resolver">
-            <xs:annotation>
-                <xs:documentation><![CDATA[
-Optional alternative resolver to use for determining the list of bundles to install for a given feature.
-                ]]>
-                </xs:documentation>
-            </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="install" type="tns:install">
-            <xs:annotation>
-                <xs:documentation><![CDATA[
-Marks if the feaute will be automatically started when thrown to the deploy folder.
-                ]]>
-                </xs:documentation>
-            </xs:annotation>
-        </xs:attribute>
-        <xs:attribute name="start-level" type="xs:int">
-             <xs:annotation>
-                <xs:documentation><![CDATA[
-Set this attribute to have an OSGi start level for this feature different
-from the default start level defined in Karaf's config.properties.
-                ]]>
-                </xs:documentation>
-             </xs:annotation>
-         </xs:attribute>
-    </xs:complexType>
-
-    <xs:complexType name="conditional">
-        <xs:annotation>
-            <xs:documentation><![CDATA[
-Definition of the Conditional.
-            ]]></xs:documentation>
-        </xs:annotation>
-        <xs:choice minOccurs="0" maxOccurs="unbounded">
-            <xs:element name="config" type="tns:config" />
-            <xs:element name="configfile" type="tns:configFile" />
-            <xs:element name="feature" type="tns:dependency" />
-            <xs:element name="bundle" type="tns:bundle" />
-            <xs:element name="condition" type="tns:dependency" minOccurs="0" maxOccurs="1" />
-        </xs:choice>
-    </xs:complexType>
-
-
-    <xs:complexType name="bundle">
-        <xs:annotation>
-            <xs:documentation><![CDATA[
-Deployable element to install.
-            ]]></xs:documentation>
-        </xs:annotation>
-        <xs:simpleContent>
-            <xs:extension base="xs:anyURI">
-                <xs:attribute name="start-level" type="xs:int">
-                    <xs:annotation>
-                        <xs:documentation><![CDATA[
-Set this attribute to have an OSGi start level for this bundle different
-from the default start level defined in the Karaf's config.properties.
-                        ]]>
-                        </xs:documentation>
-                    </xs:annotation>
-                </xs:attribute>
-                <xs:attribute name="start" type="xs:boolean" default="true">
-                    <xs:annotation>
-                        <xs:documentation><![CDATA[
-If false, leaves bundle in resolved state rather than the default active state.
-                        ]]>
-                        </xs:documentation>
-                    </xs:annotation>
-                </xs:attribute>
-                <xs:attribute name="dependency" type="xs:boolean">
-                    <xs:annotation>
-                        <xs:documentation><![CDATA[
-Mark this bundle as a dependency for the resolver.
-                        ]]>
-                        </xs:documentation>
-                    </xs:annotation>
-                </xs:attribute>
-            </xs:extension>
-        </xs:simpleContent>
-    </xs:complexType>
-
-    <xs:complexType name="dependency">
-        <xs:annotation>
-            <xs:documentation><![CDATA[
-Dependency of feature.
-            ]]></xs:documentation>
-        </xs:annotation>
-        <xs:simpleContent>
-            <xs:extension base="tns:featureName">
-                <xs:attribute name="version" type="xs:string" default="0.0.0" />
-            </xs:extension>
-        </xs:simpleContent>
-    </xs:complexType>
-
-    <xs:complexType name="config">
-        <xs:annotation>
-            <xs:documentation><![CDATA[
-Configuration entries which should be created during feature installation. This
-configuration may be used with OSGi Configuration Admin. The element content is
-read in as a properties file.
-            ]]></xs:documentation>
-        </xs:annotation>
-        <xs:simpleContent>
-            <xs:extension base="xs:string">
-                <xs:attribute name="name" type="xs:string" use="required" />
-            </xs:extension>
-        </xs:simpleContent>
-    </xs:complexType>
-
-    <xs:complexType name="configFile">
-        <xs:annotation>
-            <xs:documentation><![CDATA[
-Additional configuration files which should be created during feature installation.
-            ]]></xs:documentation>
-        </xs:annotation>
-        <xs:simpleContent>
-            <xs:extension base="xs:anyURI">
-                <xs:attribute name="finalname" type="xs:string" use="required">
-                    <xs:annotation>
-                        <xs:documentation><![CDATA[
-The final destination path and name for the configuration file.
-                        ]]></xs:documentation>
-                    </xs:annotation>
-                </xs:attribute>
-                <xs:attribute name="override" type="xs:boolean">
-                    <xs:annotation>
-                        <xs:documentation><![CDATA[
-If the configFile already exists at the finalname location, whether or not to replace it.
-                        ]]></xs:documentation>
-                    </xs:annotation>
-                </xs:attribute>
-
-            </xs:extension>
-        </xs:simpleContent>
-    </xs:complexType>
-
-    <xs:complexType name="requirement">
-        <xs:annotation>
-            <xs:documentation><![CDATA[
-Additional requirements of this feature.
-            ]]></xs:documentation>
-        </xs:annotation>
-        <xs:simpleContent>
-            <xs:extension base="xs:string">
-            </xs:extension>
-        </xs:simpleContent>
-    </xs:complexType>
-
-    <xs:complexType name="capability">
-        <xs:annotation>
-            <xs:documentation><![CDATA[
-Additional capability of this feature.
-            ]]></xs:documentation>
-        </xs:annotation>
-        <xs:simpleContent>
-            <xs:extension base="xs:string">
-            </xs:extension>
-        </xs:simpleContent>
-    </xs:complexType>
-
-    <xs:simpleType name="featureName">
-        <xs:annotation>
-            <xs:documentation><![CDATA[
-Feature name should be non empty string.
-            ]]></xs:documentation>
-        </xs:annotation>
-        <xs:restriction base="xs:string">
-            <xs:minLength value="1" />
-        </xs:restriction>
-    </xs:simpleType>
-
-    <xs:simpleType name="resolver">
-        <xs:annotation>
-            <xs:documentation><![CDATA[
-Resolver to use. Karaf will look for OSGi service which have following properties:
-objectClass: org.apache.karaf.features.Resolver
-name: the value
-            ]]></xs:documentation>
-        </xs:annotation>
-        <xs:restriction base="xs:string">
-            <xs:minLength value="1" />
-        </xs:restriction>
-    </xs:simpleType>
-    <xs:simpleType name="install">
-        <xs:annotation>
-            <xs:documentation><![CDATA[
-Installation mode. Can be either manual or auto. Specifies whether the feature should be automatically installed when
-dropped inside the deploy folder. Note: This attribute doesn't affect feature descriptors that are installed from the
-command line or as part of the org.apache.karaf.features.cfg.
-            ]]></xs:documentation>
-        </xs:annotation>
-        <xs:restriction base="xs:string">
-            <xs:minLength value="1" />
-        </xs:restriction>
-    </xs:simpleType>
-    <xs:element name="features" type="tns:features" />
-
-</xs:schema>

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/core/src/test/java/org/apache/karaf/features/ConditionalTest.java
----------------------------------------------------------------------
diff --git a/features/core/src/test/java/org/apache/karaf/features/ConditionalTest.java b/features/core/src/test/java/org/apache/karaf/features/ConditionalTest.java
deleted file mode 100644
index d5e7e46..0000000
--- a/features/core/src/test/java/org/apache/karaf/features/ConditionalTest.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * 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.karaf.features;
-
-import junit.framework.TestCase;
-import org.apache.karaf.features.internal.service.RepositoryImpl;
-
-
-public class ConditionalTest extends TestCase {
-
-    public void testLoad() throws Exception {
-        RepositoryImpl r = new RepositoryImpl(getClass().getResource("internal/service/f06.xml").toURI());
-        // Check repo
-        Feature[] features = r.getFeatures();
-        assertNotNull(features);
-        assertEquals(1, features.length);
-        Feature feature = features[0];
-
-        assertNotNull(feature.getConditional());
-        assertEquals(1,feature.getConditional().size());
-
-        Conditional conditional = feature.getConditional().get(0);
-        assertNotNull(conditional.getCondition());
-        assertEquals(1,conditional.getCondition().size());
-        Dependency dependency = conditional.getCondition().get(0);
-        assertNotNull(dependency);
-        assertEquals(dependency.getName(),"http");
-        assertNotNull(conditional.getBundles());
-        assertEquals(1, feature.getConditional().get(0).getBundles().size());
-
-        String wrapperName = "my6/1.5.3-beta-3".replaceAll("[^A-Za-z0-9 ]", "_");
-    }
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/core/src/test/java/org/apache/karaf/features/FeatureTest.java
----------------------------------------------------------------------
diff --git a/features/core/src/test/java/org/apache/karaf/features/FeatureTest.java b/features/core/src/test/java/org/apache/karaf/features/FeatureTest.java
deleted file mode 100644
index b7d4c27..0000000
--- a/features/core/src/test/java/org/apache/karaf/features/FeatureTest.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * 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.karaf.features;
-
-import junit.framework.TestCase;
-
-public class FeatureTest extends TestCase {
-	
-	public void testValueOf() {
-		Feature feature = org.apache.karaf.features.internal.model.Feature.valueOf("name" + org.apache.karaf.features.internal.model.Feature.SPLIT_FOR_NAME_AND_VERSION + "version");
-		assertEquals(feature.getName(), "name");
-		assertEquals(feature.getVersion(), "version");
-		feature = org.apache.karaf.features.internal.model.Feature.valueOf("name");
-		assertEquals(feature.getName(), "name");
-		assertEquals(feature.getVersion(), org.apache.karaf.features.internal.model.Feature.DEFAULT_VERSION);
-	}
-	
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/core/src/test/java/org/apache/karaf/features/FeaturesServiceTest.java
----------------------------------------------------------------------
diff --git a/features/core/src/test/java/org/apache/karaf/features/FeaturesServiceTest.java b/features/core/src/test/java/org/apache/karaf/features/FeaturesServiceTest.java
deleted file mode 100644
index 9f7e67b..0000000
--- a/features/core/src/test/java/org/apache/karaf/features/FeaturesServiceTest.java
+++ /dev/null
@@ -1,430 +0,0 @@
-/*
- * 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.karaf.features;
-
-import static org.easymock.EasyMock.eq;
-import static org.easymock.EasyMock.expect;
-import static org.easymock.EasyMock.replay;
-import static org.easymock.EasyMock.reset;
-import static org.easymock.EasyMock.verify;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
-import java.io.File;
-import java.io.FileWriter;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.PrintWriter;
-import java.net.MalformedURLException;
-import java.net.URI;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.EnumSet;
-import java.util.List;
-import java.util.concurrent.CopyOnWriteArraySet;
-
-import org.apache.karaf.features.internal.service.FeaturesServiceImpl;
-import org.apache.karaf.features.internal.service.StateStorage;
-import org.easymock.EasyMock;
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Test;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.BundleContext;
-
-public class FeaturesServiceTest extends TestBase {
-    private static final String FEATURE_WITH_INVALID_BUNDLE = "<features name='test' xmlns='http://karaf.apache.org/xmlns/features/v1.0.0'>"
-            + "  <feature name='f1'><bundle>%s</bundle><bundle>zfs:unknown</bundle></feature>"
-            + "  <feature name='f2'><bundle>%s</bundle></feature>"
-            + "</features>";
-
-    File dataFile;
-
-    @Before
-    public void setUp() throws IOException {
-        dataFile = File.createTempFile("features", null, null);
-    }
-    
-    private URI createTempRepo(String repoContent, Object ... variables) throws IOException {
-        File tmp = File.createTempFile("karaf", ".feature");
-        PrintWriter pw = new PrintWriter(new FileWriter(tmp));
-        pw.printf(repoContent, variables);
-        pw.close();
-        return tmp.toURI();
-    }
-
-    /*
-       TODO: migrate those tests
-
-    @Test
-    public void testInstallFeature() throws Exception {
-        URI uri = createTempRepo(
-                "<features name='test' xmlns='http://karaf.apache.org/xmlns/features/v1.0.0'>" 
-                + "  <feature name='f1'><bundle start='true'>bundle-f1</bundle></feature>"
-                + "</features>");
-
-        BundleManager bundleManager = EasyMock.createMock(BundleManager.class);
-        Bundle installedBundle = createDummyBundle(12345L, "bundle-f1", headers());
-        FeaturesServiceImpl svc = testAddRepository("bundle-f1", uri, bundleManager, installedBundle);
-        
-        reset(bundleManager);
-        
-        expect(bundleManager.installBundleIfNeeded(eq("bundle-f1"), eq(0), eq((String)null))).andReturn(new BundleInstallerResult(installedBundle, true));
-        expect(bundleManager.getDataFile(EasyMock.anyObject(String.class))).andReturn(dataFile);
-        ignoreRefreshes(bundleManager);
-        replay(bundleManager);
-        svc.installFeature("f1", org.apache.karaf.features.internal.model.Feature.DEFAULT_VERSION, EnumSet.of(FeaturesService.Option.NoAutoRefreshBundles));
-        verify(bundleManager);
-        
-        Feature[] installed = svc.listInstalledFeatures();
-        assertEquals(1, installed.length);
-        assertEquals("f1", installed[0].getName());
-    }
-
-    private FeaturesServiceImpl testAddRepository(String name, URI uri, BundleManager bundleManager,
-            Bundle installedBundle) throws IOException, BundleException, Exception {
-        expect(bundleManager.getDataFile(EasyMock.anyObject(String.class))).andReturn(dataFile);
-        expect(bundleManager.installBundleIfNeeded(eq(name), eq(0), eq((String)null))).andReturn(new BundleInstallerResult(installedBundle, true)).anyTimes();
-
-        replay(bundleManager);
-        FeaturesServiceImpl svc = new FeaturesServiceImpl(bundleManager);
-        svc.addRepository(uri);
-        Repository[] repositories = svc.listRepositories();
-        verify(bundleManager);
-
-        assertNotNull(repositories);
-        assertEquals(1, repositories.length);
-        assertNotNull(repositories[0]);
-        Feature[] features = repositories[0].getFeatures();
-        assertNotNull(features);
-        assertEquals(1, features.length);
-        assertNotNull(features[0]);
-        assertEquals("f1", features[0].getName());
-        assertNotNull(features[0].getDependencies());
-        assertEquals(0, features[0].getDependencies().size());
-        assertNotNull(features[0].getBundles());
-        assertEquals(1, features[0].getBundles().size());
-        assertEquals(name, features[0].getBundles().get(0).getLocation());
-        assertTrue(features[0].getBundles().get(0).isStart());
-        return svc;
-    }
-
-    @SuppressWarnings("unchecked")
-    @Test
-    public void testUninstallFeatureWithTwoVersions() throws Exception {
-        URI uri  = createTempRepo("<features name='test' xmlns='http://karaf.apache.org/xmlns/features/v1.0.0'>"
-                + "  <feature name='f1' version='0.1'><bundle>bundle-0.1</bundle></feature>"
-                + "  <feature name='f1' version='0.2'><bundle>bundle-0.1</bundle></feature>" 
-                + "</features>");
-
-        Bundle bundlef101 = createDummyBundle(12345L, "bundle-0.1", headers());
-
-        BundleManager bundleManager = EasyMock.createMock(BundleManager.class);
-        BundleContext bundleContext = EasyMock.createMock(BundleContext.class);
-        expect(bundleManager.getDataFile(EasyMock.anyObject(String.class))).andReturn(dataFile).anyTimes();
-        expect(bundleManager.installBundleIfNeeded("bundle-0.1", 0, null)).andReturn(new BundleInstallerResult(bundlef101, true));
-        expect(bundleManager.installBundleIfNeeded("bundle-0.1", 0, null)).andReturn(new BundleInstallerResult(bundlef101, false));
-        expect(bundleManager.getBundleContext()).andReturn(bundleContext);
-        ignoreRefreshes(bundleManager);
-        bundleManager.uninstall(Collections.EMPTY_LIST, true);
-        EasyMock.expectLastCall().times(2);
-        
-        
-        replay(bundleManager);
-        FeaturesServiceImpl svc = new FeaturesServiceImpl(bundleManager);
-        svc.addRepository(uri);
-
-        try {
-            svc.uninstallFeature("f1");
-            fail("Uninstall should have failed as feature is not installed");
-        } catch (Exception e) {
-            // ok
-        }
-
-        svc.installFeature("f1", "0.1", EnumSet.of(FeaturesService.Option.NoAutoRefreshBundles));
-        svc.installFeature("f1", "0.2", EnumSet.of(FeaturesService.Option.NoAutoRefreshBundles));
-
-        try {
-            svc.uninstallFeature("f1");
-            fail("Uninstall should have failed as feature is installed in multiple versions");
-        } catch (Exception e) {
-            // ok
-        }
-
-        svc.uninstallFeature("f1", "0.1");
-        svc.uninstallFeature("f1");
-        verify(bundleManager);
-    }    
-    
-    @Test
-    public void testAddAndRemoveRepository() throws Exception {
-        URI uri = createTempRepo("<features name='test' xmlns='http://karaf.apache.org/xmlns/features/v1.0.0'>"
-                + "  <feature name='f1' version='0.1'><bundle>bundle-f1-0.1</bundle></feature>"
-                + "</features>");
-
-        BundleManager bundleManager = EasyMock.createMock(BundleManager.class);
-        expect(bundleManager.getDataFile(EasyMock.<String>anyObject())).andReturn(dataFile).anyTimes();
-
-        replay(bundleManager);
-        FeaturesServiceImpl svc = new FeaturesServiceImpl(bundleManager);
-        EasyMock.verify(bundleManager);
-
-        svc.addRepository(uri);                                                     
-        svc.removeRepository(uri);
-        verify(bundleManager);
-    }
-
-    // Tests install of a Repository that includes a feature
-    // with a feature dependency
-    // The dependant feature is in the same repository
-    // Tests uninstall of features
-    @SuppressWarnings("unchecked")
-    @Test
-    public void testInstallFeatureWithDependantFeatures() throws Exception {
-        URI uri = createTempRepo("<features name='test' xmlns='http://karaf.apache.org/xmlns/features/v1.0.0'>"
-                                 + "  <feature name='f1' version='0.1'><feature version='0.1'>f2</feature><bundle>bundle-f1-0.1</bundle></feature>"
-                                 + "  <feature name='f2' version='0.1'><bundle>bundle-f2-0.1</bundle></feature>"
-                                 + "</features>");
-
-        BundleManager bundleManager = EasyMock.createMock(BundleManager.class);
-        BundleContext bundleContext = EasyMock.createMock(BundleContext.class);
-        Bundle bundlef101 = createDummyBundle(12345L, "bundle-f1-0.1", headers());
-        Bundle bundlef201 = createDummyBundle(54321L, "bundle-f2-0.1", headers());
-        expect(bundleManager.getDataFile(EasyMock.<String> anyObject())).andReturn(dataFile).anyTimes();
-        expect(bundleManager.installBundleIfNeeded("bundle-f1-0.1", 0, null))
-            .andReturn(new BundleInstallerResult(bundlef101, true));
-        expect(bundleManager.installBundleIfNeeded("bundle-f2-0.1", 0, null))
-            .andReturn(new BundleInstallerResult(bundlef201, true));
-        expect(bundleManager.getBundleContext()).andReturn(bundleContext).anyTimes();
-        expect(bundleContext.getBundle(12345)).andReturn(bundlef101).anyTimes();
-        ignoreRefreshes(bundleManager);
-        bundleManager.uninstall(Collections.EMPTY_LIST, true);
-       
-        EasyMock.expectLastCall().anyTimes();
-        replay(bundleManager);
-        
-        FeaturesServiceImpl svc = new FeaturesServiceImpl(bundleManager);
-        svc.addRepository(uri);
-        svc.installFeature("f1", "0.1");
-        svc.uninstallFeature("f1", "0.1");
-        verify(bundleManager);
-
-    }
-
-    @SuppressWarnings("unchecked")
-    private BundleManager prepareBundleManagerForInstallUninstall(String bundleUri, String bundlename) throws Exception {
-        BundleManager bundleManager = EasyMock.createMock(BundleManager.class);
-        BundleContext bundleContext = EasyMock.createMock(BundleContext.class);
-        Bundle installedBundle = createDummyBundle(12345L, bundlename, headers());
-        expect(bundleManager.getDataFile(EasyMock.<String>anyObject())).andReturn(dataFile).anyTimes();
-        expect(bundleManager.installBundleIfNeeded(bundleUri, 0, null)).andReturn(new BundleInstallerResult(installedBundle, true));
-        expect(bundleManager.getBundleContext()).andReturn(bundleContext);
-        ignoreRefreshes(bundleManager);
-        bundleManager.uninstall(Collections.EMPTY_LIST, true);
-        EasyMock.expectLastCall().times(2);
-        return bundleManager;
-    }
-
-    @Test
-    public void testInstallFeatureWithDependantFeaturesAndVersionWithoutPreinstall() throws Exception {
-        URI uri = createTempRepo("<features name='test' xmlns='http://karaf.apache.org/xmlns/features/v1.0.0'>"
-                + "  <feature name='f1' version='0.1'><feature version='0.1'>f2</feature></feature>"
-                + "  <feature name='f2' version='0.1'><bundle>bundle-0.1</bundle></feature>"
-                + "  <feature name='f2' version='0.2'><bundle>bundle-0.2</bundle></feature>"
-                + "</features>");
-
-        BundleManager bundleManager = prepareBundleManagerForInstallUninstall("bundle-0.1", "bundle-0.1");
-
-        replay(bundleManager);
-        FeaturesServiceImpl svc = new FeaturesServiceImpl(bundleManager);
-        svc.addRepository(uri);
-        svc.installFeature("f1", "0.1");
-        svc.uninstallFeature("f1", "0.1");
-        svc.uninstallFeature("f2", "0.1");
-        verify(bundleManager);
-    }
-
-    @Test
-    public void testInstallFeatureWithDependantFeaturesAndNoVersionWithoutPreinstall() throws Exception {
-        URI uri = createTempRepo("<features name='test' xmlns='http://karaf.apache.org/xmlns/features/v1.0.0'>"
-                + "  <feature name='f1' version='0.1'><feature>f2</feature></feature>"
-                + "  <feature name='f2' version='0.1'><bundle>bundle-0.1</bundle></feature>"
-                + "  <feature name='f2' version='0.2'><bundle>bundle-0.2</bundle></feature>"
-                + "</features>");
-
-        BundleManager bundleManager = prepareBundleManagerForInstallUninstall("bundle-0.2", "bundle-0.2");
-
-        replay(bundleManager);
-        FeaturesServiceImpl svc = new FeaturesServiceImpl(bundleManager);
-        svc.addRepository(uri);
-        svc.installFeature("f1", "0.1");
-        svc.uninstallFeature("f1", "0.1");
-        svc.uninstallFeature("f2", "0.2");
-        verify(bundleManager);
-    }
-
-    @SuppressWarnings("unchecked")
-    @Test
-    public void testInstallFeatureWithDependantFeaturesAndRangeWithoutPreinstall() throws Exception {
-        URI uri = createTempRepo("<features name='test' xmlns='http://karaf.apache.org/xmlns/features/v1.0.0'>"
-                + "  <feature name='f1' version='0.1'><feature version='[0.1,0.3)'>f2</feature></feature>"
-                + "  <feature name='f2' version='0.1'><bundle>bundle-0.1</bundle></feature>"
-                + "  <feature name='f2' version='0.2'><bundle>bundle-0.2</bundle></feature>"
-                + "</features>");
-
-        BundleManager bundleManager = EasyMock.createMock(BundleManager.class);
-        BundleContext bundleContext = EasyMock.createMock(BundleContext.class);
-        Bundle bundleVer02 = createDummyBundle(54321L, "bundleVer02", headers());
-        expect(bundleManager.getDataFile(EasyMock.<String>anyObject())).andReturn(dataFile).anyTimes();
-        expect(bundleManager.installBundleIfNeeded("bundle-0.2", 0, null)).andReturn(new BundleInstallerResult(bundleVer02, true));
-        expect(bundleManager.getBundleContext()).andReturn(bundleContext);
-        ignoreRefreshes(bundleManager);
-        bundleManager.uninstall(Collections.EMPTY_LIST, true);
-
-        EasyMock.expectLastCall().times(2);
-
-        replay(bundleManager);
-        FeaturesServiceImpl svc = new FeaturesServiceImpl(bundleManager);
-        svc.addRepository(uri);
-        svc.installFeature("f1", "0.1");
-        svc.uninstallFeature("f1", "0.1");
-        svc.uninstallFeature("f2", "0.2");
-        verify(bundleManager);
-    }
-
-    @SuppressWarnings("unchecked")
-    @Test
-    public void testInstallFeatureWithDependantFeaturesAndRangeWithPreinstall() throws Exception {
-        String bundleVer01Uri = "bundle-0.1";
-        String bundleVer02Uri = "bundle-0.2";
-
-        URI uri = createTempRepo("<features name='test' xmlns='http://karaf.apache.org/xmlns/features/v1.0.0'>"
-                + "<feature name='f1' version='0.1'><feature version='[0.1,0.3)'>f2</feature></feature>"
-                + "  <feature name='f2' version='0.1'><bundle>%s</bundle></feature>"
-                + "  <feature name='f2' version='0.2'><bundle>%s</bundle></feature>"
-                + "</features>", bundleVer01Uri, bundleVer02Uri);
-        
-        BundleContext bundleContext = EasyMock.createMock(BundleContext.class);
-        expect(bundleContext.getBundles()).andReturn(new Bundle[0]);
-        replay(bundleContext);
-
-        FeaturesServiceImpl svc = new FeaturesServiceImpl(null, bundleContext, new Storage(), null, null, null, null);
-        svc.addRepository(uri);
-        svc.installFeature("f2", "0.1");
-        svc.installFeature("f1", "0.1");
-        svc.uninstallFeature("f1", "0.1");
-        svc.uninstallFeature("f2", "0.1");
-
-        verify(bundleContext);
-    }
-    */
-
-    @Test
-    public void testGetFeaturesShouldHandleDifferentVersionPatterns() throws Exception {
-        URI uri = createTempRepo("<features name='test' xmlns='http://karaf.apache.org/xmlns/features/v1.0.0'>"
-                + "  <feature name='f1' version='0.1'><feature version='[0.1,0.3)'>f2</feature></feature>"
-                + "  <feature name='f2' version='0.1'><bundle>bundle1</bundle></feature>"
-                + "  <feature name='f2' version='0.2'><bundle>bundle2</bundle></feature>"
-                + "</features>");
-
-        FeaturesServiceImpl svc = new FeaturesServiceImpl(null, null, new Storage(), null, null, null, null, null, null, null);
-        svc.addRepository(uri);
-
-        assertEquals(feature("f2", "0.2"), svc.getFeature("f2", "[0.1,0.3)"));
-        assertEquals(feature("f2", "0.2"), svc.getFeature("f2", "0.0.0"));
-        assertEquals(feature("f2", "0.2"), svc.getFeature("f2", "0.2"));
-        assertNull(svc.getFeature("f2", "0.3"));
-    }
-
-    @Test
-    public void testInstallBatchFeatureWithFailure() throws Exception {
-        String bundle1Uri = "file:bundle1";
-        String bundle2Uri = "file:bundle2";
-
-        URI uri = createTempRepo(FEATURE_WITH_INVALID_BUNDLE, bundle1Uri, bundle2Uri);
-        
-        BundleContext bundleContext = EasyMock.createMock(BundleContext.class);
-        expect(bundleContext.getBundles()).andReturn(new Bundle[0]);
-        replay(bundleContext);
-
-        FeaturesServiceImpl svc = new FeaturesServiceImpl(null, bundleContext, new Storage(), null, null, null, null, null, null, null);
-        svc.addRepository(uri);
-        try {
-            List<String> features = new ArrayList<String>();
-            for (Feature feature : svc.listFeatures()) {
-                features.add(feature.getId());
-            }
-            Collections.reverse(features);
-            svc.installFeatures(new CopyOnWriteArraySet<String>(features),
-                                EnumSet.noneOf(FeaturesService.Option.class));
-            fail("Call should have thrown an exception");
-        } catch (MalformedURLException e) {
-        }
-        verify(bundleContext);
-    }
-
-    /**
-     * This test checks schema validation of submited uri.
-     */
-    @Test
-    public void testSchemaValidation() throws Exception {
-        URI uri = createTempRepo("<features name='test' xmlns='http://karaf.apache.org/xmlns/features/v1.0.0'>"
-                + "  <featur><bundle>somebundle</bundle></featur></features>");
-
-        FeaturesServiceImpl svc = new FeaturesServiceImpl(null, null, new Storage(), null, null, null, null, null, null, null);
-        try {
-            svc.addRepository(uri);
-            fail("exception expected");
-        } catch (Exception e) {
-            assertTrue(e.getMessage().contains("Unable to validate"));
-        }
-    }
-
-    /**
-     * This test checks feature service behavior with old, non namespaced descriptor.
-     */
-    @Test
-    public void testLoadOldFeatureFile() throws Exception {
-        URI uri = createTempRepo("<features name='test' xmlns='http://karaf.apache.org/xmlns/features/v1.0.0'>"
-                + "  <feature name='f1'><bundle>file:bundle1</bundle><bundle>file:bundle2</bundle></feature>"
-                + "</features>");
-
-        FeaturesServiceImpl svc = new FeaturesServiceImpl(null, null, new Storage(), null, null, null, null, null, null, null);
-        svc.addRepository(uri);
-        Feature feature = svc.getFeature("f1");
-        Assert.assertNotNull("No feature named fi found", feature);        
-        List<BundleInfo> bundles = feature.getBundles();
-        Assert.assertEquals(2, bundles.size());
-    }
-
-    static class Storage extends StateStorage {
-        @Override
-        protected InputStream getInputStream() throws IOException {
-            return null;
-        }
-        @Override
-        protected OutputStream getOutputStream() throws IOException {
-            return null;
-        }
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/core/src/test/java/org/apache/karaf/features/RepositoryTest.java
----------------------------------------------------------------------
diff --git a/features/core/src/test/java/org/apache/karaf/features/RepositoryTest.java b/features/core/src/test/java/org/apache/karaf/features/RepositoryTest.java
deleted file mode 100644
index 164dc79..0000000
--- a/features/core/src/test/java/org/apache/karaf/features/RepositoryTest.java
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- * 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.karaf.features;
-
-import java.net.URI;
-
-import junit.framework.TestCase;
-import org.apache.karaf.features.internal.resolver.FeatureResource;
-import org.apache.karaf.features.internal.service.RepositoryImpl;
-import org.osgi.resource.Resource;
-
-
-public class RepositoryTest extends TestCase {
-
-    public void testLoad() throws Exception {
-        RepositoryImpl r = new RepositoryImpl(getClass().getResource("repo1.xml").toURI());
-        // Check repo
-        URI[] repos = r.getRepositories();
-        assertNotNull(repos);
-        assertEquals(1, repos.length);
-        assertEquals(URI.create("urn:r1"), repos[0]);
-        // Check features
-        Feature[] features = r.getFeatures();
-        assertNotNull(features);
-        assertEquals(3, features.length);
-        assertNotNull(features[0]);
-        assertEquals("f1", features[0].getName());
-        assertNotNull(features[0].getConfigurations());
-        assertEquals(1, features[0].getConfigurations().size());
-        assertNotNull(features[0].getConfigurations().get("c1"));
-        assertEquals(1, features[0].getConfigurations().get("c1").size());
-        assertEquals("v", features[0].getConfigurations().get("c1").get("k"));
-        assertNotNull(features[0].getDependencies());
-        assertEquals(0, features[0].getDependencies().size());
-        assertNotNull(features[0].getBundles());
-        assertEquals(2, features[0].getBundles().size());
-        assertEquals("b1", features[0].getBundles().get(0).getLocation());
-        assertEquals("b2", features[0].getBundles().get(1).getLocation());
-        assertNotNull(features[1]);
-        assertEquals("f2", features[1].getName());
-        assertNotNull(features[1].getConfigurations());
-        assertEquals(0, features[1].getConfigurations().size());
-        assertNotNull(features[1].getDependencies());
-        assertEquals(1, features[1].getDependencies().size());
-        assertEquals("f1" + org.apache.karaf.features.internal.model.Feature.SPLIT_FOR_NAME_AND_VERSION + org.apache.karaf.features.internal.model.Feature.DEFAULT_VERSION, features[1].getDependencies().get(0).toString());
-        assertNotNull(features[1].getBundles());
-        assertEquals(1, features[1].getBundles().size());
-        assertEquals("b3", features[1].getBundles().get(0).getLocation());
-        assertEquals("f3", features[2].getName());
-        assertNotNull(features[2].getConfigurationFiles());
-        assertEquals(1, features[2].getConfigurationFiles().size());
-        assertEquals("cf1", features[2].getConfigurationFiles().get(0).getFinalname());
-        assertEquals(true, features[2].getConfigurationFiles().get(0).isOverride());
-        assertEquals("cfloc", features[2].getConfigurationFiles().get(0).getLocation());
-    }
-
-    public void testLoadFormattedRepo() throws Exception {
-        RepositoryImpl r = new RepositoryImpl(getClass().getResource("repo2.xml").toURI());
-        // Check repo
-        URI[] repos = r.getRepositories();
-        assertNotNull(repos);
-        assertEquals(1, repos.length);
-        assertEquals(URI.create("urn:r1"), repos[0]);
-        // Check features
-        Feature[] features = r.getFeatures();
-        assertNotNull(features);
-        assertEquals(3, features.length);
-        assertNotNull(features[0]);
-        assertEquals("f1", features[0].getName());
-        assertNotNull(features[0].getConfigurations());
-        assertEquals(1, features[0].getConfigurations().size());
-        assertNotNull(features[0].getConfigurations().get("c1"));
-        assertEquals(1, features[0].getConfigurations().get("c1").size());
-        assertEquals("v", features[0].getConfigurations().get("c1").get("k"));
-        assertNotNull(features[0].getDependencies());
-        assertEquals(0, features[0].getDependencies().size());
-        assertNotNull(features[0].getBundles());
-        assertEquals(2, features[0].getBundles().size());
-        assertEquals("b1", features[0].getBundles().get(0).getLocation());
-        assertEquals("b2", features[0].getBundles().get(1).getLocation());
-        assertNotNull(features[1]);
-        assertEquals("f2", features[1].getName());
-        assertNotNull(features[1].getConfigurations());
-        assertEquals(0, features[1].getConfigurations().size());
-        assertNotNull(features[1].getDependencies());
-        assertEquals(1, features[1].getDependencies().size());
-        assertEquals("f1" + org.apache.karaf.features.internal.model.Feature.SPLIT_FOR_NAME_AND_VERSION + org.apache.karaf.features.internal.model.Feature.DEFAULT_VERSION, features[1].getDependencies().get(0).toString());
-        assertNotNull(features[1].getBundles());
-        assertEquals(1, features[1].getBundles().size());
-        assertEquals("b3", features[1].getBundles().get(0).getLocation());
-        assertEquals("f3", features[2].getName());
-        assertNotNull(features[2].getConfigurationFiles());
-        assertEquals(1, features[2].getConfigurationFiles().size());
-        assertEquals("cf1", features[2].getConfigurationFiles().get(0).getFinalname());
-        assertEquals(true, features[2].getConfigurationFiles().get(0).isOverride());
-        assertEquals("cfloc", features[2].getConfigurationFiles().get(0).getLocation());
-    }
-
-    public void testLoadRepoWithCapabilitiesAndRequirement() throws Exception {
-        RepositoryImpl r = new RepositoryImpl(getClass().getResource("repo3.xml").toURI());
-        // Check features
-        Feature[] features = r.getFeatures();
-        assertNotNull(features);
-        assertEquals(1, features.length);
-        assertNotNull(features[0]);
-        assertEquals("f1", features[0].getName());
-        assertEquals(1, features[0].getCapabilities().size());
-        assertEquals("cap", features[0].getCapabilities().get(0).getValue().trim());
-        assertEquals(1, features[0].getRequirements().size());
-        assertEquals("req", features[0].getRequirements().get(0).getValue().trim());
-
-        Resource res = FeatureResource.build(features[0], null, null);
-        assertEquals(1, res.getCapabilities("cap").size());
-        assertEquals(1, res.getRequirements("req").size());
-    }
-
-    public void testShowWrongUriInException() throws Exception {
-        String uri = "src/test/resources/org/apache/karaf/shell/features/repo1.xml";
-        RepositoryImpl r = new RepositoryImpl(new URI(uri));
-        try {
-            r.load();
-        } catch (Exception e) {
-            assertTrue(e.getMessage().contains(uri));
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/core/src/test/java/org/apache/karaf/features/TestBase.java
----------------------------------------------------------------------
diff --git a/features/core/src/test/java/org/apache/karaf/features/TestBase.java b/features/core/src/test/java/org/apache/karaf/features/TestBase.java
deleted file mode 100644
index ac8f3d9..0000000
--- a/features/core/src/test/java/org/apache/karaf/features/TestBase.java
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * 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.karaf.features;
-
-import java.util.Arrays;
-import java.util.Dictionary;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Hashtable;
-import java.util.Map;
-import java.util.Set;
-
-import org.easymock.EasyMock;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.startlevel.BundleStartLevel;
-
-import static java.util.Arrays.asList;
-import static org.easymock.EasyMock.expect;
-import static org.easymock.EasyMock.replay;
-
-public class TestBase {
-    public Bundle createDummyBundle(long id, final String symbolicName, Dictionary<String,String> headers) {
-        Bundle bundle = EasyMock.createNiceMock(Bundle.class);
-        
-        // Be aware that this means all bundles are treated as different
-        expect(bundle.compareTo(EasyMock.<Bundle>anyObject())).andReturn(1).anyTimes();
-
-        expect(bundle.getBundleId()).andReturn(id).anyTimes();
-        expect(bundle.getSymbolicName()).andReturn(symbolicName).anyTimes();
-        expect(bundle.getHeaders()).andReturn(headers).anyTimes();
-        BundleStartLevel sl = EasyMock.createMock(BundleStartLevel.class);
-        expect(sl.isPersistentlyStarted()).andReturn(true).anyTimes();
-        expect(bundle.adapt(BundleStartLevel.class)).andReturn(sl).anyTimes();
-        replay(bundle, sl);
-        return bundle;
-    }
-    
-    public Dictionary<String, String> headers(String ... keyAndHeader) {
-        Hashtable<String, String> headersTable = new Hashtable<String, String>();
-        int c=0;
-        while (c < keyAndHeader.length) {
-            String key = keyAndHeader[c++];
-            String value = keyAndHeader[c++];
-            headersTable.put(key, value);
-        }
-        return headersTable;
-    }
-    
-    public Map<String, Map<String, Feature>> features(Feature ... features) {
-        final Map<String, Map<String, Feature>> featuresMap = new HashMap<String, Map<String,Feature>>();
-        for (Feature feature : features) {
-            Map<String, Feature> featureVersion = getOrCreate(featuresMap, feature);
-            featureVersion.put(feature.getVersion(), feature);
-        }
-        return featuresMap;
-    }
-    
-    private Map<String, Feature> getOrCreate(final Map<String, Map<String, Feature>> featuresMap, Feature feature) {
-        Map<String, Feature> featureVersion = featuresMap.get(feature.getName());
-        if (featureVersion == null) {
-            featureVersion = new HashMap<String, Feature>();
-            featuresMap.put(feature.getName(), featureVersion);
-        }
-        return featureVersion;
-    }
-
-    public Feature feature(String name) {
-        return feature(name, null);
-    }
-
-    public Feature feature(String name, String version) {
-        return new org.apache.karaf.features.internal.model.Feature(name, version);
-    }
-    
-    public Set<Bundle> setOf(Bundle ... elements) {
-        return new HashSet<Bundle>(Arrays.asList(elements));
-    }
-    
-    public Set<Long> setOf(Long ... elements) {
-        return new HashSet<Long>(Arrays.asList(elements));
-    }
-    
-    public Set<String> setOf(String ... elements) {
-        return new HashSet<String>(asList(elements));
-    }
-    
-    public Set<Feature> setOf(Feature ... elements) {
-        return new HashSet<Feature>(Arrays.asList(elements));
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/core/src/test/java/org/apache/karaf/features/internal/service/BootFeaturesInstallerTest.java
----------------------------------------------------------------------
diff --git a/features/core/src/test/java/org/apache/karaf/features/internal/service/BootFeaturesInstallerTest.java b/features/core/src/test/java/org/apache/karaf/features/internal/service/BootFeaturesInstallerTest.java
deleted file mode 100644
index 31f4f29..0000000
--- a/features/core/src/test/java/org/apache/karaf/features/internal/service/BootFeaturesInstallerTest.java
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * 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.karaf.features.internal.service;
-
-import static java.util.Arrays.asList;
-import static org.easymock.EasyMock.expect;
-import static org.easymock.EasyMock.replay;
-import static org.junit.Assert.fail;
-
-import java.net.URI;
-import java.util.EnumSet;
-
-import org.apache.karaf.features.Feature;
-import org.apache.karaf.features.FeaturesService.Option;
-import org.apache.karaf.features.TestBase;
-import org.easymock.EasyMock;
-import org.junit.Assert;
-import org.junit.Test;
-
-public class BootFeaturesInstallerTest extends TestBase {
-
-    @Test
-    @SuppressWarnings("unchecked")
-    public void testParser() {
-        BootFeaturesInstaller installer = new BootFeaturesInstaller(null, null, "", "", false);
-        Assert.assertEquals(asList(setOf("test1", "test2"),setOf("test3")), installer.parseBootFeatures("(test1, test2), test3"));
-        Assert.assertEquals(asList(setOf("test1", "test2", "test3")), installer.parseBootFeatures("test1, test2, test3"));
-    }
-    
-    @Test
-    public void testDefaultBootFeatures() throws Exception  {
-        FeaturesServiceImpl impl = EasyMock.createMock(FeaturesServiceImpl.class);
-
-        impl.installFeatures(setOf("config", "standard", "region"), EnumSet.of(Option.NoFailOnFeatureNotFound));
-        EasyMock.expectLastCall();
-
-        impl.bootDone();
-        EasyMock.expectLastCall();
-
-        replay(impl);
-        BootFeaturesInstaller bootFeatures = new BootFeaturesInstaller(null, impl, "", "config,standard,region", false);
-        bootFeatures.installBootFeatures();
-        EasyMock.verify(impl);        
-    }
-
-    @Test
-    public void testStagedBoot() throws Exception  {
-        FeaturesServiceImpl impl = EasyMock.createStrictMock(FeaturesServiceImpl.class);
-
-        impl.installFeatures(setOf("transaction"), EnumSet.of(Option.NoFailOnFeatureNotFound));
-        EasyMock.expectLastCall();
-        impl.installFeatures(setOf("ssh"), EnumSet.of(Option.NoFailOnFeatureNotFound));
-        EasyMock.expectLastCall();
-
-        impl.bootDone();
-        EasyMock.expectLastCall();
-
-        replay(impl);
-        BootFeaturesInstaller bootFeatures = new BootFeaturesInstaller(null, impl , "", "(transaction), ssh", false);
-        bootFeatures.installBootFeatures();
-        EasyMock.verify(impl);        
-    }
-
-    @Test
-    public void testStartDoesNotFailWithOneInvalidUri() throws Exception {
-        FeaturesServiceImpl impl = EasyMock.createStrictMock(FeaturesServiceImpl.class);
-        impl.addRepository(URI.create("mvn:inexistent/features/1.0/xml/features"));
-        EasyMock.expectLastCall().andThrow(new IllegalArgumentException());
-
-        impl.bootDone();
-        EasyMock.expectLastCall();
-
-        replay(impl);
-        BootFeaturesInstaller bootFeatures = new BootFeaturesInstaller(null, impl, "mvn:inexistent/features/1.0/xml/features", "", false);
-        bootFeatures.installBootFeatures();
-        EasyMock.verify(impl);
-    }
-
-}


[27/59] [abbrv] [KARAF-2852] Merge instance/core and instance/command

Posted by gn...@apache.org.
http://git-wip-us.apache.org/repos/asf/karaf/blob/7c2db062/instance/core/src/test/java/org/apache/karaf/instance/core/management/internal/InstanceToTableMapperTest.java
----------------------------------------------------------------------
diff --git a/instance/core/src/test/java/org/apache/karaf/instance/core/management/internal/InstanceToTableMapperTest.java b/instance/core/src/test/java/org/apache/karaf/instance/core/management/internal/InstanceToTableMapperTest.java
deleted file mode 100644
index c9541d3..0000000
--- a/instance/core/src/test/java/org/apache/karaf/instance/core/management/internal/InstanceToTableMapperTest.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * 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.karaf.instance.core.management.internal;
-
-import java.util.Collection;
-import java.util.Collections;
-
-import javax.management.openmbean.CompositeData;
-import javax.management.openmbean.TabularData;
-
-import junit.framework.TestCase;
-
-import org.apache.karaf.instance.core.Instance;
-import org.apache.karaf.instance.core.internal.InstanceToTableMapper;
-import org.easymock.EasyMock;
-import org.junit.Assert;
-
-public class InstanceToTableMapperTest extends TestCase {
-    public void testJMXInstance() throws Exception {
-        Instance instance = EasyMock.createMock(Instance.class);
-        EasyMock.expect(instance.getPid()).andReturn(1712);
-        EasyMock.expect(instance.getName()).andReturn("MyInstance");
-        EasyMock.expect(instance.isRoot()).andReturn(false);
-        EasyMock.expect(instance.getSshPort()).andReturn(0);
-        EasyMock.expect(instance.getRmiRegistryPort()).andReturn(0);
-        EasyMock.expect(instance.getRmiServerPort()).andReturn(0);
-        EasyMock.expect(instance.getState()).andThrow(new Exception("gotcha"));
-        EasyMock.expect(instance.getLocation()).andReturn("somewhere");
-        EasyMock.expect(instance.getJavaOpts()).andReturn("someopts");
-        EasyMock.replay(instance);
-        
-        TabularData td = InstanceToTableMapper.tableFrom(Collections.singletonList(instance));
-        Collection<?> keys = (Collection<?>) td.keySet().iterator().next();
-        Assert.assertEquals("MyInstance", keys.iterator().next());
-        
-        CompositeData cd = td.get(keys.toArray());
-        Assert.assertEquals(1712, cd.get("Pid"));
-        Assert.assertEquals("MyInstance", cd.get("Name"));
-        Assert.assertEquals(false, cd.get("Is Root"));
-        Assert.assertEquals(0, cd.get("SSH Port"));
-        Assert.assertEquals(0, cd.get("RMI Registry Port"));
-        Assert.assertEquals(0, cd.get("RMI Server Port"));
-        Assert.assertEquals("Error", cd.get("State"));
-        Assert.assertEquals("somewhere", cd.get("Location"));
-        Assert.assertEquals("someopts", cd.get("JavaOpts"));
-    }
-
-    public void testJMXInstance2() throws Exception {
-        Instance instance = EasyMock.createMock(Instance.class);
-        EasyMock.expect(instance.getPid()).andReturn(1712);
-        EasyMock.expect(instance.getName()).andReturn("MyInstance");
-        EasyMock.expect(instance.isRoot()).andReturn(true);
-        EasyMock.expect(instance.getSshPort()).andReturn(0);
-        EasyMock.expect(instance.getRmiRegistryPort()).andReturn(0);
-        EasyMock.expect(instance.getRmiServerPort()).andReturn(0);
-        EasyMock.expect(instance.getState()).andReturn("Started");
-        EasyMock.expect(instance.getLocation()).andReturn(null);
-        EasyMock.expect(instance.getJavaOpts()).andReturn(null);
-        EasyMock.replay(instance);
-        
-        TabularData td = InstanceToTableMapper.tableFrom(Collections.singletonList(instance));        
-        Collection<?> keys = (Collection<?>) td.keySet().iterator().next();
-        Assert.assertEquals("MyInstance", keys.iterator().next());
-        
-        CompositeData cd = td.get(keys.toArray());
-        Assert.assertEquals(1712, cd.get("Pid"));
-        Assert.assertEquals("MyInstance", cd.get("Name"));
-        Assert.assertEquals(true, cd.get("Is Root"));
-        Assert.assertEquals(0, cd.get("SSH Port"));
-        Assert.assertEquals(0, cd.get("RMI Registry Port"));
-        Assert.assertEquals(0, cd.get("RMI Server Port"));
-        Assert.assertEquals("Started", cd.get("State"));
-        Assert.assertNull(cd.get("Location"));
-        Assert.assertNull(cd.get("JavaOpts"));
-    }
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/7c2db062/instance/core/src/test/java/org/apache/karaf/jpm/MainTest.java
----------------------------------------------------------------------
diff --git a/instance/core/src/test/java/org/apache/karaf/jpm/MainTest.java b/instance/core/src/test/java/org/apache/karaf/jpm/MainTest.java
deleted file mode 100644
index e7f7c83..0000000
--- a/instance/core/src/test/java/org/apache/karaf/jpm/MainTest.java
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * 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.karaf.jpm;
-
-public class MainTest {
-
-    public static void main(String[] args) throws Exception {
-        Thread.sleep(Long.parseLong(args[0]));
-    }
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/7c2db062/instance/core/src/test/java/org/apache/karaf/jpm/ProcessTest.java
----------------------------------------------------------------------
diff --git a/instance/core/src/test/java/org/apache/karaf/jpm/ProcessTest.java b/instance/core/src/test/java/org/apache/karaf/jpm/ProcessTest.java
deleted file mode 100644
index 9cdc5ad..0000000
--- a/instance/core/src/test/java/org/apache/karaf/jpm/ProcessTest.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * 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.karaf.jpm;
-
-import java.io.File;
-
-import junit.framework.TestCase;
-
-import org.apache.karaf.jpm.impl.ProcessBuilderFactoryImpl;
-import org.apache.karaf.jpm.impl.ScriptUtils;
-
-public class ProcessTest extends TestCase {
-
-    public void testCreate() throws Exception {
-        String javaPath = new File(System.getProperty("java.home"), ScriptUtils.isWindows() ? "bin\\java.exe" : "bin/java").getCanonicalPath();
-        System.err.println(javaPath);
-        StringBuilder command = new StringBuilder();
-        command.append("\"").append(javaPath).append("\"");
-        command.append(" -Dprop=\"key\"");
-        command.append(" -classpath ");
-        String clRes = getClass().getName().replace('.', '/') + ".class";
-        String str = getClass().getClassLoader().getResource(clRes).toString();
-        str = str.substring("file:".length(), str.indexOf(clRes));
-        command.append(str);
-        command.append(" ");
-        command.append(MainTest.class.getName());
-        command.append(" ");
-        command.append(60000);
-        System.err.println("Executing: " + command.toString());
-
-        ProcessBuilder builder = new ProcessBuilderFactoryImpl().newBuilder();
-        org.apache.karaf.jpm.Process p = builder.command(command.toString()).start();
-        assertNotNull(p);
-        System.err.println("Process: " + p.getPid());
-        assertNotNull(p.getPid());
-        Thread.sleep(1000);
-        System.err.println("Running: " + p.isRunning());
-        assertTrue(p.isRunning());
-        System.err.println("Destroying");
-        p.destroy();
-        Thread.sleep(1000);
-        System.err.println("Running: " + p.isRunning());
-        assertFalse(p.isRunning());
-    }
-
-    /*
-     * When the process creation fails, no error is reported by the script
-     * 
-    public void testFailure() throws Exception {
-        ProcessBuilder builder = ProcessBuilderFactory.newInstance().newBuilder();
-        Process p = builder.command("ec").start();
-        fail("An exception should have been thrown");
-    }
-    */
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/7c2db062/instance/core/src/test/resources/etc/startup.properties
----------------------------------------------------------------------
diff --git a/instance/core/src/test/resources/etc/startup.properties b/instance/core/src/test/resources/etc/startup.properties
deleted file mode 100644
index df7c9bc..0000000
--- a/instance/core/src/test/resources/etc/startup.properties
+++ /dev/null
@@ -1,20 +0,0 @@
-################################################################################
-#
-#    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.
-#
-################################################################################
-
-# Fake startup.properties for unit tests as the startup properties in generated by the karaf-maven-plugin
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/karaf/blob/7c2db062/instance/pom.xml
----------------------------------------------------------------------
diff --git a/instance/pom.xml b/instance/pom.xml
index c6c1930..baeb2f9 100644
--- a/instance/pom.xml
+++ b/instance/pom.xml
@@ -10,7 +10,7 @@
         (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
+            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,
@@ -29,13 +29,172 @@
     </parent>
 
     <groupId>org.apache.karaf.instance</groupId>
-    <artifactId>instance</artifactId>
-    <packaging>pom</packaging>
-    <name>Apache Karaf :: Instance</name>
+    <artifactId>org.apache.karaf.instance.core</artifactId>
+    <packaging>bundle</packaging>
+    <name>Apache Karaf :: Instance :: Core</name>
+    <description>Core implementation of the instance feature to manipulate Karaf child instances.</description>
 
-    <modules>
-        <module>core</module>
-        <module>command</module>
-    </modules>
+    <properties>
+        <appendedResourcesDirectory>${project.basedir}/../../etc/appended-resources</appendedResourcesDirectory>
+    </properties>
 
+    <dependencies>
+
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>org.osgi.core</artifactId>
+            <scope>provided</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-api</artifactId>
+            <scope>provided</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.felix</groupId>
+            <artifactId>org.apache.felix.utils</artifactId>
+            <scope>provided</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.karaf.shell</groupId>
+            <artifactId>org.apache.karaf.shell.core</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.karaf</groupId>
+            <artifactId>org.apache.karaf.util</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.karaf.features</groupId>
+            <artifactId>org.apache.karaf.features.core</artifactId>
+            <optional>true</optional>
+        </dependency>
+
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-jdk14</artifactId>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <resources>
+            <resource>
+                <directory>${project.basedir}/src/main/resources</directory>
+                <includes>
+                    <include>**/*</include>
+                </includes>
+            </resource>
+            <resource>
+                <directory>${project.basedir}/src/main/resources</directory>
+                <filtering>true</filtering>
+                <includes>
+                    <include>**/*.info</include>
+                </includes>
+            </resource>
+            <resource>
+                <directory>${project.build.directory}/generated-resources</directory>
+                <includes>
+                    <include>**/*.*</include>
+                </includes>
+            </resource>
+        </resources>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-resources-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>copy-resources</id>
+                        <phase>generate-resources</phase>
+                        <goals>
+                            <goal>copy-resources</goal>
+                        </goals>
+                        <configuration>
+                            <outputDirectory>${project.build.directory}/generated-resources/org/apache/karaf/instance/</outputDirectory>
+                            <resources>
+                                <resource>
+                                    <directory>${project.basedir}/../assemblies/features/framework/src/main/resources</directory>
+                                    <excludes>
+                                        <exclude>**/org.apache.karaf.management.cfg</exclude>
+                                        <exclude>**/org.apache.karaf.shell.cfg</exclude>
+                                        <exclude>**/system.properties</exclude>
+                                    </excludes>
+                                </resource>
+                                <resource>
+                                    <directory>${project.basedir}/../assemblies/features/framework/src/main/filtered-resources</directory>
+                                    <filtering>true</filtering>
+                                    <includes>
+                                        <include>**/*.properties</include>
+                                        <include>**/*.cfg</include>
+                                        <include>**/*.xml</include>
+                                        <include>**/*.info</include>
+                                    </includes>
+                                </resource>
+                                <resource>
+                                	<directory>${project.basedir}/../assemblies/features/framework/src/main/snapshot</directory>
+                                	<filtering>true</filtering>
+                                    <includes>
+                                        <include>**/*.cfg</include>
+                                    </includes>
+                                </resource>
+                            </resources>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+                <configuration>
+                    <instructions>
+                        <Export-Package>
+                            org.apache.karaf.instance.core
+                        </Export-Package>
+                        <!-- We have to avoid importing instance.core.internal and jansi
+                             as Execute.java accesses the InstanceServiceImpl and jansi
+                             (but only outside OSGi) -->
+                        <Import-Package>
+                            !org.apache.karaf.shell.impl.action.command,
+                            !org.apache.karaf.instance.core.internal,
+                            *
+                        </Import-Package>
+                        <Provide-Capability>
+                            service-reference;effective:=active;objectClass=org.apache.karaf.instance.core.InstanceService
+                        </Provide-Capability>
+                        <Private-Package>
+                            org.apache.karaf.jpm,
+                            org.apache.karaf.jpm.impl,
+                            org.apache.karaf.instance.main,
+                            org.apache.karaf.instance.command,
+                            org.apache.karaf.instance.command.completers,
+                            org.apache.karaf.instance.core.internal,
+                            org.apache.karaf.instance.core.internal.osgi,
+                            org.apache.felix.utils.properties;-split-package:=merge-first,
+                            org.apache.karaf.util.locks,
+                            org.apache.karaf.util.tracker
+                        </Private-Package>
+                        <Bundle-Activator>
+                            org.apache.karaf.instance.core.internal.osgi.Activator
+                        </Bundle-Activator>
+                        <Karaf-Commands>org.apache.karaf.instance.command.*</Karaf-Commands>
+                    </instructions>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-surefire-plugin</artifactId>
+                <configuration>
+                  <excludes>
+                    <!-- this is not a unit test but an application used for testing -->
+                    <exclude>**/MainTest.java</exclude>
+                  </excludes>
+                </configuration>
+           </plugin>
+        </plugins>
+    </build>
 </project>

http://git-wip-us.apache.org/repos/asf/karaf/blob/7c2db062/instance/src/main/java/org/apache/karaf/instance/command/ChangeOptsCommand.java
----------------------------------------------------------------------
diff --git a/instance/src/main/java/org/apache/karaf/instance/command/ChangeOptsCommand.java b/instance/src/main/java/org/apache/karaf/instance/command/ChangeOptsCommand.java
new file mode 100644
index 0000000..c526c07
--- /dev/null
+++ b/instance/src/main/java/org/apache/karaf/instance/command/ChangeOptsCommand.java
@@ -0,0 +1,41 @@
+/*
+ * 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.karaf.instance.command;
+
+import org.apache.karaf.instance.command.completers.InstanceCompleter;
+import org.apache.karaf.shell.api.action.Argument;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.Completion;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+
+@Command(scope = "instance", name = "opts-change", description = "Changes the Java options of an existing container instance.")
+@Service
+public class ChangeOptsCommand extends InstanceCommandSupport {
+
+    @Argument(index = 0, name = "name", description="The name of the container instance", required = true, multiValued = false)
+    @Completion(InstanceCompleter.class)
+    private String instance = null;
+
+    @Argument(index = 1, name = "javaOpts", description = "The new Java options to set", required = true, multiValued = false)
+    private String javaOpts;
+
+    protected Object doExecute() throws Exception {
+        getExistingInstance(instance).changeJavaOpts(javaOpts);
+        return null;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/7c2db062/instance/src/main/java/org/apache/karaf/instance/command/ChangeRmiRegistryPortCommand.java
----------------------------------------------------------------------
diff --git a/instance/src/main/java/org/apache/karaf/instance/command/ChangeRmiRegistryPortCommand.java b/instance/src/main/java/org/apache/karaf/instance/command/ChangeRmiRegistryPortCommand.java
new file mode 100644
index 0000000..de5bfaf
--- /dev/null
+++ b/instance/src/main/java/org/apache/karaf/instance/command/ChangeRmiRegistryPortCommand.java
@@ -0,0 +1,41 @@
+/*
+ * 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.karaf.instance.command;
+
+import org.apache.karaf.instance.command.completers.InstanceCompleter;
+import org.apache.karaf.shell.api.action.Argument;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.Completion;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+
+@Command(scope = "instance", name = "rmi-registry-port-change", description = "Changes the RMI registry port (used by management layer) of an existing container instance.")
+@Service
+public class ChangeRmiRegistryPortCommand extends InstanceCommandSupport {
+
+    @Argument(index = 0, name = "name", description = "The name of the container instance", required = true, multiValued = false)
+    @Completion(InstanceCompleter.class)
+    private String instance = null;
+
+    @Argument(index = 1, name = "port", description = "The new RMI registry port to set", required = true, multiValued = false)
+    private int port = 0;
+
+    protected Object doExecute() throws Exception {
+        getExistingInstance(instance).changeRmiRegistryPort(port);
+        return null;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/7c2db062/instance/src/main/java/org/apache/karaf/instance/command/ChangeRmiServerPortCommand.java
----------------------------------------------------------------------
diff --git a/instance/src/main/java/org/apache/karaf/instance/command/ChangeRmiServerPortCommand.java b/instance/src/main/java/org/apache/karaf/instance/command/ChangeRmiServerPortCommand.java
new file mode 100644
index 0000000..0ac2cf7
--- /dev/null
+++ b/instance/src/main/java/org/apache/karaf/instance/command/ChangeRmiServerPortCommand.java
@@ -0,0 +1,41 @@
+/*
+ * 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.karaf.instance.command;
+
+import org.apache.karaf.instance.command.completers.InstanceCompleter;
+import org.apache.karaf.shell.api.action.Argument;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.Completion;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+
+@Command(scope = "instance", name = "rmi-server-port-change", description = "Changes the RMI server port (used by management layer) of an existing instance.")
+@Service
+public class ChangeRmiServerPortCommand extends InstanceCommandSupport {
+
+    @Argument(index = 0, name = "name", description = "The name of the container instance", required = true, multiValued = false)
+    @Completion(InstanceCompleter.class)
+    private String instance = null;
+
+    @Argument(index = 1, name = "port", description = "The new RMI server port to set", required = true, multiValued = false)
+    private int port = 0;
+
+    protected Object doExecute() throws Exception {
+        getExistingInstance(instance).changeRmiServerPort(port);
+        return null;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/7c2db062/instance/src/main/java/org/apache/karaf/instance/command/ChangeSshPortCommand.java
----------------------------------------------------------------------
diff --git a/instance/src/main/java/org/apache/karaf/instance/command/ChangeSshPortCommand.java b/instance/src/main/java/org/apache/karaf/instance/command/ChangeSshPortCommand.java
new file mode 100644
index 0000000..17ad26c
--- /dev/null
+++ b/instance/src/main/java/org/apache/karaf/instance/command/ChangeSshPortCommand.java
@@ -0,0 +1,41 @@
+/*
+ * 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.karaf.instance.command;
+
+import org.apache.karaf.instance.command.completers.InstanceCompleter;
+import org.apache.karaf.shell.api.action.Argument;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.Completion;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+
+@Command(scope = "instance", name = "ssh-port-change", description = "Changes the secure shell port of an existing container instance.")
+@Service
+public class ChangeSshPortCommand extends InstanceCommandSupport {
+
+    @Argument(index = 0, name = "name", description="The name of the container instance", required = true, multiValued = false)
+    @Completion(InstanceCompleter.class)
+    private String instance = null;
+
+    @Argument(index = 1, name = "port", description = "The new secure shell port to set", required = true, multiValued = false)
+    private int port = 0;
+
+    protected Object doExecute() throws Exception {
+        getExistingInstance(instance).changeSshPort(port);
+        return null;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/7c2db062/instance/src/main/java/org/apache/karaf/instance/command/CloneCommand.java
----------------------------------------------------------------------
diff --git a/instance/src/main/java/org/apache/karaf/instance/command/CloneCommand.java b/instance/src/main/java/org/apache/karaf/instance/command/CloneCommand.java
new file mode 100644
index 0000000..e4f28c5
--- /dev/null
+++ b/instance/src/main/java/org/apache/karaf/instance/command/CloneCommand.java
@@ -0,0 +1,66 @@
+/*
+ * 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.karaf.instance.command;
+
+import org.apache.karaf.instance.command.completers.InstanceCompleter;
+import org.apache.karaf.instance.core.InstanceSettings;
+import org.apache.karaf.shell.api.action.Argument;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.Completion;
+import org.apache.karaf.shell.api.action.Option;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+
+/**
+ * Clone an existing instance.
+ */
+@Command(scope = "instance", name = "clone", description = "Clones an existing container instance.")
+@Service
+public class CloneCommand extends InstanceCommandSupport {
+
+    @Option(name = "-s", aliases = {"--ssh-port"}, description = "Port number for remote secure shell connection", required = false, multiValued = false)
+    int sshPort = 0;
+
+    @Option(name = "-r", aliases = {"-rr", "--rmi-port", "--rmi-registry-port"}, description = "Port number for RMI registry connection", required = false, multiValued = false)
+    int rmiRegistryPort = 0;
+
+    @Option(name = "-rs", aliases = {"--rmi-server-port"}, description = "Port number for RMI server connection", required = false, multiValued = false)
+    int rmiServerPort = 0;
+
+    @Option(name = "-l", aliases = {"--location"}, description = "Location of the cloned container instance in the file system", required = false, multiValued = false)
+    String location;
+
+    @Option(name = "-o", aliases = {"--java-opts"}, description = "JVM options to use when launching the cloned instance", required = false, multiValued = false)
+    String javaOpts;
+
+    @Option(name = "-v", aliases = {"--verbose"}, description = "Display actions performed by the command (disabled by default)", required = false, multiValued = false)
+    boolean verbose = false;
+
+    @Argument(index = 0, name = "name", description = "The name of the source container instance", required = true, multiValued = false)
+    @Completion(InstanceCompleter.class)
+    String name;
+
+    @Argument(index = 1, name = "cloneName", description = "The name of the cloned container instance", required = true, multiValued = false)
+    String cloneName;
+
+
+    protected Object doExecute() throws Exception {
+        InstanceSettings settings = new InstanceSettings(sshPort, rmiRegistryPort, rmiServerPort, location, javaOpts, null, null);
+        getInstanceService().cloneInstance(name, cloneName, settings, verbose);
+        return null;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/7c2db062/instance/src/main/java/org/apache/karaf/instance/command/ConnectCommand.java
----------------------------------------------------------------------
diff --git a/instance/src/main/java/org/apache/karaf/instance/command/ConnectCommand.java b/instance/src/main/java/org/apache/karaf/instance/command/ConnectCommand.java
new file mode 100644
index 0000000..c81a3eb
--- /dev/null
+++ b/instance/src/main/java/org/apache/karaf/instance/command/ConnectCommand.java
@@ -0,0 +1,78 @@
+/*
+ * 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.karaf.instance.command;
+
+import java.util.List;
+
+import org.apache.karaf.instance.command.completers.InstanceCompleter;
+import org.apache.karaf.shell.api.action.Argument;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.Completion;
+import org.apache.karaf.shell.api.action.Option;
+import org.apache.karaf.shell.api.action.lifecycle.Reference;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.apache.karaf.shell.api.console.Session;
+
+@Command(scope = "instance", name = "connect", description = "Connects to an existing container instance.")
+@Service
+public class ConnectCommand extends InstanceCommandSupport {
+
+    @Option(name="-u", aliases={"--username"}, description="Remote user name", required = false, multiValued = false)
+    private String username;
+
+    @Option(name = "-p", aliases = {"--password"}, description = "Remote password", required = false, multiValued = false)
+    private String password;
+
+    @Argument(index = 0, name="name", description="The name of the container instance", required = true, multiValued = false)
+    @Completion(InstanceCompleter.class)
+    private String instance = null;
+
+    @Argument(index = 1, name = "command", description = "Optional command to execute", required = false, multiValued = true)
+    private List<String> command;
+
+    @Reference
+    Session session;
+
+    protected Object doExecute() throws Exception {
+        String cmdStr = "";
+        if (command != null) {
+            StringBuilder sb = new StringBuilder();
+            for (String cmd : command) {
+                if (sb.length() > 0) {
+                    sb.append(' ');
+                }
+                sb.append(cmd);
+            }
+            cmdStr = "'" + sb.toString().replaceAll("'", "\\'") + "'";
+        }
+
+        int port = getExistingInstance(instance).getSshPort();
+        if (username != null) {
+            if (password == null) {
+                session.execute("ssh:ssh -q -l " + username + " -p " + port + " localhost " + cmdStr);
+            } else {
+                session.execute("ssh:ssh -q -l " + username + " -P " + password + " -p " + port + " localhost " + cmdStr);
+            }
+        } else {
+            session.execute("ssh:ssh -q -p " + port + " localhost " + cmdStr);
+        }
+        return null;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/7c2db062/instance/src/main/java/org/apache/karaf/instance/command/CreateCommand.java
----------------------------------------------------------------------
diff --git a/instance/src/main/java/org/apache/karaf/instance/command/CreateCommand.java b/instance/src/main/java/org/apache/karaf/instance/command/CreateCommand.java
new file mode 100644
index 0000000..0dcc3ac
--- /dev/null
+++ b/instance/src/main/java/org/apache/karaf/instance/command/CreateCommand.java
@@ -0,0 +1,74 @@
+/*
+ * 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.karaf.instance.command;
+
+import java.util.List;
+
+import org.apache.karaf.features.command.completers.AllFeatureCompleter;
+import org.apache.karaf.features.command.completers.InstalledRepoUriCompleter;
+import org.apache.karaf.instance.core.InstanceSettings;
+import org.apache.karaf.shell.api.action.Argument;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.Completion;
+import org.apache.karaf.shell.api.action.Option;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+
+/**
+ * Creates a new instance.
+ */
+@Command(scope = "instance", name = "create", description = "Creates a new container instance.")
+@Service
+public class CreateCommand extends InstanceCommandSupport
+{
+    @Option(name = "-s", aliases = {"--ssh-port"}, description = "Port number for remote secure shell connection", required = false, multiValued = false)
+    int sshPort = 0;
+
+    @Option(name = "-r", aliases = {"-rr", "--rmi-port", "--rmi-registry-port"}, description = "Port number for RMI registry connection", required = false, multiValued = false)
+    int rmiRegistryPort = 0;
+
+    @Option(name = "-rs", aliases = {"--rmi-server-port"}, description = "Port number for RMI server connection", required = false, multiValued = false)
+    int rmiServerPort = 0;
+
+    @Option(name = "-l", aliases = {"--location"}, description = "Location of the new container instance in the file system", required = false, multiValued = false)
+    String location;
+
+    @Option(name = "-o", aliases = {"--java-opts"}, description = "JVM options to use when launching the instance", required = false, multiValued = false)
+    String javaOpts;
+    
+    @Option(name = "-f", aliases = {"--feature"},
+            description = "Initial features. This option can be specified multiple times to enable multiple initial features", required = false, multiValued = true)
+    @Completion(AllFeatureCompleter.class)
+    List<String> features;
+    
+    @Option(name = "-furl", aliases = {"--featureURL"}, 
+            description = "Additional feature descriptor URLs. This option can be specified multiple times to add multiple URLs", required = false, multiValued = true)
+    @Completion(InstalledRepoUriCompleter.class)
+    List<String> featureURLs;
+
+    @Option(name = "-v", aliases = {"--verbose"}, description = "Display actions performed by the command (disabled by default)", required = false, multiValued = false)
+    boolean verbose = false;
+
+    @Argument(index = 0, name = "name", description="The name of the new container instance", required = true, multiValued = false)
+    String instance = null;
+
+    protected Object doExecute() throws Exception {
+        InstanceSettings settings = new InstanceSettings(sshPort, rmiRegistryPort, rmiServerPort, location, javaOpts, featureURLs, features);
+        getInstanceService().createInstance(instance, settings, verbose);
+        return null;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/7c2db062/instance/src/main/java/org/apache/karaf/instance/command/DestroyCommand.java
----------------------------------------------------------------------
diff --git a/instance/src/main/java/org/apache/karaf/instance/command/DestroyCommand.java b/instance/src/main/java/org/apache/karaf/instance/command/DestroyCommand.java
new file mode 100644
index 0000000..fb2964f
--- /dev/null
+++ b/instance/src/main/java/org/apache/karaf/instance/command/DestroyCommand.java
@@ -0,0 +1,41 @@
+/*
+ * 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.karaf.instance.command;
+
+import org.apache.karaf.instance.command.completers.InstanceCompleter;
+import org.apache.karaf.shell.api.action.Argument;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.Completion;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+
+/**
+ * Destroy an existing instance.
+ */
+@Command(scope = "instance", name = "destroy", description = "Destroys an existing container instance.")
+@Service
+public class DestroyCommand extends InstanceCommandSupport
+{
+    @Argument(index = 0, name = "name", description= "The name of the container instance to destroy", required = true, multiValued = false)
+    @Completion(InstanceCompleter.class)
+    private String instance = null;
+
+    protected Object doExecute() throws Exception {
+        getExistingInstance(instance).destroy();
+        return null;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/7c2db062/instance/src/main/java/org/apache/karaf/instance/command/InstanceCommandSupport.java
----------------------------------------------------------------------
diff --git a/instance/src/main/java/org/apache/karaf/instance/command/InstanceCommandSupport.java b/instance/src/main/java/org/apache/karaf/instance/command/InstanceCommandSupport.java
new file mode 100644
index 0000000..3b0b535
--- /dev/null
+++ b/instance/src/main/java/org/apache/karaf/instance/command/InstanceCommandSupport.java
@@ -0,0 +1,51 @@
+/*
+ * 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.karaf.instance.command;
+
+import org.apache.karaf.instance.core.Instance;
+import org.apache.karaf.instance.core.InstanceService;
+import org.apache.karaf.shell.api.action.Action;
+import org.apache.karaf.shell.api.action.lifecycle.Reference;
+
+public abstract class InstanceCommandSupport implements Action {
+
+    @Reference
+    private InstanceService instanceService;
+
+    public InstanceService getInstanceService() {
+        return instanceService;
+    }
+
+    public void setInstanceService(InstanceService instanceService) {
+        this.instanceService = instanceService;
+    }
+
+    protected Instance getExistingInstance(String name) {
+        Instance i = instanceService.getInstance(name);
+        if (i == null) {
+            throw new IllegalArgumentException("Instances '" + name + "' does not exist");
+        }
+        return i;
+    }
+
+    @Override
+    public Object execute() throws Exception {
+        return doExecute();
+    }
+
+    protected abstract Object doExecute() throws Exception;
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/7c2db062/instance/src/main/java/org/apache/karaf/instance/command/ListCommand.java
----------------------------------------------------------------------
diff --git a/instance/src/main/java/org/apache/karaf/instance/command/ListCommand.java b/instance/src/main/java/org/apache/karaf/instance/command/ListCommand.java
new file mode 100644
index 0000000..fe571a8
--- /dev/null
+++ b/instance/src/main/java/org/apache/karaf/instance/command/ListCommand.java
@@ -0,0 +1,81 @@
+/*
+ * 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.karaf.instance.command;
+
+import org.apache.karaf.instance.core.Instance;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.Option;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.apache.karaf.shell.support.table.ShellTable;
+
+@Command(scope = "instance", name = "list", description = "Lists all existing container instances.")
+@Service
+public class ListCommand extends InstanceCommandSupport {
+
+    @Option(name = "-l", aliases = { "--location" }, description = "Displays the location of the container instances", required = false, multiValued = false)
+    boolean location;
+
+    @Option(name = "-o", aliases = { "--java-opts" }, description = "Displays the Java options used to launch the JVM", required = false, multiValued = false)
+    boolean javaOpts;
+
+    @Option(name = "--no-color", description = "Disable table rendered output", required = false, multiValued = false)
+    boolean noFormat;
+
+    protected Object doExecute() throws Exception {
+        getInstanceService().refreshInstance();
+        Instance[] instances = getInstanceService().getInstances();
+        ShellTable table = new ShellTable();
+        table.column("SSH Port").alignRight();
+        table.column("RMI Registry").alignRight();
+        table.column("RMI Server").alignRight();
+        table.column("State");
+        table.column("PID");
+        table.column(getRightColumnHeader());
+        for (Instance instance : instances) {
+            table.addRow().addContent(
+                    instance.getSshPort(),
+                    instance.getRmiRegistryPort(),
+                    instance.getRmiServerPort(),
+                    instance.getState(),
+                    instance.getPid(),
+                    getRightColumnValue(instance));
+        }
+        table.print(System.out, !noFormat);
+        return null;
+    }
+
+    private String getRightColumnHeader() {
+        if (javaOpts) {
+            return "JavaOpts";
+        } else if (location) {
+            return "Location";
+        } else {
+            return "Name";
+        }
+    }
+
+    private String getRightColumnValue(Instance instance) {
+        if (javaOpts) {
+            return instance.getJavaOpts();
+        } else if (location) {
+            return instance.getLocation();
+        } else {
+            return instance.getName();
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/7c2db062/instance/src/main/java/org/apache/karaf/instance/command/RenameCommand.java
----------------------------------------------------------------------
diff --git a/instance/src/main/java/org/apache/karaf/instance/command/RenameCommand.java b/instance/src/main/java/org/apache/karaf/instance/command/RenameCommand.java
new file mode 100644
index 0000000..ef68400
--- /dev/null
+++ b/instance/src/main/java/org/apache/karaf/instance/command/RenameCommand.java
@@ -0,0 +1,45 @@
+/*
+ * 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.karaf.instance.command;
+
+import org.apache.karaf.instance.command.completers.InstanceCompleter;
+import org.apache.karaf.shell.api.action.Argument;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.Completion;
+import org.apache.karaf.shell.api.action.Option;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+
+@Command(scope = "instance", name = "rename", description = "Rename an existing container instance.")
+@Service
+public class RenameCommand extends InstanceCommandSupport {
+
+    @Option(name = "-v", aliases = {"--verbose"}, description = "Display actions performed by the command (disabled by default)", required = false, multiValued = false)
+    boolean verbose = false;
+
+    @Argument(index = 0, name = "name", description = "The name of the container instance to rename", required = true, multiValued = false)
+    @Completion(InstanceCompleter.class)
+    String instance = null;
+
+    @Argument(index = 1, name = "new-name", description = "The new name of the container instance", required = true, multiValued = false)
+    String newName = null;
+
+    protected Object doExecute() throws Exception {
+        getInstanceService().renameInstance(instance, newName, verbose);
+        return null;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/7c2db062/instance/src/main/java/org/apache/karaf/instance/command/StartCommand.java
----------------------------------------------------------------------
diff --git a/instance/src/main/java/org/apache/karaf/instance/command/StartCommand.java b/instance/src/main/java/org/apache/karaf/instance/command/StartCommand.java
new file mode 100644
index 0000000..8c52d5e
--- /dev/null
+++ b/instance/src/main/java/org/apache/karaf/instance/command/StartCommand.java
@@ -0,0 +1,76 @@
+/*
+ * 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.karaf.instance.command;
+
+import org.apache.karaf.instance.command.completers.InstanceCompleter;
+import org.apache.karaf.instance.core.Instance;
+import org.apache.karaf.shell.api.action.Argument;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.Completion;
+import org.apache.karaf.shell.api.action.Option;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+
+@Command(scope = "instance", name = "start", description = "Start an existing container instance.")
+@Service
+public class StartCommand extends InstanceCommandSupport {
+                      
+    @Option(name = "-d", aliases = { "--debug"}, description = "Start the instance in debug mode", required = false, multiValued = false)
+    private boolean debug; 
+    
+    @Option(name = "-o", aliases = { "--java-opts"}, description = "Java options when launching the instance", required = false, multiValued = false)
+    private String javaOpts;
+
+    @Option(name = "-w", aliases = { "--wait"}, description = "Wait for the instance to be fully started", required = false, multiValued = false)
+    private boolean wait;
+
+    @Argument(index = 0, name = "name", description = "The name of the container instance", required = true, multiValued = false)
+    @Completion(InstanceCompleter.class)
+    private String instance = null;
+
+    static final String DEBUG_OPTS = " -Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005";
+    static final String DEFAULT_OPTS = "-server -Xmx512M -Dcom.sun.management.jmxremote";
+
+    protected Object doExecute() throws Exception {
+        Instance child = getExistingInstance(instance);
+        String opts = javaOpts;
+        if (opts == null) {
+            opts = child.getJavaOpts();
+        }
+        if (opts == null) {
+            opts = DEFAULT_OPTS;
+        }
+        if (debug) {
+            opts += DEBUG_OPTS;
+        }
+        if (wait) {
+            String state = child.getState();
+            if (Instance.STOPPED.equals(state)) {
+                child.start(opts);
+            }
+            if (!Instance.STARTED.equals(state)) {
+                do {
+                    Thread.sleep(500);
+                    state = child.getState();
+                } while (Instance.STARTING.equals(state));
+            }
+        } else {
+            child.start(opts);
+        }
+        return null;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/7c2db062/instance/src/main/java/org/apache/karaf/instance/command/StatusCommand.java
----------------------------------------------------------------------
diff --git a/instance/src/main/java/org/apache/karaf/instance/command/StatusCommand.java b/instance/src/main/java/org/apache/karaf/instance/command/StatusCommand.java
new file mode 100644
index 0000000..82100e1
--- /dev/null
+++ b/instance/src/main/java/org/apache/karaf/instance/command/StatusCommand.java
@@ -0,0 +1,40 @@
+/*
+ * 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.karaf.instance.command;
+
+import org.apache.karaf.instance.command.completers.InstanceCompleter;
+import org.apache.karaf.instance.core.Instance;
+import org.apache.karaf.shell.api.action.Argument;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.Completion;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+
+@Command(scope = "instance", name = "status", description = "Check the current status of an instance.")
+@Service
+public class StatusCommand extends InstanceCommandSupport {
+
+    @Argument(index = 0, name = "name", description = "The name of the instance", required = true, multiValued = false)
+    @Completion(InstanceCompleter.class)
+    private String name;
+
+    protected Object doExecute() throws Exception {
+        Instance instance = getExistingInstance(name);
+        System.out.println(instance.getState());
+        return null;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/7c2db062/instance/src/main/java/org/apache/karaf/instance/command/StopCommand.java
----------------------------------------------------------------------
diff --git a/instance/src/main/java/org/apache/karaf/instance/command/StopCommand.java b/instance/src/main/java/org/apache/karaf/instance/command/StopCommand.java
new file mode 100644
index 0000000..6c8de10
--- /dev/null
+++ b/instance/src/main/java/org/apache/karaf/instance/command/StopCommand.java
@@ -0,0 +1,38 @@
+/*
+ * 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.karaf.instance.command;
+
+import org.apache.karaf.instance.command.completers.InstanceCompleter;
+import org.apache.karaf.shell.api.action.Argument;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.Completion;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+
+@Command(scope = "instance", name = "stop", description = "Stop an existing container instance.")
+@Service
+public class StopCommand extends InstanceCommandSupport {
+
+    @Argument(index = 0, name = "name", description = "The name of the container instance", required = true, multiValued = false)
+    @Completion(InstanceCompleter.class)
+    private String instance = null;
+
+    protected Object doExecute() throws Exception {
+        getExistingInstance(instance).stop();
+        return null;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/7c2db062/instance/src/main/java/org/apache/karaf/instance/command/completers/InstanceCompleter.java
----------------------------------------------------------------------
diff --git a/instance/src/main/java/org/apache/karaf/instance/command/completers/InstanceCompleter.java b/instance/src/main/java/org/apache/karaf/instance/command/completers/InstanceCompleter.java
new file mode 100644
index 0000000..4468374
--- /dev/null
+++ b/instance/src/main/java/org/apache/karaf/instance/command/completers/InstanceCompleter.java
@@ -0,0 +1,52 @@
+/*
+ * 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.karaf.instance.command.completers;
+
+import java.util.List;
+
+import org.apache.karaf.instance.core.Instance;
+import org.apache.karaf.instance.core.InstanceService;
+import org.apache.karaf.shell.api.action.lifecycle.Reference;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.apache.karaf.shell.api.console.CommandLine;
+import org.apache.karaf.shell.api.console.Completer;
+import org.apache.karaf.shell.api.console.Session;
+import org.apache.karaf.shell.support.completers.StringsCompleter;
+
+/**
+ * Displays a list of configured server instances for the instance commands.
+ *
+ */
+@Service
+public class InstanceCompleter implements Completer {
+
+    @Reference
+    private InstanceService instanceService;
+
+    public void setInstanceService(InstanceService instanceService) {
+        this.instanceService = instanceService;
+    }
+
+    public int complete(Session session, CommandLine commandLine, List<String> candidates) {
+        StringsCompleter delegate = new StringsCompleter();
+        for (Instance instance : instanceService.getInstances()) {
+            delegate.getStrings().add(instance.getName());
+        }
+        return delegate.complete(session, commandLine, candidates);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/7c2db062/instance/src/main/java/org/apache/karaf/instance/core/Instance.java
----------------------------------------------------------------------
diff --git a/instance/src/main/java/org/apache/karaf/instance/core/Instance.java b/instance/src/main/java/org/apache/karaf/instance/core/Instance.java
new file mode 100644
index 0000000..5e78bb2
--- /dev/null
+++ b/instance/src/main/java/org/apache/karaf/instance/core/Instance.java
@@ -0,0 +1,66 @@
+/*
+ * 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.karaf.instance.core;
+
+public interface Instance {
+
+    String STOPPED = "Stopped";
+    String STARTING = "Starting";
+    String STARTED = "Started";
+    String ERROR = "Error";
+
+    String getName();
+
+    @Deprecated
+    void setName(String name);
+    
+    boolean isRoot();
+
+    String getLocation();
+
+    @Deprecated
+    void setLocation(String location);
+
+    int getPid();
+
+    int getSshPort();
+
+    void changeSshPort(int port) throws Exception;
+
+    int getRmiRegistryPort();
+
+    void changeRmiRegistryPort(int port) throws Exception;
+
+    int getRmiServerPort();
+
+    void changeRmiServerPort(int port) throws Exception;
+
+    String getJavaOpts();
+
+    void changeJavaOpts(String javaOpts) throws Exception;
+
+    void start(String javaOpts) throws Exception;
+
+    void stop() throws Exception;
+
+    void destroy() throws Exception;
+
+    String getState() throws Exception;
+
+    @Deprecated
+    boolean isAttached();
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/7c2db062/instance/src/main/java/org/apache/karaf/instance/core/InstanceService.java
----------------------------------------------------------------------
diff --git a/instance/src/main/java/org/apache/karaf/instance/core/InstanceService.java b/instance/src/main/java/org/apache/karaf/instance/core/InstanceService.java
new file mode 100644
index 0000000..cc6c10c
--- /dev/null
+++ b/instance/src/main/java/org/apache/karaf/instance/core/InstanceService.java
@@ -0,0 +1,33 @@
+/*
+ * 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.karaf.instance.core;
+
+public interface InstanceService {
+
+    Instance createInstance(String name, InstanceSettings settings, boolean printOutput) throws Exception;
+
+    void renameInstance(String name, String newName, boolean printOutput) throws Exception;
+
+    @Deprecated
+    void refreshInstance() throws Exception;
+
+    Instance cloneInstance(String name, String cloneName, InstanceSettings settings, boolean printOutput) throws Exception;
+
+    Instance[] getInstances();
+
+    Instance getInstance(String name);    
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/7c2db062/instance/src/main/java/org/apache/karaf/instance/core/InstanceSettings.java
----------------------------------------------------------------------
diff --git a/instance/src/main/java/org/apache/karaf/instance/core/InstanceSettings.java b/instance/src/main/java/org/apache/karaf/instance/core/InstanceSettings.java
new file mode 100644
index 0000000..0f9cf97
--- /dev/null
+++ b/instance/src/main/java/org/apache/karaf/instance/core/InstanceSettings.java
@@ -0,0 +1,97 @@
+/*
+ * 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.karaf.instance.core;
+
+import java.util.List;
+
+public class InstanceSettings {
+
+    private final int sshPort;
+    private final int rmiRegistryPort;
+    private final int rmiServerPort;
+    private final String location;
+    private final String javaOpts;
+    private final List<String> featureURLs;
+    private final List<String> features;
+
+    public InstanceSettings(int sshPort, int rmiRegistryPort, int rmiServerPort, String location, String javaOpts, List<String> featureURLs, List<String> features) {
+        this.sshPort = sshPort;
+        this.rmiRegistryPort = rmiRegistryPort;
+        this.rmiServerPort = rmiServerPort;
+        this.location = location;
+        this.javaOpts = javaOpts;
+        this.featureURLs = featureURLs;
+        this.features = features;
+    }
+
+    public int getSshPort() {
+        return sshPort;
+    }
+
+    public int getRmiRegistryPort() {
+        return rmiRegistryPort;
+    }
+
+    public int getRmiServerPort() {
+        return rmiServerPort;
+    }
+
+    public String getLocation() {
+        return location;
+    }
+
+    public String getJavaOpts() {
+        return javaOpts;
+    }
+
+    public List<String> getFeatureURLs() {
+        return featureURLs;
+    }
+
+    public List<String> getFeatures() {
+        return features;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (o == this) {
+            return true;
+        }
+        if (!(o instanceof InstanceSettings)) {
+            return false;
+        }
+        InstanceSettings is = (InstanceSettings) o;
+        return is.sshPort == sshPort &&
+               is.rmiRegistryPort == rmiRegistryPort &&
+               is.rmiServerPort == rmiServerPort &&
+               (location == null ? is.location == null : location.equals(is.location)) &&
+               (javaOpts == null ? is.javaOpts == null : javaOpts.equals(is.javaOpts)) &&
+               (featureURLs == null ? is.featureURLs == null : featureURLs.equals(is.featureURLs)) &&
+               (features == null ? is.features == null : features.equals(is.features));
+    }
+
+    @Override
+    public int hashCode() {
+        int result = sshPort + rmiRegistryPort + rmiServerPort;
+        result = 31 * result + (location != null ? location.hashCode() : 0);
+        result = 31 * result + (javaOpts != null ? javaOpts.hashCode() : 0);
+        result = 31 * result + (featureURLs != null ? featureURLs.hashCode() : 0);
+        result = 31 * result + (features != null ? features.hashCode() : 0);
+        return result;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/7c2db062/instance/src/main/java/org/apache/karaf/instance/core/InstancesMBean.java
----------------------------------------------------------------------
diff --git a/instance/src/main/java/org/apache/karaf/instance/core/InstancesMBean.java b/instance/src/main/java/org/apache/karaf/instance/core/InstancesMBean.java
new file mode 100644
index 0000000..f75e099
--- /dev/null
+++ b/instance/src/main/java/org/apache/karaf/instance/core/InstancesMBean.java
@@ -0,0 +1,55 @@
+/*
+ * 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.karaf.instance.core;
+
+import javax.management.MBeanException;
+import javax.management.openmbean.TabularData;
+
+public interface InstancesMBean {
+
+    String INSTANCE_PID = "Pid";
+    String INSTANCE_NAME = "Name";
+    String INSTANCE_IS_ROOT = "Is Root";
+    String INSTANCE_SSH_PORT = "SSH Port";
+    String INSTANCE_RMI_REGISTRY_PORT = "RMI Registry Port";
+    String INSTANCE_RMI_SERVER_PORT = "RMI Server Port";
+    String INSTANCE_STATE = "State";
+    String INSTANCE_LOCATION = "Location";
+    String INSTANCE_JAVAOPTS = "JavaOpts";
+
+    String[] INSTANCE = {INSTANCE_PID, INSTANCE_NAME, INSTANCE_IS_ROOT, INSTANCE_SSH_PORT, INSTANCE_RMI_REGISTRY_PORT,
+            INSTANCE_RMI_SERVER_PORT, INSTANCE_STATE, INSTANCE_LOCATION, INSTANCE_JAVAOPTS };
+
+    // Operations
+    int createInstance(String name, int sshPort, int rmiRegistryPort, int rmiServerPort, String location, String javaOpts, String features, String featureURLs) throws MBeanException;
+    void changeSshPort(String name, int port) throws MBeanException;
+    void changeRmiRegistryPort(String name, int port) throws MBeanException;
+    void changeRmiServerPort(String name, int port) throws MBeanException;
+    void changeJavaOpts(String name, String javaopts) throws MBeanException;
+    void destroyInstance(String name) throws MBeanException;
+    void startInstance(String name) throws MBeanException;
+    void startInstance(String name, String opts) throws MBeanException;
+    void startInstance(String name, String opts, boolean wait, boolean debug) throws MBeanException;
+    void stopInstance(String name) throws MBeanException;
+    void renameInstance(String originalName, String newName) throws MBeanException;
+    void renameInstance(String originalName, String newName, boolean verbose) throws MBeanException;
+    void cloneInstance(String name, String cloneName, int sshPort, int rmiRegistryPort, int rmiServerPort, String location, String javaOpts) throws MBeanException;
+
+    // Attributes
+    TabularData getInstances() throws MBeanException;
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/7c2db062/instance/src/main/java/org/apache/karaf/instance/core/internal/InstanceImpl.java
----------------------------------------------------------------------
diff --git a/instance/src/main/java/org/apache/karaf/instance/core/internal/InstanceImpl.java b/instance/src/main/java/org/apache/karaf/instance/core/internal/InstanceImpl.java
new file mode 100644
index 0000000..edc4ec5
--- /dev/null
+++ b/instance/src/main/java/org/apache/karaf/instance/core/internal/InstanceImpl.java
@@ -0,0 +1,110 @@
+/*
+ * 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.karaf.instance.core.internal;
+
+import org.apache.karaf.instance.core.Instance;
+
+public class InstanceImpl implements Instance {
+
+    private final InstanceServiceImpl service;
+    private String name;
+
+    public InstanceImpl(InstanceServiceImpl service, String name) {
+        this.service = service;
+        this.name = name;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        throw new UnsupportedOperationException();
+    }
+
+    void doSetName(String name) {
+        this.name = name;
+    }
+
+    public boolean isRoot() {
+        return service.isInstanceRoot(name);
+    }
+
+    public String getLocation() {
+        return service.getInstanceLocation(name);
+    }
+
+    public void setLocation(String location) {
+        throw new UnsupportedOperationException();
+    }
+
+    public int getPid() {
+        return service.getInstancePid(name);
+    }
+
+    public int getSshPort() {
+        return service.getInstanceSshPort(name);
+    }
+
+    public void changeSshPort(int port) throws Exception {
+        service.changeInstanceSshPort(name, port);
+    }
+
+    public int getRmiRegistryPort() {
+        return service.getInstanceRmiRegistryPort(name);
+    }
+
+    public void changeRmiRegistryPort(int port) throws Exception {
+        service.changeInstanceRmiRegistryPort(name, port);
+    }
+
+    public int getRmiServerPort() {
+        return service.getInstanceRmiServerPort(name);
+    }
+
+    public void changeRmiServerPort(int port) throws Exception {
+        service.changeInstanceRmiServerPort(name, port);
+    }
+
+    public String getJavaOpts() {
+        return service.getInstanceJavaOpts(name);
+    }
+
+    public void changeJavaOpts(String javaOpts) throws Exception {
+        service.changeInstanceJavaOpts(name, javaOpts);
+    }
+
+    public void start(String javaOpts) throws Exception {
+        service.startInstance(name, javaOpts);
+    }
+
+    public void stop() throws Exception {
+        service.stopInstance(name);
+    }
+
+    public void destroy() throws Exception {
+        service.destroyInstance(name);
+    }
+
+    public String getState() throws Exception {
+        return service.getInstanceState(name);
+    }
+
+    public boolean isAttached() {
+        return getPid() != 0;
+    }
+}
\ No newline at end of file


[41/59] [abbrv] [KARAF-2852] Merge system/core and system/command

Posted by gn...@apache.org.
http://git-wip-us.apache.org/repos/asf/karaf/blob/0a100d76/system/src/main/java/org/apache/karaf/system/SystemService.java
----------------------------------------------------------------------
diff --git a/system/src/main/java/org/apache/karaf/system/SystemService.java b/system/src/main/java/org/apache/karaf/system/SystemService.java
new file mode 100644
index 0000000..2f53946
--- /dev/null
+++ b/system/src/main/java/org/apache/karaf/system/SystemService.java
@@ -0,0 +1,130 @@
+ /*
+ * 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.karaf.system;
+
+/**
+ * Describe a system service
+ */
+public interface SystemService {
+
+    /**
+     * Types defining what to remove on a restart of Karaf
+     */
+    public enum Swipe {
+        /** Delete nothing; simple restart */
+        NONE,
+        /** Delete only the cache; everything else remains */
+        CACHE,
+        /** Forces a clean restart by removing the working directory; this option is compatible to the former clean method. */
+        ALL
+    }
+
+    /**
+     * Halt the Karaf container.
+     */
+    void halt() throws Exception;
+
+    /**
+     * Halt the Karaf container.
+     *
+     * @param time shutdown delay. The time argument can have different formats.
+     *  First, it can be an absolute time in the format hh:mm, in which hh is the hour (1 or 2 digits) and mm
+     *  is the minute of the hour (in two digits). Second, it can be in the format +m, in which m is the number of minutes
+     *  to wait. The word now is an alias for +0.
+     */
+    void halt(String time) throws Exception;
+
+    /**
+     * Reboot the Karaf container.
+     *
+     * @throws Exception
+     */
+    void reboot() throws Exception;
+
+    /**
+     * Reboot the Karaf container.
+     *
+     * @param time reboot delay. The time argument can have different formats.
+     *  First, it can be an absolute time in the format hh:mm, in which hh is the hour (1 or 2 digits) and mm
+     *  is the minute of the hour (in two digits). Second, it can be in the format +m, in which m is the number of minutes
+     *  to wait. The word now is an alias for +0.
+     *  @param clean Force a clean restart by deleting the working directory.
+     */
+    void reboot(String time, Swipe clean) throws Exception;
+
+    /**
+     * Set the system start level.
+     *
+     * @param startLevel the new system start level.
+     */
+    void setStartLevel(int startLevel) throws Exception;
+
+    /**
+     * Get the system start level.
+     *
+     * @return the current system start level.
+     */
+    int getStartLevel() throws Exception;
+
+    /**
+     * Get the version of the current Karaf instance
+     *
+     * @return instance version
+     */
+    String getVersion();
+
+    /**
+     * Get the name of the current Karaf instance
+     *
+     * @return instance name
+     */
+    String getName();
+    
+    /**
+     * Set the name of the Karaf instance
+     *
+     * @param name new instance name
+     */
+    void setName(String name);
+    
+    /**
+     * Get the current OSGi framework in use.
+     *
+     * @return the name of the OSGi framework in use.
+     * @throws Exception
+     */
+    FrameworkType getFramework();
+    
+    /**
+     * change OSGi framework
+     *
+     * @param framework to use.
+     */
+    void setFramework(FrameworkType framework);
+    
+    /**
+     * Enable or diable debgging
+     * @param debug enable if true
+     */
+    void setFrameworkDebug(boolean debug);
+
+    /**
+     * Set a system property and persist to etc/system.properties
+     * @param key
+     */
+    String setSystemProperty(String key, String value, boolean persist);
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/0a100d76/system/src/main/java/org/apache/karaf/system/commands/FrameworkOptions.java
----------------------------------------------------------------------
diff --git a/system/src/main/java/org/apache/karaf/system/commands/FrameworkOptions.java b/system/src/main/java/org/apache/karaf/system/commands/FrameworkOptions.java
new file mode 100644
index 0000000..9e16a7d
--- /dev/null
+++ b/system/src/main/java/org/apache/karaf/system/commands/FrameworkOptions.java
@@ -0,0 +1,73 @@
+/*
+ * 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.karaf.system.commands;
+
+import org.apache.karaf.shell.api.action.Action;
+import org.apache.karaf.shell.api.action.Argument;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.Option;
+import org.apache.karaf.shell.api.action.lifecycle.Reference;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.apache.karaf.system.FrameworkType;
+import org.apache.karaf.system.SystemService;
+
+/**
+ * Command for enabling/disabling debug logging on the OSGi framework
+ */
+@Command(scope = "system", name = "framework", description = "OSGi Framework options.")
+@Service
+public class FrameworkOptions implements Action {
+
+    @Option(name = "-debug", aliases={"--enable-debug"}, description="Enable debug for the OSGi framework", required = false, multiValued = false)
+    boolean debug;
+
+    @Option(name = "-nodebug", aliases={"--disable-debug"}, description="Disable debug for the OSGi framework", required = false, multiValued = false)
+    boolean nodebug;
+
+    @Argument(name = "framework", required = false, description = "Name of the OSGi framework to use")
+    String framework;
+
+    @Reference
+    SystemService systemService;
+
+    @Override
+    public Object execute() throws Exception {
+
+        if (!debug^nodebug && framework == null) {
+            System.out.printf("Current OSGi framework is %s%n", systemService.getFramework().name());
+            return null;
+        }
+        if (framework != null) {
+            FrameworkType frameworkType = FrameworkType.valueOf(framework);
+            systemService.setFramework(frameworkType);
+            System.out.println("Changed OSGi framework to " + frameworkType.toString().toLowerCase() + ". Karaf needs to be restarted to make the change effective");
+        }
+        if (debug) {
+            FrameworkType frameworkType = systemService.getFramework();
+            System.out.printf("Enabling debug for OSGi framework (%s)%n", frameworkType.name());
+            systemService.setFrameworkDebug(true);
+        }
+        if (nodebug) {
+            FrameworkType frameworkType = systemService.getFramework();
+            System.out.printf("Disabling debug for OSGi framework (%s)%n", frameworkType.name());
+            systemService.setFrameworkDebug(false);
+        }
+
+        return null;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/0a100d76/system/src/main/java/org/apache/karaf/system/commands/Name.java
----------------------------------------------------------------------
diff --git a/system/src/main/java/org/apache/karaf/system/commands/Name.java b/system/src/main/java/org/apache/karaf/system/commands/Name.java
new file mode 100644
index 0000000..a716d82
--- /dev/null
+++ b/system/src/main/java/org/apache/karaf/system/commands/Name.java
@@ -0,0 +1,51 @@
+/*
+ * 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.karaf.system.commands;
+
+
+import org.apache.karaf.shell.api.action.Action;
+import org.apache.karaf.shell.api.action.Argument;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.lifecycle.Reference;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.apache.karaf.system.SystemService;
+
+/**
+ * Command to shut down Karaf container.
+ */
+@Command(scope = "system", name = "name", description = "Show or change Karaf instance name.")
+@Service
+public class Name implements Action {
+
+    @Argument(name = "name", index = 0, description = "New name for the instance", required = false, multiValued = false)
+    String name;
+
+    @Reference
+    SystemService systemService;
+
+    @Override
+    public Object execute() throws Exception {
+        if (name == null) {
+            System.out.println(systemService.getName());
+        } else {
+            systemService.setName(name);
+            System.out.println("Instance name changed to " + name + ". Restart needed for this to take effect.");
+        }
+        return null;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/0a100d76/system/src/main/java/org/apache/karaf/system/commands/Shutdown.java
----------------------------------------------------------------------
diff --git a/system/src/main/java/org/apache/karaf/system/commands/Shutdown.java b/system/src/main/java/org/apache/karaf/system/commands/Shutdown.java
new file mode 100644
index 0000000..b8b4b41
--- /dev/null
+++ b/system/src/main/java/org/apache/karaf/system/commands/Shutdown.java
@@ -0,0 +1,104 @@
+/*
+ * 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.karaf.system.commands;
+
+import org.apache.karaf.shell.api.action.Action;
+import org.apache.karaf.shell.api.action.Argument;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.Option;
+import org.apache.karaf.shell.api.action.lifecycle.Reference;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.apache.karaf.shell.api.console.Session;
+import org.apache.karaf.system.SystemService;
+
+/**
+ * Command to shut down Karaf container.
+ */
+@Command(scope = "system", name = "shutdown", description = "Shutdown Karaf.")
+@Service
+public class Shutdown implements Action {
+
+    @Option(name = "-f", aliases = "--force", description = "Force the shutdown without confirmation message.", required = false, multiValued = false)
+    boolean force = false;
+
+    @Option(name = "-r", aliases = "--reboot", description = "Reboot the Karaf container.", required = false, multiValued = false)
+    boolean reboot = false;
+
+    @Option(name = "-h", aliases = "--halt", description = "Halt the Karaf container.", required = false, multiValued = false)
+    boolean halt = false;
+
+    @Option(name = "-c", aliases = {"--clean", "--clean-all", "-ca"}, description = "Force a clean restart by deleting the data directory")
+    private boolean cleanAll;
+
+    @Option(name = "-cc", aliases = {"--clean-cache", "-cc"}, description = "Force a clean restart by deleting the cache directory")
+    private boolean cleanCache;
+
+
+    @Argument(name = "time", index = 0, description = "Shutdown after a specified delay. The time argument can have different" +
+            " formats. First, it can be an absolute time in the format hh:mm, in which hh is the hour (1 or 2 digits) and mm" +
+            " is the minute of the hour (in two digits). Second, it can be in the format +m, in which m is the number of minutes" +
+            " to wait. The word now is an alias for +0.", required = false, multiValued = false)
+    String time;
+
+    @Reference
+    SystemService systemService;
+
+    @Reference
+    Session session;
+
+    @Override
+    public Object execute() throws Exception {
+
+        if (force) {
+            if (reboot) {
+                systemService.reboot(time, determineSwipeType());
+            } else {
+                systemService.halt(time);
+            }
+            return null;
+        }
+
+        for (; ; ) {
+            String karafName = System.getProperty("karaf.name");
+            String msg;
+            if (reboot) {
+                msg = String.format("Confirm: reboot instance %s (yes/no): ", karafName);
+            } else {
+                msg = String.format("Confirm: halt instance %s (yes/no): ", karafName);
+            }
+            String str = session.readLine(msg, null);
+            if (str.equalsIgnoreCase("yes")) {
+                if (reboot) {
+                    systemService.reboot(time, determineSwipeType());
+                } else {
+                    systemService.halt(time);
+                }
+            }
+            return null;
+        }
+    }
+
+    private SystemService.Swipe determineSwipeType() {
+        if (cleanAll) {
+            return SystemService.Swipe.ALL;
+        } else if (cleanCache) {
+            return SystemService.Swipe.CACHE;
+        }
+        return SystemService.Swipe.NONE;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/0a100d76/system/src/main/java/org/apache/karaf/system/commands/StartLevel.java
----------------------------------------------------------------------
diff --git a/system/src/main/java/org/apache/karaf/system/commands/StartLevel.java b/system/src/main/java/org/apache/karaf/system/commands/StartLevel.java
new file mode 100644
index 0000000..e91c15a
--- /dev/null
+++ b/system/src/main/java/org/apache/karaf/system/commands/StartLevel.java
@@ -0,0 +1,49 @@
+/*
+ * 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.karaf.system.commands;
+
+import org.apache.karaf.shell.api.action.Action;
+import org.apache.karaf.shell.api.action.Argument;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.lifecycle.Reference;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.apache.karaf.system.SystemService;
+
+/**
+ * Get/set the system start level.
+ */
+@Command(scope = "system", name = "start-level", description = "Gets or sets the system start level.")
+@Service
+public class StartLevel implements Action {
+
+    @Argument(index = 0, name = "level", description = "The new system start level to set", required = false, multiValued = false)
+    Integer level;
+
+    @Reference
+    SystemService systemService;
+
+    @Override
+    public Object execute() throws Exception {
+        if (level == null) {
+            System.out.println("Level " + systemService.getStartLevel());
+        } else {
+            systemService.setStartLevel(level);
+        }
+        return null;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/0a100d76/system/src/main/java/org/apache/karaf/system/commands/SystemProperty.java
----------------------------------------------------------------------
diff --git a/system/src/main/java/org/apache/karaf/system/commands/SystemProperty.java b/system/src/main/java/org/apache/karaf/system/commands/SystemProperty.java
new file mode 100644
index 0000000..37c2a1e
--- /dev/null
+++ b/system/src/main/java/org/apache/karaf/system/commands/SystemProperty.java
@@ -0,0 +1,157 @@
+/*
+ * 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.karaf.system.commands;
+
+import java.io.File;
+import java.io.PrintStream;
+import java.text.SimpleDateFormat;
+import java.util.Collections;
+import java.util.Date;
+import java.util.Iterator;
+import java.util.Properties;
+import java.util.Set;
+import java.util.Vector;
+
+import org.apache.karaf.shell.api.action.Action;
+import org.apache.karaf.shell.api.action.Argument;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.Option;
+import org.apache.karaf.shell.api.action.lifecycle.Reference;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.apache.karaf.system.SystemService;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+
+/**
+ * Command that allow access to system properties easily.
+ */
+@Command(scope = "system", name = "property", description = "Get or set a system property.")
+@Service
+public class SystemProperty implements Action {
+
+    @Option(name = "-p", aliases = {"--persistent"}, description = "Persist the new value to the etc/system.properties file")
+    boolean persistent;
+
+    @Option(name = "-f", aliases = {"--file-dump"}, description = "Dump all system properties in a file (in data folder)")
+    boolean dumpToFile;
+
+    @Option(name = "-u", aliases = {"--unset"}, description = "Show unset know properties with value unset")
+    boolean unset;
+
+    @Argument(index = 0, name = "key", required = false, description = "The system property name")
+    String key;
+
+    @Argument(index = 1, name = "value", required = false, description = "New value for the system property")
+    String value;
+
+    @Reference
+    BundleContext bundleContext;
+
+    @Reference
+    SystemService systemService;
+
+    @Override
+    public Object execute() throws Exception {
+        if (key == null && value == null) {
+            Properties props = (Properties) System.getProperties().clone();
+
+            String def = null;
+            if (unset) {
+                def = "unset";
+            }
+
+            setProperty(props, Constants.FRAMEWORK_BEGINNING_STARTLEVEL, def);
+            setProperty(props, Constants.FRAMEWORK_BOOTDELEGATION, def);
+            setProperty(props, Constants.FRAMEWORK_BUNDLE_PARENT, def);
+            setProperty(props, Constants.FRAMEWORK_BUNDLE_PARENT_APP, def);
+            setProperty(props, Constants.FRAMEWORK_BUNDLE_PARENT_BOOT, def);
+            setProperty(props, Constants.FRAMEWORK_BUNDLE_PARENT_EXT, def);
+            setProperty(props, Constants.FRAMEWORK_BUNDLE_PARENT_FRAMEWORK, def);
+            setProperty(props, Constants.FRAMEWORK_EXECPERMISSION, def);
+            setProperty(props, Constants.FRAMEWORK_EXECUTIONENVIRONMENT, def);
+            setProperty(props, Constants.FRAMEWORK_LANGUAGE, def);
+            setProperty(props, Constants.FRAMEWORK_LIBRARY_EXTENSIONS, def);
+            setProperty(props, Constants.FRAMEWORK_OS_NAME, def);
+            setProperty(props, Constants.FRAMEWORK_OS_VERSION, def);
+            setProperty(props, Constants.FRAMEWORK_PROCESSOR, def);
+            setProperty(props, Constants.FRAMEWORK_SECURITY, def);
+            setProperty(props, Constants.FRAMEWORK_SECURITY_OSGI, def);
+            setProperty(props, Constants.FRAMEWORK_STORAGE, def);
+            setProperty(props, Constants.FRAMEWORK_STORAGE_CLEAN_ONFIRSTINIT, def);
+            setProperty(props, Constants.FRAMEWORK_SYSTEMPACKAGES, def);
+            setProperty(props, Constants.FRAMEWORK_SYSTEMPACKAGES_EXTRA, def);
+            setProperty(props, Constants.FRAMEWORK_VENDOR, def);
+            setProperty(props, Constants.FRAMEWORK_VERSION, def);
+            setProperty(props, Constants.FRAMEWORK_WINDOWSYSTEM, def);
+
+            setProperty(props, Constants.SUPPORTS_BOOTCLASSPATH_EXTENSION, def);
+            setProperty(props, Constants.SUPPORTS_FRAMEWORK_EXTENSION, def);
+            setProperty(props, Constants.SUPPORTS_FRAMEWORK_FRAGMENT, def);
+            setProperty(props, Constants.SUPPORTS_FRAMEWORK_REQUIREBUNDLE, def);
+
+            if (dumpToFile) {
+                PrintStream ps = new PrintStream(
+                        new File(
+                                bundleContext.getProperty("karaf.data"),
+                                "dump-properties-" + System.currentTimeMillis() + ".properties"
+                        )
+                );
+                ps.println("#Dump of the System and OSGi properties with the command system:property");
+                ps.println("#Dump executed at " + new SimpleDateFormat().format(new Date()));
+                printOrderedProperties(props, ps);
+                ps.flush();
+                ps.close();
+            } else {
+                printOrderedProperties(props, System.out);
+            }
+
+            return null;
+        }
+
+        if (value != null) {
+            systemService.setSystemProperty(key, value, persistent);
+        } else {
+            System.out.println(System.getProperty(key));
+        }
+
+        return null;
+    }
+
+    private void printOrderedProperties(Properties props, PrintStream out) {
+        Set<Object> keys = props.keySet();
+        Vector<String> order = new Vector<String>(keys.size());
+        for (Iterator<Object> i = keys.iterator(); i.hasNext(); ) {
+            Object str = (Object) i.next();
+            order.add((String) str);
+        }
+        Collections.sort(order);
+        for (Iterator<String> i = order.iterator(); i.hasNext(); ) {
+            String key = (String) i.next();
+            out.println(key + "=" + props.getProperty(key));
+        }
+    }
+
+    private void setProperty(Properties props, String key, String def) {
+        String val = bundleContext.getProperty(key);
+        if (val == null && def != null) {
+            props.setProperty(key, def);
+        } else if (val != null) {
+            props.setProperty(key, val);
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/0a100d76/system/src/main/java/org/apache/karaf/system/commands/Version.java
----------------------------------------------------------------------
diff --git a/system/src/main/java/org/apache/karaf/system/commands/Version.java b/system/src/main/java/org/apache/karaf/system/commands/Version.java
new file mode 100644
index 0000000..9837aaa
--- /dev/null
+++ b/system/src/main/java/org/apache/karaf/system/commands/Version.java
@@ -0,0 +1,38 @@
+/*
+ * 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.karaf.system.commands;
+
+import org.apache.karaf.shell.api.action.Action;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.lifecycle.Reference;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.apache.karaf.system.SystemService;
+
+@Command(scope = "system", name = "version", description = "Display the instance version")
+@Service
+public class Version implements Action {
+
+    @Reference
+    SystemService systemService;
+
+    @Override
+    public Object execute() throws Exception {
+        System.out.println(systemService.getVersion());
+        return null;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/0a100d76/system/src/main/java/org/apache/karaf/system/internal/SystemServiceImpl.java
----------------------------------------------------------------------
diff --git a/system/src/main/java/org/apache/karaf/system/internal/SystemServiceImpl.java b/system/src/main/java/org/apache/karaf/system/internal/SystemServiceImpl.java
new file mode 100644
index 0000000..8fa5a38
--- /dev/null
+++ b/system/src/main/java/org/apache/karaf/system/internal/SystemServiceImpl.java
@@ -0,0 +1,238 @@
+/*
+* 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.karaf.system.internal;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.Calendar;
+import java.util.GregorianCalendar;
+
+import org.apache.felix.utils.properties.Properties;
+import org.apache.karaf.system.FrameworkType;
+import org.apache.karaf.system.SystemService;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.startlevel.FrameworkStartLevel;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Implementation of the system service.
+ */
+public class SystemServiceImpl implements SystemService {
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(SystemServiceImpl.class);
+
+    private BundleContext bundleContext;
+
+    public void setBundleContext(BundleContext bundleContext) {
+        this.bundleContext = bundleContext;
+    }
+
+    public BundleContext getBundleContext() {
+        return this.bundleContext;
+    }
+
+    public void halt() throws Exception {
+        halt(null);
+    }
+
+    public void halt(String time) throws Exception {
+        shutdown(timeToSleep(time));
+    }
+
+    public void reboot() throws Exception {
+        reboot(null, Swipe.NONE);
+    }
+
+    public void reboot(String time, Swipe cleanup) throws Exception {
+        reboot(timeToSleep(time), cleanup);
+    }
+
+    private void shutdown(final long sleep) {
+        new Thread() {
+            public void run() {
+                try {
+                    sleepWithMsg(sleep, "Shutdown in " + sleep / 1000 / 60 + " minute(s)");
+                    getBundleContext().getBundle(0).stop();
+                } catch (Exception e) {
+                    LOGGER.error("Halt error", e);
+                }
+            }
+        }.start();
+    }
+
+    private void reboot(final long sleep, final Swipe clean) {
+        new Thread() {
+            public void run() {
+                try {
+                    sleepWithMsg(sleep, "Reboot in " + sleep / 1000 / 60 + " minute(s)");
+                    System.setProperty("karaf.restart", "true");
+                    if (clean.equals(Swipe.ALL)) {
+                        System.setProperty("karaf.clean.all", "true");
+                    } else if (clean.equals(Swipe.CACHE)) {
+                        System.setProperty("karaf.clean.cache", "true");
+                    }
+                    bundleContext.getBundle(0).stop();
+                } catch (Exception e) {
+                    LOGGER.error("Reboot error", e);
+                }
+            }
+        }.start();
+    }
+    
+    private void sleepWithMsg(final long sleep, String msg)
+            throws InterruptedException {
+        if (sleep > 0) {
+            LOGGER.info(msg);
+            System.err.println(msg);
+        }
+        Thread.sleep(sleep);
+    }
+
+    public void setStartLevel(int startLevel) throws Exception {
+        getBundleContext().getBundle(0).adapt(FrameworkStartLevel.class).setStartLevel(startLevel);
+    }
+
+    public int getStartLevel() throws Exception {
+        return getBundleContext().getBundle(0).adapt(FrameworkStartLevel.class).getStartLevel();
+    }
+
+    /**
+     * Convert a time string to sleep period (in millisecond).
+     *
+     * @param time the time string.
+     * @return the corresponding sleep period in millisecond.
+     */
+    private long timeToSleep(String time) throws Exception {
+        long sleep = 0;
+        if (time != null) {
+            if (!time.equals("now")) {
+                if (time.startsWith("+")) {
+                    // delay in number of minutes provided
+                    time = time.substring(1);
+                    try {
+                        sleep = Long.parseLong(time) * 60 * 1000;
+                    } catch (Exception e) {
+                        throw new IllegalArgumentException("Time " + time + " is not valid");
+                    }
+                } else {
+                    // try to parse the date in hh:mm
+                    String[] strings = time.split(":");
+                    if (strings.length != 2) {
+                        throw new IllegalArgumentException("Time " + time + " is not valid");
+                    }
+                    GregorianCalendar currentDate = new GregorianCalendar();
+                    GregorianCalendar shutdownDate = new GregorianCalendar(currentDate.get(Calendar.YEAR), currentDate.get(Calendar.MONTH), currentDate.get(Calendar.DATE), Integer.parseInt(strings[0]), Integer.parseInt(strings[1]));
+                    if (shutdownDate.before(currentDate)) {
+                        shutdownDate.set(Calendar.DATE, shutdownDate.get(Calendar.DATE) + 1);
+                    }
+                    sleep = shutdownDate.getTimeInMillis() - currentDate.getTimeInMillis();
+                }
+            }
+        }
+        return sleep;
+    }
+
+    @Override
+    public String getVersion() {
+        return System.getProperty("karaf.version");
+    }
+
+    @Override
+    public String getName() {
+        return bundleContext.getProperty("karaf.name");
+    }
+
+    @Override
+    public void setName(String name) {
+        try {
+            String karafEtc = bundleContext.getProperty("karaf.etc");
+            File etcDir = new File(karafEtc);
+            File syspropsFile = new File(etcDir, "system.properties");
+            FileInputStream fis = new FileInputStream(syspropsFile);
+            Properties props = new Properties();
+            props.load(fis);
+            fis.close();
+            props.setProperty("karaf.name", name);
+            FileOutputStream fos = new FileOutputStream(syspropsFile);
+            props.store(fos, "");
+            fos.close();
+        } catch (Exception e) {
+            throw new RuntimeException(e.getMessage(), e);
+        }
+    }
+    
+    public FrameworkType getFramework() {
+        if (bundleContext.getBundle(0).getSymbolicName().contains("felix")) {
+            return FrameworkType.felix;
+        } else {
+            return FrameworkType.equinox;
+        }
+    }
+
+    private Properties loadProps() throws IOException {
+        return new Properties(new File(System.getProperty("karaf.etc"), "config.properties"));
+    }
+
+    public void setFramework(FrameworkType framework) {
+        if (framework == null) {
+            return;
+        }
+        try {
+            Properties properties = loadProps();
+            properties.put("karaf.framework", framework.name());
+            properties.save();
+        } catch (IOException e) {
+            throw new RuntimeException("Error setting framework: " + e.getMessage(), e);
+        }
+    }
+
+    public void setFrameworkDebug(boolean debug) {
+        try {
+            Properties properties = loadProps();
+            if (debug) {
+                properties.put("felix.log.level", "4");
+                properties.put("osgi.debug", "etc/equinox-debug.properties");
+            } else {
+                properties.remove("felix.log.level");
+                properties.remove("osgi.debug");
+            }
+            // TODO populate the equinox-debug.properties file with the one provided in shell/dev module
+            properties.save();
+        } catch (IOException e) {
+            throw new RuntimeException("Error settting framework debugging: " + e.getMessage(), e);
+        }
+    }
+
+    @Override
+    public String setSystemProperty(String key, String value, boolean persist) {
+        if (persist) {
+            try {
+                String etc = System.getProperty("karaf.etc");
+                Properties props = new Properties(new File(etc, "system.properties"));
+                props.put(key, value);
+                props.save();
+            } catch (IOException e) {
+                throw new RuntimeException("Error persisting system property", e);
+            }
+        }
+        return System.setProperty(key, value);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/0a100d76/system/src/main/java/org/apache/karaf/system/internal/osgi/Activator.java
----------------------------------------------------------------------
diff --git a/system/src/main/java/org/apache/karaf/system/internal/osgi/Activator.java b/system/src/main/java/org/apache/karaf/system/internal/osgi/Activator.java
new file mode 100644
index 0000000..b7f8eab
--- /dev/null
+++ b/system/src/main/java/org/apache/karaf/system/internal/osgi/Activator.java
@@ -0,0 +1,38 @@
+/*
+ * 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.karaf.system.internal.osgi;
+
+import org.apache.karaf.system.SystemService;
+import org.apache.karaf.system.internal.SystemServiceImpl;
+import org.apache.karaf.system.management.internal.SystemMBeanImpl;
+import org.apache.karaf.util.tracker.BaseActivator;
+
+public class Activator extends BaseActivator {
+
+    @Override
+    protected void doStart() throws Exception {
+        SystemServiceImpl systemService = new SystemServiceImpl();
+        systemService.setBundleContext(bundleContext);
+        register(SystemService.class, systemService);
+
+        SystemMBeanImpl mbean = new SystemMBeanImpl();
+        mbean.setBundleContext(bundleContext);
+        mbean.setSystemService(systemService);
+        registerMBean(mbean, "type=system");
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/0a100d76/system/src/main/java/org/apache/karaf/system/management/SystemMBean.java
----------------------------------------------------------------------
diff --git a/system/src/main/java/org/apache/karaf/system/management/SystemMBean.java b/system/src/main/java/org/apache/karaf/system/management/SystemMBean.java
new file mode 100644
index 0000000..5d9bdbc
--- /dev/null
+++ b/system/src/main/java/org/apache/karaf/system/management/SystemMBean.java
@@ -0,0 +1,157 @@
+/*
+ * 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.karaf.system.management;
+
+import javax.management.MBeanException;
+import java.util.Map;
+
+/**
+ * Describe the system MBean.
+ */
+public interface SystemMBean {
+
+    /**
+     * Stop the Karaf instance
+     *
+     * @throws Exception
+     */
+    void halt() throws MBeanException;
+
+    /**
+     * Stop the Karaf instance at a given time.
+     *
+     * @param time the time when to stop the Karaf instance.
+     * @throws Exception
+     */
+    void halt(String time) throws MBeanException;
+
+    /**
+     * Reboot the Karaf instance.
+     *
+     * @throws Exception
+     */
+    void reboot() throws MBeanException;
+
+    /**
+     * Reboot the Karaf instance at a given time.
+     *
+     * @param time the time when to reboot the Karaf instance.
+     * @throws Exception
+     */
+    void reboot(String time) throws MBeanException;
+
+    /**
+     * Reboot the Karaf instance at a given time and clean the cache.
+     *
+     * @param time the time when to reboot the Karaf instance.
+     * @throws Exception
+     */
+    void rebootCleanCache(String time) throws MBeanException;
+
+    /**
+     * Reboot the Karaf instance at a given time and clean all working files.
+     *
+     * @param time the time when to reboot the Karaf instance.
+     * @throws Exception
+     */
+    void rebootCleanAll(String time) throws MBeanException;
+
+    /**
+     * Set the system bundle start level.
+     *
+     * @param startLevel the new system bundle start level.
+     * @throws Exception
+     */
+    void setStartLevel(int startLevel) throws MBeanException;
+
+    /**
+     * Get the current system bundle start level.
+     *
+     * @return the current system bundle start level.
+     * @throws Exception
+     */
+    int getStartLevel() throws MBeanException;
+
+    /**
+     * Get the current OSGi framework in use.
+     *
+     * @return the name of the OSGi framework in use.
+     * @throws Exception
+     */
+    String getFramework();
+
+    /**
+     * change OSGi framework
+     *
+     * @param framework to use.
+     */
+    void setFramework(String framework);
+    
+    /**
+     * Enable or diable debgging
+     * @param debug enable if true
+     */
+    void setFrameworkDebug(boolean debug);
+
+    /**
+     * Get the current Karaf instance name.
+     *
+     * @return the current Karaf instance name.
+     */
+    String getName();
+
+    /**
+     * Change Karaf instance name.
+     *
+     * @param name the new Karaf instance name.
+     */
+    void setName(String name);
+
+    /**
+     * Get the version of the current Karaf instance.
+     *
+     * @return the current Karaf instance version.
+     */
+    String getVersion();
+
+    /**
+     * Get all system properties.
+     *
+     * @param unset if true, display the OSGi properties even if they are not defined (with "undef" value).
+     * @param dumpToFile if true, dump the properties into a file in the data folder.
+     * @return the list of system properties.
+     */
+    Map<String, String> getProperties(boolean unset, boolean dumpToFile) throws MBeanException;
+
+    /**
+     * Get the value of a given system property.
+     *
+     * @param key the system property key.
+     * @return the system property value.
+     */
+    String getProperty(String key);
+
+    /**
+     * Set the value of a system property.
+     *
+     * @param key the system property key.
+     * @param value the new system property value.
+     * @param persistent if true, persist the new value to the etc/system.properties file.
+     */
+    void setProperty(String key, String value, boolean persistent);
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/0a100d76/system/src/main/java/org/apache/karaf/system/management/internal/SystemMBeanImpl.java
----------------------------------------------------------------------
diff --git a/system/src/main/java/org/apache/karaf/system/management/internal/SystemMBeanImpl.java b/system/src/main/java/org/apache/karaf/system/management/internal/SystemMBeanImpl.java
new file mode 100644
index 0000000..c0f34cd
--- /dev/null
+++ b/system/src/main/java/org/apache/karaf/system/management/internal/SystemMBeanImpl.java
@@ -0,0 +1,259 @@
+/*
+ * 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.karaf.system.management.internal;
+
+import org.apache.karaf.system.FrameworkType;
+import org.apache.karaf.system.SystemService;
+import org.apache.karaf.system.management.SystemMBean;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+
+import javax.management.MBeanException;
+import javax.management.NotCompliantMBeanException;
+import javax.management.StandardMBean;
+import java.io.File;
+import java.io.PrintStream;
+import java.text.SimpleDateFormat;
+import java.util.*;
+
+/**
+ * System MBean implementation.
+ */
+public class SystemMBeanImpl extends StandardMBean implements SystemMBean {
+
+    private SystemService systemService;
+    private BundleContext bundleContext;
+
+    public void setBundleContext(BundleContext bundleContext) {
+        this.bundleContext = bundleContext;
+    }
+
+    public SystemMBeanImpl() throws NotCompliantMBeanException {
+        super(SystemMBean.class);
+    }
+
+    public void setSystemService(SystemService systemService) {
+        this.systemService = systemService;
+    }
+
+    public SystemService getSystemService() {
+        return this.systemService;
+    }
+
+    public void halt() throws MBeanException {
+        try {
+            systemService.halt();
+        } catch (Exception e) {
+            throw new MBeanException(null, e.getMessage());
+        }
+    }
+
+    public void halt(String time) throws MBeanException {
+        try {
+            systemService.halt(time);
+        } catch (Exception e) {
+            throw new MBeanException(null, e.getMessage());
+        }
+    }
+
+    public void reboot() throws MBeanException {
+        try {
+            systemService.reboot();
+        } catch (Exception e) {
+            throw new MBeanException(null, e.getMessage());
+        }
+    }
+
+    public void reboot(String time) throws MBeanException {
+        try {
+            systemService.reboot(time, SystemService.Swipe.NONE);
+        } catch (Exception e) {
+            throw new MBeanException(null, e.getMessage());
+        }
+    }
+
+    public void rebootCleanCache(String time) throws MBeanException {
+        try {
+            systemService.reboot(time, SystemService.Swipe.CACHE);
+        } catch (Exception e) {
+            throw new MBeanException(null, e.getMessage());
+        }
+    }
+
+    public void rebootCleanAll(String time) throws MBeanException {
+        try {
+            systemService.reboot(time, SystemService.Swipe.ALL);
+        } catch (Exception e) {
+            throw new MBeanException(null, e.getMessage());
+        }
+    }
+
+    public void setStartLevel(int startLevel) throws MBeanException {
+        try {
+            systemService.setStartLevel(startLevel);
+        } catch (Exception e) {
+            throw new MBeanException(null, e.getMessage());
+        }
+    }
+
+    public int getStartLevel() throws MBeanException {
+        try {
+            return systemService.getStartLevel();
+        } catch (Exception e) {
+            throw new MBeanException(null, e.getMessage());
+        }
+    }
+
+    @Override
+    public String getFramework() {
+        return this.systemService.getFramework().toString();
+    }
+
+    @Override
+    public void setFramework(String framework) {
+        this.systemService.setFramework(FrameworkType.valueOf(framework.toLowerCase()));
+    }
+
+    @Override
+    public void setFrameworkDebug(boolean debug) {
+        this.systemService.setFrameworkDebug(debug);
+    }
+
+    @Override
+    public String getName() {
+        return this.systemService.getName();
+    }
+
+    @Override
+    public void setName(String name) {
+        if (name == null || name.trim().isEmpty()) {
+            throw new IllegalArgumentException("Instance name can't be null or empty");
+        }
+        this.systemService.setName(name);
+    }
+
+    @Override
+    public String getVersion() {
+        return this.systemService.getVersion();
+    }
+
+    @Override
+    public Map<String, String> getProperties(boolean unset, boolean dumpToFile) throws MBeanException {
+        try {
+            Map<String, String> result = new HashMap<String, String>();
+
+            Properties props = (Properties) java.lang.System.getProperties().clone();
+
+            String def = null;
+            if (unset) {
+                def = "unset";
+            }
+
+            setProperty(props, Constants.FRAMEWORK_BEGINNING_STARTLEVEL, def);
+            setProperty(props, Constants.FRAMEWORK_BOOTDELEGATION, def);
+            setProperty(props, Constants.FRAMEWORK_BUNDLE_PARENT, def);
+            setProperty(props, Constants.FRAMEWORK_BUNDLE_PARENT_APP, def);
+            setProperty(props, Constants.FRAMEWORK_BUNDLE_PARENT_BOOT, def);
+            setProperty(props, Constants.FRAMEWORK_BUNDLE_PARENT_EXT, def);
+            setProperty(props, Constants.FRAMEWORK_BUNDLE_PARENT_FRAMEWORK, def);
+            setProperty(props, Constants.FRAMEWORK_EXECPERMISSION, def);
+            setProperty(props, Constants.FRAMEWORK_EXECUTIONENVIRONMENT, def);
+            setProperty(props, Constants.FRAMEWORK_LANGUAGE, def);
+            setProperty(props, Constants.FRAMEWORK_LIBRARY_EXTENSIONS, def);
+            setProperty(props, Constants.FRAMEWORK_OS_NAME, def);
+            setProperty(props, Constants.FRAMEWORK_OS_VERSION, def);
+            setProperty(props, Constants.FRAMEWORK_PROCESSOR, def);
+            setProperty(props, Constants.FRAMEWORK_SECURITY, def);
+            setProperty(props, Constants.FRAMEWORK_SECURITY_OSGI, def);
+            setProperty(props, Constants.FRAMEWORK_STORAGE, def);
+            setProperty(props, Constants.FRAMEWORK_STORAGE_CLEAN_ONFIRSTINIT, def);
+            setProperty(props, Constants.FRAMEWORK_SYSTEMPACKAGES, def);
+            setProperty(props, Constants.FRAMEWORK_SYSTEMPACKAGES_EXTRA, def);
+            setProperty(props, Constants.FRAMEWORK_VENDOR, def);
+            setProperty(props, Constants.FRAMEWORK_VERSION, def);
+            setProperty(props, Constants.FRAMEWORK_WINDOWSYSTEM, def);
+
+            setProperty(props, Constants.SUPPORTS_BOOTCLASSPATH_EXTENSION, def);
+            setProperty(props, Constants.SUPPORTS_FRAMEWORK_EXTENSION, def);
+            setProperty(props, Constants.SUPPORTS_FRAMEWORK_FRAGMENT, def);
+            setProperty(props, Constants.SUPPORTS_FRAMEWORK_REQUIREBUNDLE, def);
+
+            if (dumpToFile) {
+                PrintStream ps = new PrintStream(new File(bundleContext.getProperty("karaf.data"), "dump-properties-" + java.lang.System.currentTimeMillis() + ".properties"));
+                ps.println("#Dump of the System and OSGi properties");
+                ps.println("#Dump executed at " + new SimpleDateFormat().format(new Date()));
+                printOrderedProperties(props, ps);
+                ps.flush();
+                ps.close();
+            } else {
+                printOrderedProperties(props, result);
+            }
+
+            return result;
+        } catch (Exception e) {
+            throw new MBeanException(null, e.getMessage());
+        }
+    }
+
+    private void printOrderedProperties(Properties props, PrintStream out) {
+        Set<Object> keys = props.keySet();
+        Vector<String> order = new Vector<String>(keys.size());
+        for (Iterator<Object> i = keys.iterator(); i.hasNext(); ) {
+            Object str = (Object) i.next();
+            order.add((String) str);
+        }
+        Collections.sort(order);
+        for (Iterator<String> i = order.iterator(); i.hasNext(); ) {
+            String key = (String) i.next();
+            out.println(key + "=" + props.getProperty(key));
+        }
+    }
+
+    private void printOrderedProperties(Properties props, Map<String, String> result) {
+        Set<Object> keys = props.keySet();
+        Vector<String> order = new Vector<String>(keys.size());
+        for (Iterator<Object> i = keys.iterator(); i.hasNext(); ) {
+            Object str = (Object) i.next();
+            order.add((String) str);
+        }
+        Collections.sort(order);
+        for (Iterator<String> i = order.iterator(); i.hasNext(); ) {
+            String key = (String) i.next();
+            result.put(key, props.getProperty(key));
+        }
+    }
+
+    private void setProperty(Properties props, String key, String def) {
+        String val = bundleContext.getProperty(key);
+        if (val == null && def != null) {
+            props.setProperty(key, def);
+        } else if (val != null) {
+            props.setProperty(key, val);
+        }
+    }
+
+    @Override
+    public String getProperty(String key) {
+        return java.lang.System.getProperty(key);
+    }
+
+    @Override
+    public void setProperty(String key, String value, boolean persistent) {
+        systemService.setSystemProperty(key, value, persistent);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/0a100d76/system/src/main/resources/OSGI-INF/bundle.info
----------------------------------------------------------------------
diff --git a/system/src/main/resources/OSGI-INF/bundle.info b/system/src/main/resources/OSGI-INF/bundle.info
new file mode 100644
index 0000000..acca1c8
--- /dev/null
+++ b/system/src/main/resources/OSGI-INF/bundle.info
@@ -0,0 +1,16 @@
+h1. Synopsis
+
+${project.name}
+
+${project.description}
+
+Maven URL:
+[mvn:${project.groupId}/${project.artifactId}/${project.version}]
+
+h1. Description
+
+This bundle provides support of the system service, which control the Karaf container.
+
+h1. See also
+
+Shutdown - section of the Karaf User Guide

http://git-wip-us.apache.org/repos/asf/karaf/blob/0a100d76/system/src/test/java/org/apache/karaf/system/internal/SystemServiceImplTest.java
----------------------------------------------------------------------
diff --git a/system/src/test/java/org/apache/karaf/system/internal/SystemServiceImplTest.java b/system/src/test/java/org/apache/karaf/system/internal/SystemServiceImplTest.java
new file mode 100644
index 0000000..2de4e1e
--- /dev/null
+++ b/system/src/test/java/org/apache/karaf/system/internal/SystemServiceImplTest.java
@@ -0,0 +1,53 @@
+/*
+* 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.karaf.system.internal;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.net.URL;
+
+import org.apache.felix.utils.properties.Properties;
+import org.easymock.EasyMock;
+import org.junit.Assert;
+import org.junit.Test;
+import org.osgi.framework.BundleContext;
+
+/**
+ * Implementation of the system service.
+ */
+
+public class SystemServiceImplTest {
+
+    private static final String NEW_NAME = "newName";
+
+    @Test
+    public void testSetName() throws URISyntaxException, IOException {
+        SystemServiceImpl system = new SystemServiceImpl();
+        BundleContext bundleContext = EasyMock.createMock(BundleContext.class);
+        URL propUrl = this.getClass().getClassLoader().getResource("etc/system.properties");
+        File propfile = new File(propUrl.toURI());        
+        EasyMock.expect(bundleContext.getProperty("karaf.etc")).andReturn(propfile.getParentFile().getParent() + "/etc");
+        EasyMock.replay(bundleContext);
+        system.setBundleContext(bundleContext);
+        system.setName(NEW_NAME);
+        EasyMock.verify(bundleContext);
+        Properties props = new Properties(propfile);
+        String nameAfter = props.getProperty("karaf.name");
+        Assert.assertEquals(NEW_NAME, nameAfter);
+    }
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/0a100d76/system/src/test/resources/etc/system.properties
----------------------------------------------------------------------
diff --git a/system/src/test/resources/etc/system.properties b/system/src/test/resources/etc/system.properties
new file mode 100644
index 0000000..6749fbb
--- /dev/null
+++ b/system/src/test/resources/etc/system.properties
@@ -0,0 +1,22 @@
+################################################################################
+#
+#    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.
+#
+################################################################################
+
+#Comment
+karaf.name=oldName
+#Comment2


[23/59] [abbrv] [KARAF-2852] Merge config/core and config/command

Posted by gn...@apache.org.
http://git-wip-us.apache.org/repos/asf/karaf/blob/d33e0955/config/core/src/main/java/org/apache/karaf/config/core/impl/ConfigMBeanImpl.java
----------------------------------------------------------------------
diff --git a/config/core/src/main/java/org/apache/karaf/config/core/impl/ConfigMBeanImpl.java b/config/core/src/main/java/org/apache/karaf/config/core/impl/ConfigMBeanImpl.java
deleted file mode 100644
index a8b8090..0000000
--- a/config/core/src/main/java/org/apache/karaf/config/core/impl/ConfigMBeanImpl.java
+++ /dev/null
@@ -1,186 +0,0 @@
-/*
- * 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.config.core.impl;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Dictionary;
-import java.util.Enumeration;
-import java.util.HashMap;
-import java.util.Hashtable;
-import java.util.List;
-import java.util.Map;
-
-import javax.management.MBeanException;
-import javax.management.NotCompliantMBeanException;
-import javax.management.StandardMBean;
-
-import org.apache.karaf.config.core.ConfigMBean;
-import org.apache.karaf.config.core.ConfigRepository;
-import org.osgi.service.cm.Configuration;
-
-/**
- * Implementation of the ConfigMBean.
- */
-public class ConfigMBeanImpl extends StandardMBean implements ConfigMBean {
-
-    private ConfigRepository configRepo;
-
-    public ConfigMBeanImpl() throws NotCompliantMBeanException {
-        super(ConfigMBean.class);
-    }
-
-    private Configuration getConfiguration(String pid) throws IOException {
-        Configuration configuration = configRepo.getConfigAdmin().getConfiguration(pid);
-        if (configuration == null) {
-            throw new IllegalArgumentException("Configuration PID " + pid + " doesn't exist");
-        }
-        return configuration;
-    }
-
-    @SuppressWarnings("rawtypes")
-    private Dictionary getConfigProperties(String pid) throws IOException {
-        Configuration configuration = getConfiguration(pid);
-
-        Dictionary dictionary = configuration.getProperties();
-        if (dictionary == null) {
-            dictionary = new java.util.Properties();
-        }
-        return dictionary;
-    }
-
-    /**
-     * Get all config pids
-     */
-    public List<String> getConfigs() throws MBeanException {
-        try {
-            Configuration[] configurations = this.configRepo.getConfigAdmin().listConfigurations(null);
-            List<String> pids = new ArrayList<String>();
-            for (int i = 0; i < configurations.length; i++) {
-                pids.add(configurations[i].getPid());
-            }
-            return pids;
-        } catch (Exception e) {
-            throw new MBeanException(null, e.getMessage());
-        }
-    }
-
-    @SuppressWarnings("rawtypes")
-    public void create(String pid) throws MBeanException {
-        try {
-            configRepo.update(pid, new Hashtable());
-        } catch (Exception e) {
-            throw new MBeanException(null, e.getMessage());
-        }
-    }
-
-    public void delete(String pid) throws MBeanException {
-        try {
-            this.configRepo.delete(pid);
-        } catch (Exception e) {
-            throw new MBeanException(null, e.getMessage());
-        }
-    }
-
-    @SuppressWarnings("rawtypes")
-    public Map<String, String> listProperties(String pid) throws MBeanException {
-        try {
-            Dictionary dictionary = getConfigProperties(pid);
-
-            Map<String, String> propertiesMap = new HashMap<String, String>();
-            for (Enumeration e = dictionary.keys(); e.hasMoreElements(); ) {
-                Object key = e.nextElement();
-                Object value = dictionary.get(key);
-                propertiesMap.put(key.toString(), value.toString());
-            }
-            return propertiesMap;
-        } catch (Exception e) {
-            throw new MBeanException(null, e.getMessage());
-        }
-    }
-
-    @SuppressWarnings("rawtypes")
-    public void deleteProperty(String pid, String key) throws MBeanException {
-        try {
-            Dictionary dictionary = getConfigProperties(pid);
-            dictionary.remove(key);
-            configRepo.update(pid, dictionary);
-        } catch (Exception e) {
-            throw new MBeanException(null, e.getMessage());
-        }
-    }
-
-    @SuppressWarnings({"rawtypes", "unchecked"})
-    public void appendProperty(String pid, String key, String value) throws MBeanException {
-        try {
-            Dictionary dictionary = getConfigProperties(pid);
-            Object currentValue = dictionary.get(key);
-            if (currentValue == null) {
-                dictionary.put(key, value);
-            } else if (currentValue instanceof String) {
-                dictionary.put(key, currentValue + value);
-            } else {
-                throw new IllegalStateException("Current value is not a String");
-            }
-            configRepo.update(pid, dictionary);
-        } catch (Exception e) {
-            throw new MBeanException(null, e.getMessage());
-        }
-    }
-
-    @SuppressWarnings({"rawtypes", "unchecked"})
-    public void setProperty(String pid, String key, String value) throws MBeanException {
-        try {
-            Dictionary dictionary = getConfigProperties(pid);
-            dictionary.put(key, value);
-            configRepo.update(pid, dictionary);
-        } catch (Exception e) {
-            throw new MBeanException(null, e.getMessage());
-        }
-    }
-
-    public void update(String pid, Map<String, String> properties) throws MBeanException {
-        try {
-            if (properties == null) {
-                properties = new HashMap<String, String>();
-            }
-            Dictionary<String, String> dictionary = toDictionary(properties);
-            configRepo.update(pid, dictionary);
-        } catch (Exception e) {
-            throw new MBeanException(null, e.getMessage());
-        }
-    }
-
-	private Dictionary<String, String> toDictionary(
-			Map<String, String> properties) {
-		Dictionary<String, String> dictionary = new Hashtable<String, String>();
-		for (String key : properties.keySet()) {
-		    dictionary.put(key, properties.get(key));
-		}
-		return dictionary;
-	}
-
-
-    public void setConfigRepo(ConfigRepository configRepo) {
-        this.configRepo = configRepo;
-    }
-
-	@Override
-	public String createFactoryConfiguration(String factoryPid,
-			Map<String, String> properties) throws MBeanException {
-		Dictionary<String, String> dict = toDictionary(properties);
-		return configRepo.createFactoryConfiguration(factoryPid, dict);
-	}
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d33e0955/config/core/src/main/java/org/apache/karaf/config/core/impl/ConfigRepositoryImpl.java
----------------------------------------------------------------------
diff --git a/config/core/src/main/java/org/apache/karaf/config/core/impl/ConfigRepositoryImpl.java b/config/core/src/main/java/org/apache/karaf/config/core/impl/ConfigRepositoryImpl.java
deleted file mode 100644
index 11bb720..0000000
--- a/config/core/src/main/java/org/apache/karaf/config/core/impl/ConfigRepositoryImpl.java
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * 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.karaf.config.core.impl;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.Dictionary;
-import java.util.Hashtable;
-
-import org.apache.karaf.config.core.ConfigRepository;
-import org.osgi.framework.InvalidSyntaxException;
-import org.osgi.service.cm.Configuration;
-import org.osgi.service.cm.ConfigurationAdmin;
-
-public class ConfigRepositoryImpl implements ConfigRepository {
-    private ConfigurationAdmin configAdmin;
-    
-    private File storage;
-
-    public ConfigRepositoryImpl(ConfigurationAdmin configAdmin) {
-        this.configAdmin = configAdmin;
-    }
-
-    /* (non-Javadoc)
-     * @see org.apache.karaf.shell.config.impl.ConfigRepository#update(java.lang.String, java.util.Dictionary, boolean)
-     */
-    @Override
-    @SuppressWarnings({ "rawtypes", "unchecked" })
-    public void update(String pid, Dictionary props) throws IOException {
-        Configuration cfg = this.configAdmin.getConfiguration(pid, null);
-        if (cfg.getBundleLocation() != null) {
-            cfg.setBundleLocation(null);
-        }
-        cfg.update(props);
-    }
-
-    /* (non-Javadoc)
-     * @see org.apache.karaf.shell.config.impl.ConfigRepository#delete(java.lang.String)
-     */
-    @Override
-    public void delete(String pid) throws Exception {
-        Configuration configuration = this.configAdmin.getConfiguration(pid);
-        configuration.delete();
-        deleteStorage(pid);
-    }
-    
-    protected void deleteStorage(String pid) throws Exception {
-        if (storage != null) {
-            File cfgFile = new File(storage, pid + ".cfg");
-            cfgFile.delete();
-        }
-    }
-
-    /* (non-Javadoc)
-     * @see org.apache.karaf.shell.config.impl.ConfigRepository#getConfigProperties(java.lang.String)
-     */
-    @Override
-    @SuppressWarnings("rawtypes")
-    public Dictionary getConfigProperties(String pid) throws IOException, InvalidSyntaxException {
-        if(pid != null && configAdmin != null) {
-            Configuration configuration = this.configAdmin.getConfiguration(pid);
-            if(configuration != null) {
-                Dictionary props = configuration.getProperties();
-                return (props != null) ? props : new Hashtable<String, String>();
-            }
-        }
-        return null;
-    }
-
-    public ConfigurationAdmin getConfigAdmin() {
-        return this.configAdmin;
-    }
-
-	@Override
-	public String createFactoryConfiguration(String factoryPid, Dictionary<String, ?> properties) {
-		try {
-			Configuration config = configAdmin.createFactoryConfiguration(factoryPid);
-			config.update(properties);
-			return config.getPid();
-		} catch (IOException e) {
-			throw new RuntimeException(e.getMessage(), e);
-		}
-	}
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d33e0955/config/core/src/main/java/org/apache/karaf/config/core/impl/osgi/Activator.java
----------------------------------------------------------------------
diff --git a/config/core/src/main/java/org/apache/karaf/config/core/impl/osgi/Activator.java b/config/core/src/main/java/org/apache/karaf/config/core/impl/osgi/Activator.java
deleted file mode 100644
index bdfab09..0000000
--- a/config/core/src/main/java/org/apache/karaf/config/core/impl/osgi/Activator.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * 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.karaf.config.core.impl.osgi;
-
-import org.apache.karaf.config.core.ConfigRepository;
-import org.apache.karaf.config.core.impl.ConfigMBeanImpl;
-import org.apache.karaf.config.core.impl.ConfigRepositoryImpl;
-import org.apache.karaf.util.tracker.BaseActivator;
-import org.osgi.service.cm.ConfigurationAdmin;
-
-public class Activator extends BaseActivator {
-
-    @Override
-    protected void doOpen() throws Exception {
-        trackService(ConfigurationAdmin.class);
-    }
-
-    protected void doStart() throws Exception {
-        ConfigurationAdmin configurationAdmin = getTrackedService(ConfigurationAdmin.class);
-        if (configurationAdmin == null) {
-            return;
-        }
-
-        ConfigRepository configRepository = new ConfigRepositoryImpl(configurationAdmin);
-        register(ConfigRepository.class, configRepository);
-
-        ConfigMBeanImpl configMBean = new ConfigMBeanImpl();
-        configMBean.setConfigRepo(configRepository);
-        registerMBean(configMBean, "type=config");
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d33e0955/config/core/src/main/resources/OSGI-INF/bundle.info
----------------------------------------------------------------------
diff --git a/config/core/src/main/resources/OSGI-INF/bundle.info b/config/core/src/main/resources/OSGI-INF/bundle.info
deleted file mode 100644
index 3cd35da..0000000
--- a/config/core/src/main/resources/OSGI-INF/bundle.info
+++ /dev/null
@@ -1,27 +0,0 @@
-h1. Synopsis
-
-${project.name}
-
-${project.description}
-
-Maven URL:
-[mvn:${project.groupId}/${project.artifactId}/${project.version}]
-
-h1. Description
-
-This bundle provides Karaf shell commands to manipulate the ConfigAdmin OSGi service.
-
-The following commands are available:
-* config:cancel - Cancels the changes to the configuration being edited.
-* config:edit - Creates or edits a configuration.
-* config:list - Lists existing configurations.
-* config:propappend - Appends the given value to an existing property or creates
- the property with the specified name and value.
-* config:propdel - Deletes a property from the edited configuration.
-* config:proplist - Lists properties from the currently edited configuration.
-* config:propset - Sets a property in the currently edited configuration.
-* config:update - Saves and propagates changes from the configuration being edited.
-
-h1. See also
-
-Commands - section of the Karaf User Guide.
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/karaf/blob/d33e0955/config/core/src/main/resources/OSGI-INF/metatype/metatype.properties
----------------------------------------------------------------------
diff --git a/config/core/src/main/resources/OSGI-INF/metatype/metatype.properties b/config/core/src/main/resources/OSGI-INF/metatype/metatype.properties
deleted file mode 100644
index 3bce187..0000000
--- a/config/core/src/main/resources/OSGI-INF/metatype/metatype.properties
+++ /dev/null
@@ -1,28 +0,0 @@
-#
-#  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.
-#
-
-#
-# This file contains localization strings for configuration labels and
-# descriptions as used in the metatype.xml descriptor
-
-config.name = Apache Karaf Shell Config
-config.description = Configuration of Apache Karaf Shell Config
-
-storage.name = Storage directory
-storage.description = the directory used as a storage for configurations

http://git-wip-us.apache.org/repos/asf/karaf/blob/d33e0955/config/core/src/main/resources/OSGI-INF/metatype/metatype.xml
----------------------------------------------------------------------
diff --git a/config/core/src/main/resources/OSGI-INF/metatype/metatype.xml b/config/core/src/main/resources/OSGI-INF/metatype/metatype.xml
deleted file mode 100644
index 83d3242..0000000
--- a/config/core/src/main/resources/OSGI-INF/metatype/metatype.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-
-    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.
-
--->
-<metatype:MetaData xmlns:metatype="http://www.osgi.org/xmlns/metatype/v1.0.0" localization="OSGI-INF/metatype/metatype">
-    <OCD id="org.apache.karaf.config" name="%config.name" description="%config.description">
-        <AD id="storage" type="String" default="${karaf.etc}/"
-            name="%storage.name" description="%storage.description"/>
-    </OCD>
-    <Designate pid="org.apache.karaf.config">
-        <Object ocdref="org.apache.karaf.config"/>
-    </Designate>
-</metatype:MetaData>

http://git-wip-us.apache.org/repos/asf/karaf/blob/d33e0955/config/pom.xml
----------------------------------------------------------------------
diff --git a/config/pom.xml b/config/pom.xml
index 10cc1af..af0de85 100644
--- a/config/pom.xml
+++ b/config/pom.xml
@@ -10,7 +10,7 @@
         (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
+           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,
@@ -29,13 +29,92 @@
     </parent>
 
     <groupId>org.apache.karaf.config</groupId>
-    <artifactId>config</artifactId>
-    <packaging>pom</packaging>
-    <name>Apache Karaf :: ConfigAdmin</name>
-
-    <modules>
-        <module>core</module>
-        <module>command</module>
-    </modules>
+    <artifactId>org.apache.karaf.config.core</artifactId>
+    <packaging>bundle</packaging>
+    <name>Apache Karaf :: ConfigAdmin :: Core</name>
+    <description>This bundle provides Karaf services</description>
+
+    <properties>
+        <appendedResourcesDirectory>${basedir}/../etc/appended-resources</appendedResourcesDirectory>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>org.osgi.core</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>org.osgi.compendium</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-api</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.karaf</groupId>
+            <artifactId>org.apache.karaf.util</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.karaf.shell</groupId>
+            <artifactId>org.apache.karaf.shell.core</artifactId>
+            <optional>true</optional>
+        </dependency>
+
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-jdk14</artifactId>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <resources>
+            <resource>
+                <directory>${project.basedir}/src/main/resources</directory>
+                <includes>
+                    <include>**/*</include>
+                </includes>
+            </resource>
+            <resource>
+                <directory>${project.basedir}/src/main/resources</directory>
+                <filtering>true</filtering>
+                <includes>
+                    <include>**/*.info</include>
+                </includes>
+            </resource>
+        </resources>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+                <configuration>
+                    <instructions>
+                        <Export-Package>
+                            org.apache.karaf.config.command*,
+                            org.apache.karaf.config.core
+                        </Export-Package>
+                        <Import-Package>
+                            *
+                        </Import-Package>
+                        <Private-Package>
+                            org.apache.karaf.config.core.impl,
+                            org.apache.karaf.config.core.impl.osgi,
+                            org.apache.karaf.util.tracker
+                        </Private-Package>
+                        <Bundle-Activator>
+                            org.apache.karaf.config.core.impl.osgi.Activator
+                        </Bundle-Activator>
+                        <Karaf-Commands>org.apache.karaf.config.command.*</Karaf-Commands>
+                    </instructions>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
 
 </project>

http://git-wip-us.apache.org/repos/asf/karaf/blob/d33e0955/config/src/main/java/org/apache/karaf/config/command/CancelCommand.java
----------------------------------------------------------------------
diff --git a/config/src/main/java/org/apache/karaf/config/command/CancelCommand.java b/config/src/main/java/org/apache/karaf/config/command/CancelCommand.java
new file mode 100644
index 0000000..dff43fa
--- /dev/null
+++ b/config/src/main/java/org/apache/karaf/config/command/CancelCommand.java
@@ -0,0 +1,32 @@
+/*
+ * 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.karaf.config.command;
+
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+
+@Command(scope = "config", name = "cancel", description = "Cancels the changes to the configuration being edited.")
+@Service
+public class CancelCommand extends ConfigCommandSupport {
+
+    protected Object doExecute() throws Exception {
+        session.put(PROPERTY_CONFIG_PID, null);
+        session.put(PROPERTY_CONFIG_PROPS, null);
+        return null;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d33e0955/config/src/main/java/org/apache/karaf/config/command/ConfigCommandSupport.java
----------------------------------------------------------------------
diff --git a/config/src/main/java/org/apache/karaf/config/command/ConfigCommandSupport.java b/config/src/main/java/org/apache/karaf/config/command/ConfigCommandSupport.java
new file mode 100644
index 0000000..fe0ca93
--- /dev/null
+++ b/config/src/main/java/org/apache/karaf/config/command/ConfigCommandSupport.java
@@ -0,0 +1,63 @@
+/*
+ * 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.karaf.config.command;
+
+import java.util.Dictionary;
+
+import org.apache.karaf.config.core.ConfigRepository;
+import org.apache.karaf.shell.api.action.Action;
+import org.apache.karaf.shell.api.action.lifecycle.Reference;
+import org.apache.karaf.shell.api.console.Session;
+
+/**
+ * Abstract class from which all commands related to the ConfigurationAdmin
+ * service should derive.
+ * This command retrieves a reference to the ConfigurationAdmin service before
+ * calling another method to actually process the command.
+ */
+public abstract class ConfigCommandSupport implements Action {
+
+    public static final String PROPERTY_CONFIG_PID = "ConfigCommand.PID";
+    public static final String PROPERTY_CONFIG_PROPS = "ConfigCommand.Props";
+    public static final String PROPERTY_FACTORY = "ConfigCommand.Factory";
+
+    @Reference
+    protected ConfigRepository configRepository;
+
+    @Reference
+    protected Session session;
+
+    @Override
+    public Object execute() throws Exception {
+        return doExecute();
+    }
+
+    protected abstract Object doExecute() throws Exception;
+
+    @SuppressWarnings("rawtypes")
+    protected Dictionary getEditedProps() throws Exception {
+        return (Dictionary) this.session.get(PROPERTY_CONFIG_PROPS);
+    }
+    
+    public void setConfigRepository(ConfigRepository configRepository) {
+        this.configRepository = configRepository;
+    }
+
+    public void setSession(Session session) {
+        this.session = session;
+    }
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d33e0955/config/src/main/java/org/apache/karaf/config/command/ConfigPropertyCommandSupport.java
----------------------------------------------------------------------
diff --git a/config/src/main/java/org/apache/karaf/config/command/ConfigPropertyCommandSupport.java b/config/src/main/java/org/apache/karaf/config/command/ConfigPropertyCommandSupport.java
new file mode 100644
index 0000000..619c224
--- /dev/null
+++ b/config/src/main/java/org/apache/karaf/config/command/ConfigPropertyCommandSupport.java
@@ -0,0 +1,85 @@
+/*
+ * 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.karaf.config.command;
+
+import java.util.Dictionary;
+import java.util.Properties;
+
+import org.apache.karaf.config.command.completers.ConfigurationCompleter;
+import org.apache.karaf.shell.api.action.Completion;
+import org.apache.karaf.shell.api.action.Option;
+
+/**
+ * Abstract class which commands that are related to property processing should extend.
+ */
+public abstract class ConfigPropertyCommandSupport extends ConfigCommandSupport {
+
+    @Option(name = "-p", aliases = "--pid", description = "The configuration pid", required = false, multiValued = false)
+    @Completion(ConfigurationCompleter.class)
+    protected String pid;
+
+    @SuppressWarnings("rawtypes")
+    protected Object doExecute() throws Exception {
+        Dictionary props = getEditedProps();
+        if (props == null && pid == null) {
+            System.err.println("No configuration is being edited--run the edit command first");
+        } else {
+            if (props == null) {
+                props = new Properties();
+            }
+            propertyAction(props);
+            if(requiresUpdate(pid)) {
+                this.configRepository.update(pid, props);
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Perform an action on the properties.
+     * @param props
+     */
+    @SuppressWarnings("rawtypes")
+    protected abstract void propertyAction(Dictionary props);
+
+    /**
+     * Checks if the configuration requires to be updated.
+     * The default behavior is to update if a valid pid has been passed to the method.
+     * @param pid
+     * @return
+     */
+    protected boolean requiresUpdate(String pid) {
+        if (pid != null) {
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+
+    /**
+     * Retrieves confguration from the pid, if used or delegates to session from getting the configuration.
+     * @return
+     * @throws Exception
+     */
+    @SuppressWarnings("rawtypes")
+    @Override
+    protected Dictionary getEditedProps() throws Exception {
+        Dictionary props = this.configRepository.getConfigProperties(pid);
+        return (props != null) ? props : super.getEditedProps();
+    }
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d33e0955/config/src/main/java/org/apache/karaf/config/command/DeleteCommand.java
----------------------------------------------------------------------
diff --git a/config/src/main/java/org/apache/karaf/config/command/DeleteCommand.java b/config/src/main/java/org/apache/karaf/config/command/DeleteCommand.java
new file mode 100644
index 0000000..6953ef0
--- /dev/null
+++ b/config/src/main/java/org/apache/karaf/config/command/DeleteCommand.java
@@ -0,0 +1,52 @@
+/*
+ * 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.karaf.config.command;
+
+import org.apache.karaf.config.command.completers.ConfigurationCompleter;
+import org.apache.karaf.shell.api.action.Argument;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.Completion;
+import org.apache.karaf.shell.api.action.Option;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+
+@Command(scope = "config", name = "delete", description = "Delete a configuration.")
+@Service
+public class DeleteCommand extends ConfigCommandSupport {
+
+    @Argument(index = 0, name = "pid", description = "PID of the configuration", required = true, multiValued = false)
+    @Completion(ConfigurationCompleter.class)
+    String pid;
+
+    @Option(name = "--force", aliases = {}, description = "Force the edition of this config, even if another one was under edition", required = false, multiValued = false)
+    boolean force;
+
+    protected Object doExecute() throws Exception {
+        String oldPid = (String) this.session.get(PROPERTY_CONFIG_PID);
+        if (oldPid != null && oldPid.equals(pid) && !force) {
+            System.err.println("This config is being edited.  Cancel / update first, or use the --force option");
+            return null;
+        }
+
+        this.configRepository.delete(pid);
+        if (oldPid != null && oldPid.equals(pid) && !force) {
+            this.session.put(PROPERTY_CONFIG_PID, null);
+            this.session.put(PROPERTY_CONFIG_PROPS, null);
+        }
+        return null;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d33e0955/config/src/main/java/org/apache/karaf/config/command/EditCommand.java
----------------------------------------------------------------------
diff --git a/config/src/main/java/org/apache/karaf/config/command/EditCommand.java b/config/src/main/java/org/apache/karaf/config/command/EditCommand.java
new file mode 100644
index 0000000..8c48b83
--- /dev/null
+++ b/config/src/main/java/org/apache/karaf/config/command/EditCommand.java
@@ -0,0 +1,70 @@
+/*
+ * 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.karaf.config.command;
+
+import java.util.Dictionary;
+
+import org.apache.karaf.config.command.completers.ConfigurationCompleter;
+import org.apache.karaf.shell.api.action.Argument;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.Completion;
+import org.apache.karaf.shell.api.action.Option;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.osgi.service.cm.Configuration;
+
+@Command(scope = "config", name = "edit", description = "Creates or edits a configuration.", detailedDescription="classpath:edit.txt")
+@Service
+public class EditCommand extends ConfigCommandSupport {
+
+    @Argument(index = 0, name = "pid", description = "PID of the configuration or of the factory if --factory is given. Pid can also be specified as ldap query", required = true, multiValued = false)
+    @Completion(ConfigurationCompleter.class)
+    String pid;
+
+    @Option(name = "--force", aliases = {}, description = "Force the edition of this config, even if another one was under edition", required = false, multiValued = false)
+    boolean force;
+    
+    @Option(name = "--factory", aliases = {}, description = "Define this config as a factory config. Will be crearted on calling update", required = false, multiValued = false)
+    boolean factory;
+
+    @SuppressWarnings("rawtypes")
+    protected Object doExecute() throws Exception {
+        String oldPid = (String) this.session.get(PROPERTY_CONFIG_PID);
+        if (oldPid != null && !oldPid.equals(pid) && !force) {
+            System.err.println("Another config is being edited.  Cancel / update first, or use the --force option");
+            return null;
+        }
+        
+        if (pid.startsWith("(")) {
+        	Configuration[] configs = this.configRepository.getConfigAdmin().listConfigurations(pid);
+        	if (configs.length == 0) {
+        		throw new RuntimeException("Filter matches no config");
+        	}
+        	if (configs.length > 1) {
+        		throw new RuntimeException("Filter matches more than one config");
+        	}
+        	pid = configs[0].getPid();
+        	System.out.println("Editing config " + pid);
+        }
+
+        Dictionary props = this.configRepository.getConfigProperties(pid);
+        this.session.put(PROPERTY_CONFIG_PID, pid);
+        this.session.put(PROPERTY_FACTORY, factory);
+        this.session.put(PROPERTY_CONFIG_PROPS, props);
+        return null;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d33e0955/config/src/main/java/org/apache/karaf/config/command/ListCommand.java
----------------------------------------------------------------------
diff --git a/config/src/main/java/org/apache/karaf/config/command/ListCommand.java b/config/src/main/java/org/apache/karaf/config/command/ListCommand.java
new file mode 100644
index 0000000..bce8410
--- /dev/null
+++ b/config/src/main/java/org/apache/karaf/config/command/ListCommand.java
@@ -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.karaf.config.command;
+
+import java.util.Dictionary;
+import java.util.Enumeration;
+import java.util.Map;
+import java.util.TreeMap;
+
+import org.apache.karaf.shell.api.action.Argument;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.osgi.service.cm.Configuration;
+
+@Command(scope = "config", name = "list", description = "Lists existing configurations.")
+@Service
+public class ListCommand extends ConfigCommandSupport {
+
+    @Argument(index = 0, name = "query", description = "Query in LDAP syntax. Example: \"(service.pid=org.apache.karaf.log)\"", required = false, multiValued = false)
+    String query;
+
+    @SuppressWarnings("rawtypes")
+    protected Object doExecute() throws Exception {
+        Configuration[] configs = configRepository.getConfigAdmin().listConfigurations(query);
+        if (configs != null) {
+            Map<String, Configuration> sortedConfigs = new TreeMap<String, Configuration>();
+            for (Configuration config : configs) {
+                sortedConfigs.put(config.getPid(), config);
+            }
+            for (String pid : sortedConfigs.keySet()) {
+                Configuration config = sortedConfigs.get(pid);
+                System.out.println("----------------------------------------------------------------");
+                System.out.println("Pid:            " + config.getPid());
+                if (config.getFactoryPid() != null) {
+                    System.out.println("FactoryPid:     " + config.getFactoryPid());
+                }
+                System.out.println("BundleLocation: " + config.getBundleLocation());
+                if (config.getProperties() != null) {
+                    System.out.println("Properties:");
+                    Dictionary props = config.getProperties();
+                    Map<String, Object> sortedProps = new TreeMap<String, Object>();
+                    for (Enumeration e = props.keys(); e.hasMoreElements();) {
+                        Object key = e.nextElement();
+                        sortedProps.put(key.toString(), props.get(key));
+                    }
+                    for (String key : sortedProps.keySet()) {
+                        System.out.println("   " + key + " = " + sortedProps.get(key));
+                    }
+                }
+            }
+        }
+        return null;
+    }
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d33e0955/config/src/main/java/org/apache/karaf/config/command/PropAppendCommand.java
----------------------------------------------------------------------
diff --git a/config/src/main/java/org/apache/karaf/config/command/PropAppendCommand.java b/config/src/main/java/org/apache/karaf/config/command/PropAppendCommand.java
new file mode 100644
index 0000000..f021146
--- /dev/null
+++ b/config/src/main/java/org/apache/karaf/config/command/PropAppendCommand.java
@@ -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.karaf.config.command;
+
+import java.util.Dictionary;
+
+import org.apache.karaf.config.command.completers.ConfigurationPropertyCompleter;
+import org.apache.karaf.shell.api.action.Argument;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.Completion;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+
+@Command(scope = "config", name = "property-append", description = "Appends the given value to an existing property or creates the property with the specified name and value.")
+@Service
+public class PropAppendCommand extends ConfigPropertyCommandSupport {
+
+    @Argument(index = 0, name = "name", description = "The name of the property", required = true, multiValued = false)
+    @Completion(ConfigurationPropertyCompleter.class)
+    String prop;
+
+    @Argument(index = 1, name = "value", description = "The value to append to the property", required = true, multiValued = false)
+    String value;
+
+    @SuppressWarnings({"unchecked", "rawtypes"})
+    @Override
+    public void propertyAction(Dictionary props) {
+        final Object currentValue = props.get(prop);
+        if (currentValue == null) {
+            props.put(prop, value);
+        } else if (currentValue instanceof String) {
+            props.put(prop, currentValue + value);
+        } else {
+            System.err.println("Append Failed: current value is not a String.");
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d33e0955/config/src/main/java/org/apache/karaf/config/command/PropDelCommand.java
----------------------------------------------------------------------
diff --git a/config/src/main/java/org/apache/karaf/config/command/PropDelCommand.java b/config/src/main/java/org/apache/karaf/config/command/PropDelCommand.java
new file mode 100644
index 0000000..e416cf6
--- /dev/null
+++ b/config/src/main/java/org/apache/karaf/config/command/PropDelCommand.java
@@ -0,0 +1,38 @@
+/*
+ * 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.karaf.config.command;
+
+import java.util.Dictionary;
+
+import org.apache.karaf.shell.api.action.Argument;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+
+
+@Command(scope = "config", name = "property-delete", description = "Deletes a property from the configuration being edited.")
+@Service
+public class PropDelCommand extends ConfigPropertyCommandSupport {
+
+    @Argument(index = 0, name = "property", description = "The name of the property to delete", required = true, multiValued = false)
+    String prop;
+
+    @SuppressWarnings("rawtypes")
+    @Override
+    public void propertyAction(Dictionary props) {
+        props.remove(prop);
+    }
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d33e0955/config/src/main/java/org/apache/karaf/config/command/PropListCommand.java
----------------------------------------------------------------------
diff --git a/config/src/main/java/org/apache/karaf/config/command/PropListCommand.java b/config/src/main/java/org/apache/karaf/config/command/PropListCommand.java
new file mode 100644
index 0000000..a0d3a61
--- /dev/null
+++ b/config/src/main/java/org/apache/karaf/config/command/PropListCommand.java
@@ -0,0 +1,47 @@
+/*
+ * 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.karaf.config.command;
+
+import java.util.Dictionary;
+import java.util.Enumeration;
+
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+
+@Command(scope = "config", name = "property-list", description = "Lists properties from the currently edited configuration.")
+@Service
+public class PropListCommand extends ConfigPropertyCommandSupport {
+
+    @SuppressWarnings("rawtypes")
+    @Override
+    public void propertyAction(Dictionary props) {
+        for (Enumeration e = props.keys(); e.hasMoreElements(); ) {
+            Object key = e.nextElement();
+            System.out.println("   " + key + " = " + props.get(key));
+        }
+    }
+
+    /**
+     * List commands never requires an update, so it always returns false.
+     * @param pid
+     * @return
+     */
+    @Override
+    protected boolean requiresUpdate(String pid) {
+        return false;
+    }
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d33e0955/config/src/main/java/org/apache/karaf/config/command/PropSetCommand.java
----------------------------------------------------------------------
diff --git a/config/src/main/java/org/apache/karaf/config/command/PropSetCommand.java b/config/src/main/java/org/apache/karaf/config/command/PropSetCommand.java
new file mode 100644
index 0000000..8337f6a
--- /dev/null
+++ b/config/src/main/java/org/apache/karaf/config/command/PropSetCommand.java
@@ -0,0 +1,43 @@
+/*
+ * 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.karaf.config.command;
+
+import java.util.Dictionary;
+
+import org.apache.karaf.config.command.completers.ConfigurationPropertyCompleter;
+import org.apache.karaf.shell.api.action.Argument;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.Completion;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+
+@Command(scope = "config", name = "property-set", description = "Sets a property in the currently edited configuration.")
+@Service
+public class PropSetCommand extends ConfigPropertyCommandSupport {
+
+    @Argument(index = 0, name = "property", description = "The name of the property to set", required = true, multiValued = false)
+    @Completion(ConfigurationPropertyCompleter.class)
+    String prop;
+
+    @Argument(index = 1, name = "value", description = "The value of the property", required = true, multiValued = false)
+    String value;
+
+    @SuppressWarnings({"unchecked", "rawtypes"})
+    @Override
+    public void propertyAction(Dictionary props) {
+        props.put(prop, value);
+    }
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d33e0955/config/src/main/java/org/apache/karaf/config/command/UpdateCommand.java
----------------------------------------------------------------------
diff --git a/config/src/main/java/org/apache/karaf/config/command/UpdateCommand.java b/config/src/main/java/org/apache/karaf/config/command/UpdateCommand.java
new file mode 100644
index 0000000..cc368b8
--- /dev/null
+++ b/config/src/main/java/org/apache/karaf/config/command/UpdateCommand.java
@@ -0,0 +1,48 @@
+/*
+ * 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.karaf.config.command;
+
+import java.util.Dictionary;
+
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+
+@Command(scope = "config", name = "update", description = "Saves and propagates changes from the configuration being edited.")
+@Service
+public class UpdateCommand extends ConfigCommandSupport {
+
+    @SuppressWarnings({ "rawtypes", "unchecked" })
+    protected Object doExecute() throws Exception {
+        Dictionary props = getEditedProps();
+        if (props == null) {
+            System.err.println("No configuration is being edited--run the edit command first");
+            return null;
+        }
+
+        String pid = (String) this.session.get(PROPERTY_CONFIG_PID);
+        boolean isFactory = this.session.get(PROPERTY_FACTORY) != null && (Boolean) this.session.get(PROPERTY_FACTORY);
+        if (isFactory) {
+        	this.configRepository.createFactoryConfiguration(pid, props);
+        } else {
+        	this.configRepository.update(pid, props);
+        }
+        this.session.put(PROPERTY_CONFIG_PID, null);
+        this.session.put(PROPERTY_FACTORY, null);
+        this.session.put(PROPERTY_CONFIG_PROPS, null);
+        return null;
+    }
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d33e0955/config/src/main/java/org/apache/karaf/config/command/completers/ConfigurationCompleter.java
----------------------------------------------------------------------
diff --git a/config/src/main/java/org/apache/karaf/config/command/completers/ConfigurationCompleter.java b/config/src/main/java/org/apache/karaf/config/command/completers/ConfigurationCompleter.java
new file mode 100644
index 0000000..fe60c56
--- /dev/null
+++ b/config/src/main/java/org/apache/karaf/config/command/completers/ConfigurationCompleter.java
@@ -0,0 +1,103 @@
+/*
+ * 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.karaf.config.command.completers;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import org.apache.karaf.shell.api.action.lifecycle.Destroy;
+import org.apache.karaf.shell.api.action.lifecycle.Init;
+import org.apache.karaf.shell.api.action.lifecycle.Reference;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.apache.karaf.shell.api.console.CommandLine;
+import org.apache.karaf.shell.api.console.Completer;
+import org.apache.karaf.shell.api.console.Session;
+import org.apache.karaf.shell.support.completers.StringsCompleter;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceRegistration;
+import org.osgi.service.cm.Configuration;
+import org.osgi.service.cm.ConfigurationAdmin;
+import org.osgi.service.cm.ConfigurationEvent;
+import org.osgi.service.cm.ConfigurationListener;
+
+/**
+ * {@link Completer} for Configuration Admin configurations.
+ *
+ * Displays a list of existing config instance configurations for completion.
+ *
+ */
+@Service
+public class ConfigurationCompleter implements Completer, ConfigurationListener {
+
+    private final StringsCompleter delegate = new StringsCompleter();
+
+    @Reference
+    private ConfigurationAdmin admin;
+
+    @Reference
+    private BundleContext bundleContext;
+
+    private ServiceRegistration<ConfigurationListener> registration;
+
+    public void setAdmin(ConfigurationAdmin admin) {
+        this.admin = admin;
+    }
+
+    @Init
+    public void init() {
+        registration = bundleContext.registerService(ConfigurationListener.class, this, null);
+
+        Configuration[] configs;
+        try {
+            configs = admin.listConfigurations(null);
+            if (configs == null) {
+                return;
+            }
+        } catch (Exception e) {
+            return;
+        }
+
+        Collection<String> pids = new ArrayList<String>();
+        for (Configuration config : configs) {
+            pids.add(config.getPid());
+        }
+
+        delegate.getStrings().addAll(pids);
+    }
+
+    @Destroy
+    public void destroy() {
+        registration.unregister();
+    }
+
+    public int complete(final Session session, final CommandLine commandLine, final List<String> candidates) {
+        return delegate.complete(session, commandLine, candidates);
+    }
+
+    public void configurationEvent(ConfigurationEvent configurationEvent) {
+        String pid = configurationEvent.getPid();
+        if (configurationEvent.getType() == ConfigurationEvent.CM_DELETED) {
+            delegate.getStrings().remove(pid);
+        } else if (configurationEvent.getType() == ConfigurationEvent.CM_UPDATED) {
+            delegate.getStrings().add(pid);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d33e0955/config/src/main/java/org/apache/karaf/config/command/completers/ConfigurationPropertyCompleter.java
----------------------------------------------------------------------
diff --git a/config/src/main/java/org/apache/karaf/config/command/completers/ConfigurationPropertyCompleter.java b/config/src/main/java/org/apache/karaf/config/command/completers/ConfigurationPropertyCompleter.java
new file mode 100644
index 0000000..2b43fec
--- /dev/null
+++ b/config/src/main/java/org/apache/karaf/config/command/completers/ConfigurationPropertyCompleter.java
@@ -0,0 +1,136 @@
+/*
+ * 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.karaf.config.command.completers;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Dictionary;
+import java.util.Enumeration;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.karaf.config.command.ConfigCommandSupport;
+import org.apache.karaf.shell.api.action.lifecycle.Reference;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.apache.karaf.shell.api.console.CommandLine;
+import org.apache.karaf.shell.api.console.Completer;
+import org.apache.karaf.shell.api.console.Session;
+import org.apache.karaf.shell.support.completers.StringsCompleter;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.service.cm.Configuration;
+import org.osgi.service.cm.ConfigurationAdmin;
+
+/**
+ * {@link Completer} for Configuration Admin properties.
+ *
+ * Displays a list of existing properties based on the current configuration being edited.
+ *
+ */
+@Service
+public class ConfigurationPropertyCompleter implements Completer {
+
+    private final StringsCompleter delegate = new StringsCompleter();
+
+    private static final String OPTION = "-p";
+    private static final String ALIAS = "--pid";
+
+    @Reference
+    private ConfigurationAdmin configAdmin;
+
+    @SuppressWarnings("rawtypes")
+    public int complete(final Session session, final CommandLine commandLine, final List<String> candidates) {
+        if (session != null) {
+            String pid = getPid(session, commandLine);
+            Set<String> propertyNames = getPropertyNames(pid);
+            delegate.getStrings().clear();
+            if (propertyNames != null && !propertyNames.isEmpty()) {
+                delegate.getStrings().addAll(propertyNames);
+            }
+        }
+        return delegate.complete(session, commandLine, candidates);
+    }
+
+    /**
+     * Retrieves the pid stored in the {@link Session} or passed as an argument.
+     * Argument takes precedence from pid stored in the {@link Session}.
+     */
+    private String getPid(Session session, CommandLine commandLine) {
+        String pid = (String) session.get(ConfigCommandSupport.PROPERTY_CONFIG_PID);
+        if (commandLine.getArguments().length > 0) {
+            List<String> arguments = Arrays.asList(commandLine.getArguments());
+            if (arguments.contains(OPTION)) {
+                int index = arguments.indexOf(OPTION);
+                if (arguments.size() > index) {
+                    return arguments.get(index + 1);
+                }
+            }
+
+            if (arguments.contains(ALIAS)) {
+                int index = arguments.indexOf(ALIAS);
+                if (arguments.size() > index) {
+                    return arguments.get(index + 1);
+                }
+            }
+        }
+        return pid;
+    }
+
+    /**
+     * Returns the property names for the given pid.
+     * @param pid
+     * @return
+     */
+    @SuppressWarnings("rawtypes")
+    private Set<String> getPropertyNames(String pid) {
+        Set<String> propertyNames = new HashSet<String>();
+        if (pid != null) {
+            Configuration configuration = null;
+            try {
+                Configuration[] configs = configAdmin.listConfigurations("(service.pid="+pid+")");
+                if (configs != null && configs.length > 0) {
+                    configuration = configs[0];
+                    if (configuration != null) {
+                        Dictionary properties = configuration.getProperties();
+                        if (properties != null) {
+                            Enumeration keys = properties.keys();
+                            while (keys.hasMoreElements()) {
+                                propertyNames.add(String.valueOf(keys.nextElement()));
+                            }
+                        }
+                    }
+                }
+            } catch (IOException e) {
+              //Ignore
+            } catch (InvalidSyntaxException e) {
+                //Ignore
+            }
+        }
+        return propertyNames;
+    }
+
+    public ConfigurationAdmin getConfigAdmin() {
+        return configAdmin;
+    }
+
+    public void setConfigAdmin(ConfigurationAdmin configAdmin) {
+        this.configAdmin = configAdmin;
+    }
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d33e0955/config/src/main/java/org/apache/karaf/config/core/ConfigMBean.java
----------------------------------------------------------------------
diff --git a/config/src/main/java/org/apache/karaf/config/core/ConfigMBean.java b/config/src/main/java/org/apache/karaf/config/core/ConfigMBean.java
new file mode 100644
index 0000000..9cb9f7f
--- /dev/null
+++ b/config/src/main/java/org/apache/karaf/config/core/ConfigMBean.java
@@ -0,0 +1,107 @@
+/*
+ * 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.config.core;
+
+import javax.management.MBeanException;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * MBean to manipulate the Config layer.
+ */
+public interface ConfigMBean {
+
+    /**
+     * Get the list of all configuration PIDs.
+     *
+     * @return the list of all configuration PIDs.
+     * @throws Exception
+     */
+    List<String> getConfigs() throws MBeanException;
+
+    /**
+     * Create a new configuration for the given PID.
+     *
+     * @param pid the configuration PID.
+     * @throws Exception
+     */
+    void create(String pid) throws MBeanException;
+
+    /**
+     * Delete a configuration identified by the given PID.
+     *
+     * @param pid the configuration PID to delete.
+     * @throws Exception
+     */
+    void delete(String pid) throws MBeanException;
+
+    /**
+     * Get the list of properties for a configuration PID.
+     *
+     * @param pid the configuration PID.
+     * @return the list of properties.
+     * @throws Exception
+     */
+    Map<String, String> listProperties(String pid) throws MBeanException;
+
+    /**
+     * Remove the configuration property identified by the given key.
+     *
+     * @param pid the configuration PID.
+     * @param key the property key.
+     * @throws Exception
+     */
+    void deleteProperty(String pid, String key) throws MBeanException;
+
+    /**
+     * Append (or add) a value for the given configuration key.
+     *
+     * @param pid the configuration PID.
+     * @param key the property key.
+     * @param value the value to append to the current property value.
+     * @throws Exception
+     */
+    void appendProperty(String pid, String key, String value) throws MBeanException;
+
+    /**
+     * Set a configuration property.
+     *
+     * @param pid the configuration PID.
+     * @param key the property key.
+     * @param value the property value.
+     * @throws Exception
+     */
+    void setProperty(String pid, String key, String value) throws MBeanException;
+
+    /**
+     * Update a complete configuration.
+     *
+     * @param pid the configuration PID.
+     * @param properties the new properties to set in the configuration.
+     * @throws MBeanException
+     */
+    void update(String pid, Map<String, String> properties) throws MBeanException;
+    
+    /**
+     * Create a factory based configuration.
+     *
+     * @param factoryPid
+     * @param properties the new properties to set in the configuration.
+     * @return created pid
+     * @throws MBeanException
+     */
+    String createFactoryConfiguration(String factoryPid, Map<String, String> properties) throws MBeanException;
+
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d33e0955/config/src/main/java/org/apache/karaf/config/core/ConfigRepository.java
----------------------------------------------------------------------
diff --git a/config/src/main/java/org/apache/karaf/config/core/ConfigRepository.java b/config/src/main/java/org/apache/karaf/config/core/ConfigRepository.java
new file mode 100644
index 0000000..8121679
--- /dev/null
+++ b/config/src/main/java/org/apache/karaf/config/core/ConfigRepository.java
@@ -0,0 +1,51 @@
+/*
+ * 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.karaf.config.core;
+
+import java.io.IOException;
+import java.util.Dictionary;
+
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.service.cm.ConfigurationAdmin;
+
+public interface ConfigRepository {
+
+    /**
+     * Saves config to storage or ConfigurationAdmin.
+     * @param pid
+     * @param props
+     * @throws IOException
+     */
+    @SuppressWarnings("rawtypes")
+    void update(String pid, Dictionary props) throws IOException;
+
+    void delete(String pid) throws Exception;
+
+    @SuppressWarnings("rawtypes")
+    Dictionary getConfigProperties(String pid) throws IOException, InvalidSyntaxException;
+
+    ConfigurationAdmin getConfigAdmin();
+
+    /**
+     * Create a factory based configuration.
+     *
+     * @param factoryPid
+     * @param properties the new properties to set in the configuration.
+     * @return created pid
+     */
+	String createFactoryConfiguration(String factoryPid, Dictionary<String, ?> properties);
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d33e0955/config/src/main/java/org/apache/karaf/config/core/impl/ConfigMBeanImpl.java
----------------------------------------------------------------------
diff --git a/config/src/main/java/org/apache/karaf/config/core/impl/ConfigMBeanImpl.java b/config/src/main/java/org/apache/karaf/config/core/impl/ConfigMBeanImpl.java
new file mode 100644
index 0000000..a8b8090
--- /dev/null
+++ b/config/src/main/java/org/apache/karaf/config/core/impl/ConfigMBeanImpl.java
@@ -0,0 +1,186 @@
+/*
+ * 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.config.core.impl;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Dictionary;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.List;
+import java.util.Map;
+
+import javax.management.MBeanException;
+import javax.management.NotCompliantMBeanException;
+import javax.management.StandardMBean;
+
+import org.apache.karaf.config.core.ConfigMBean;
+import org.apache.karaf.config.core.ConfigRepository;
+import org.osgi.service.cm.Configuration;
+
+/**
+ * Implementation of the ConfigMBean.
+ */
+public class ConfigMBeanImpl extends StandardMBean implements ConfigMBean {
+
+    private ConfigRepository configRepo;
+
+    public ConfigMBeanImpl() throws NotCompliantMBeanException {
+        super(ConfigMBean.class);
+    }
+
+    private Configuration getConfiguration(String pid) throws IOException {
+        Configuration configuration = configRepo.getConfigAdmin().getConfiguration(pid);
+        if (configuration == null) {
+            throw new IllegalArgumentException("Configuration PID " + pid + " doesn't exist");
+        }
+        return configuration;
+    }
+
+    @SuppressWarnings("rawtypes")
+    private Dictionary getConfigProperties(String pid) throws IOException {
+        Configuration configuration = getConfiguration(pid);
+
+        Dictionary dictionary = configuration.getProperties();
+        if (dictionary == null) {
+            dictionary = new java.util.Properties();
+        }
+        return dictionary;
+    }
+
+    /**
+     * Get all config pids
+     */
+    public List<String> getConfigs() throws MBeanException {
+        try {
+            Configuration[] configurations = this.configRepo.getConfigAdmin().listConfigurations(null);
+            List<String> pids = new ArrayList<String>();
+            for (int i = 0; i < configurations.length; i++) {
+                pids.add(configurations[i].getPid());
+            }
+            return pids;
+        } catch (Exception e) {
+            throw new MBeanException(null, e.getMessage());
+        }
+    }
+
+    @SuppressWarnings("rawtypes")
+    public void create(String pid) throws MBeanException {
+        try {
+            configRepo.update(pid, new Hashtable());
+        } catch (Exception e) {
+            throw new MBeanException(null, e.getMessage());
+        }
+    }
+
+    public void delete(String pid) throws MBeanException {
+        try {
+            this.configRepo.delete(pid);
+        } catch (Exception e) {
+            throw new MBeanException(null, e.getMessage());
+        }
+    }
+
+    @SuppressWarnings("rawtypes")
+    public Map<String, String> listProperties(String pid) throws MBeanException {
+        try {
+            Dictionary dictionary = getConfigProperties(pid);
+
+            Map<String, String> propertiesMap = new HashMap<String, String>();
+            for (Enumeration e = dictionary.keys(); e.hasMoreElements(); ) {
+                Object key = e.nextElement();
+                Object value = dictionary.get(key);
+                propertiesMap.put(key.toString(), value.toString());
+            }
+            return propertiesMap;
+        } catch (Exception e) {
+            throw new MBeanException(null, e.getMessage());
+        }
+    }
+
+    @SuppressWarnings("rawtypes")
+    public void deleteProperty(String pid, String key) throws MBeanException {
+        try {
+            Dictionary dictionary = getConfigProperties(pid);
+            dictionary.remove(key);
+            configRepo.update(pid, dictionary);
+        } catch (Exception e) {
+            throw new MBeanException(null, e.getMessage());
+        }
+    }
+
+    @SuppressWarnings({"rawtypes", "unchecked"})
+    public void appendProperty(String pid, String key, String value) throws MBeanException {
+        try {
+            Dictionary dictionary = getConfigProperties(pid);
+            Object currentValue = dictionary.get(key);
+            if (currentValue == null) {
+                dictionary.put(key, value);
+            } else if (currentValue instanceof String) {
+                dictionary.put(key, currentValue + value);
+            } else {
+                throw new IllegalStateException("Current value is not a String");
+            }
+            configRepo.update(pid, dictionary);
+        } catch (Exception e) {
+            throw new MBeanException(null, e.getMessage());
+        }
+    }
+
+    @SuppressWarnings({"rawtypes", "unchecked"})
+    public void setProperty(String pid, String key, String value) throws MBeanException {
+        try {
+            Dictionary dictionary = getConfigProperties(pid);
+            dictionary.put(key, value);
+            configRepo.update(pid, dictionary);
+        } catch (Exception e) {
+            throw new MBeanException(null, e.getMessage());
+        }
+    }
+
+    public void update(String pid, Map<String, String> properties) throws MBeanException {
+        try {
+            if (properties == null) {
+                properties = new HashMap<String, String>();
+            }
+            Dictionary<String, String> dictionary = toDictionary(properties);
+            configRepo.update(pid, dictionary);
+        } catch (Exception e) {
+            throw new MBeanException(null, e.getMessage());
+        }
+    }
+
+	private Dictionary<String, String> toDictionary(
+			Map<String, String> properties) {
+		Dictionary<String, String> dictionary = new Hashtable<String, String>();
+		for (String key : properties.keySet()) {
+		    dictionary.put(key, properties.get(key));
+		}
+		return dictionary;
+	}
+
+
+    public void setConfigRepo(ConfigRepository configRepo) {
+        this.configRepo = configRepo;
+    }
+
+	@Override
+	public String createFactoryConfiguration(String factoryPid,
+			Map<String, String> properties) throws MBeanException {
+		Dictionary<String, String> dict = toDictionary(properties);
+		return configRepo.createFactoryConfiguration(factoryPid, dict);
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d33e0955/config/src/main/java/org/apache/karaf/config/core/impl/ConfigRepositoryImpl.java
----------------------------------------------------------------------
diff --git a/config/src/main/java/org/apache/karaf/config/core/impl/ConfigRepositoryImpl.java b/config/src/main/java/org/apache/karaf/config/core/impl/ConfigRepositoryImpl.java
new file mode 100644
index 0000000..11bb720
--- /dev/null
+++ b/config/src/main/java/org/apache/karaf/config/core/impl/ConfigRepositoryImpl.java
@@ -0,0 +1,99 @@
+/*
+ * 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.karaf.config.core.impl;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Dictionary;
+import java.util.Hashtable;
+
+import org.apache.karaf.config.core.ConfigRepository;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.service.cm.Configuration;
+import org.osgi.service.cm.ConfigurationAdmin;
+
+public class ConfigRepositoryImpl implements ConfigRepository {
+    private ConfigurationAdmin configAdmin;
+    
+    private File storage;
+
+    public ConfigRepositoryImpl(ConfigurationAdmin configAdmin) {
+        this.configAdmin = configAdmin;
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.karaf.shell.config.impl.ConfigRepository#update(java.lang.String, java.util.Dictionary, boolean)
+     */
+    @Override
+    @SuppressWarnings({ "rawtypes", "unchecked" })
+    public void update(String pid, Dictionary props) throws IOException {
+        Configuration cfg = this.configAdmin.getConfiguration(pid, null);
+        if (cfg.getBundleLocation() != null) {
+            cfg.setBundleLocation(null);
+        }
+        cfg.update(props);
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.karaf.shell.config.impl.ConfigRepository#delete(java.lang.String)
+     */
+    @Override
+    public void delete(String pid) throws Exception {
+        Configuration configuration = this.configAdmin.getConfiguration(pid);
+        configuration.delete();
+        deleteStorage(pid);
+    }
+    
+    protected void deleteStorage(String pid) throws Exception {
+        if (storage != null) {
+            File cfgFile = new File(storage, pid + ".cfg");
+            cfgFile.delete();
+        }
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.karaf.shell.config.impl.ConfigRepository#getConfigProperties(java.lang.String)
+     */
+    @Override
+    @SuppressWarnings("rawtypes")
+    public Dictionary getConfigProperties(String pid) throws IOException, InvalidSyntaxException {
+        if(pid != null && configAdmin != null) {
+            Configuration configuration = this.configAdmin.getConfiguration(pid);
+            if(configuration != null) {
+                Dictionary props = configuration.getProperties();
+                return (props != null) ? props : new Hashtable<String, String>();
+            }
+        }
+        return null;
+    }
+
+    public ConfigurationAdmin getConfigAdmin() {
+        return this.configAdmin;
+    }
+
+	@Override
+	public String createFactoryConfiguration(String factoryPid, Dictionary<String, ?> properties) {
+		try {
+			Configuration config = configAdmin.createFactoryConfiguration(factoryPid);
+			config.update(properties);
+			return config.getPid();
+		} catch (IOException e) {
+			throw new RuntimeException(e.getMessage(), e);
+		}
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d33e0955/config/src/main/java/org/apache/karaf/config/core/impl/osgi/Activator.java
----------------------------------------------------------------------
diff --git a/config/src/main/java/org/apache/karaf/config/core/impl/osgi/Activator.java b/config/src/main/java/org/apache/karaf/config/core/impl/osgi/Activator.java
new file mode 100644
index 0000000..bdfab09
--- /dev/null
+++ b/config/src/main/java/org/apache/karaf/config/core/impl/osgi/Activator.java
@@ -0,0 +1,46 @@
+/*
+ * 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.karaf.config.core.impl.osgi;
+
+import org.apache.karaf.config.core.ConfigRepository;
+import org.apache.karaf.config.core.impl.ConfigMBeanImpl;
+import org.apache.karaf.config.core.impl.ConfigRepositoryImpl;
+import org.apache.karaf.util.tracker.BaseActivator;
+import org.osgi.service.cm.ConfigurationAdmin;
+
+public class Activator extends BaseActivator {
+
+    @Override
+    protected void doOpen() throws Exception {
+        trackService(ConfigurationAdmin.class);
+    }
+
+    protected void doStart() throws Exception {
+        ConfigurationAdmin configurationAdmin = getTrackedService(ConfigurationAdmin.class);
+        if (configurationAdmin == null) {
+            return;
+        }
+
+        ConfigRepository configRepository = new ConfigRepositoryImpl(configurationAdmin);
+        register(ConfigRepository.class, configRepository);
+
+        ConfigMBeanImpl configMBean = new ConfigMBeanImpl();
+        configMBean.setConfigRepo(configRepository);
+        registerMBean(configMBean, "type=config");
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d33e0955/config/src/main/resources/OSGI-INF/bundle.info
----------------------------------------------------------------------
diff --git a/config/src/main/resources/OSGI-INF/bundle.info b/config/src/main/resources/OSGI-INF/bundle.info
new file mode 100644
index 0000000..3cd35da
--- /dev/null
+++ b/config/src/main/resources/OSGI-INF/bundle.info
@@ -0,0 +1,27 @@
+h1. Synopsis
+
+${project.name}
+
+${project.description}
+
+Maven URL:
+[mvn:${project.groupId}/${project.artifactId}/${project.version}]
+
+h1. Description
+
+This bundle provides Karaf shell commands to manipulate the ConfigAdmin OSGi service.
+
+The following commands are available:
+* config:cancel - Cancels the changes to the configuration being edited.
+* config:edit - Creates or edits a configuration.
+* config:list - Lists existing configurations.
+* config:propappend - Appends the given value to an existing property or creates
+ the property with the specified name and value.
+* config:propdel - Deletes a property from the edited configuration.
+* config:proplist - Lists properties from the currently edited configuration.
+* config:propset - Sets a property in the currently edited configuration.
+* config:update - Saves and propagates changes from the configuration being edited.
+
+h1. See also
+
+Commands - section of the Karaf User Guide.
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/karaf/blob/d33e0955/config/src/main/resources/OSGI-INF/metatype/metatype.properties
----------------------------------------------------------------------
diff --git a/config/src/main/resources/OSGI-INF/metatype/metatype.properties b/config/src/main/resources/OSGI-INF/metatype/metatype.properties
new file mode 100644
index 0000000..3bce187
--- /dev/null
+++ b/config/src/main/resources/OSGI-INF/metatype/metatype.properties
@@ -0,0 +1,28 @@
+#
+#  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.
+#
+
+#
+# This file contains localization strings for configuration labels and
+# descriptions as used in the metatype.xml descriptor
+
+config.name = Apache Karaf Shell Config
+config.description = Configuration of Apache Karaf Shell Config
+
+storage.name = Storage directory
+storage.description = the directory used as a storage for configurations

http://git-wip-us.apache.org/repos/asf/karaf/blob/d33e0955/config/src/main/resources/OSGI-INF/metatype/metatype.xml
----------------------------------------------------------------------
diff --git a/config/src/main/resources/OSGI-INF/metatype/metatype.xml b/config/src/main/resources/OSGI-INF/metatype/metatype.xml
new file mode 100644
index 0000000..83d3242
--- /dev/null
+++ b/config/src/main/resources/OSGI-INF/metatype/metatype.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    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.
+
+-->
+<metatype:MetaData xmlns:metatype="http://www.osgi.org/xmlns/metatype/v1.0.0" localization="OSGI-INF/metatype/metatype">
+    <OCD id="org.apache.karaf.config" name="%config.name" description="%config.description">
+        <AD id="storage" type="String" default="${karaf.etc}/"
+            name="%storage.name" description="%storage.description"/>
+    </OCD>
+    <Designate pid="org.apache.karaf.config">
+        <Object ocdref="org.apache.karaf.config"/>
+    </Designate>
+</metatype:MetaData>

http://git-wip-us.apache.org/repos/asf/karaf/blob/d33e0955/config/src/main/resources/org/apache/karaf/config/command/edit.txt
----------------------------------------------------------------------
diff --git a/config/src/main/resources/org/apache/karaf/config/command/edit.txt b/config/src/main/resources/org/apache/karaf/config/command/edit.txt
new file mode 100644
index 0000000..88fa6d5
--- /dev/null
+++ b/config/src/main/resources/org/apache/karaf/config/command/edit.txt
@@ -0,0 +1,13 @@
+The edit command can be used to create or edit a configuration in three ways.
+
+Edit or create a config by pid:
+  > config:edit org.apache.karaf.sample.pid
+The command above will also create a file etc/org.apache.karaf.sample.pid which corresponds to a configuration object with pid org.apache.karaf.sample.pid.
+  
+Create a factory config by factory pid:
+  > config:edit --factory myfactorypid
+In this case the config is created with a pid like myfactorypid.<generated id>. This config is not written to a file.
+
+Edit a config specified by an ldap query
+  > config:edit '(myattribute=myvalue)'
+This executes an ldap query like in config:list. If the result is exactly one config then it is edited.


[18/59] [abbrv] [KARAF-2852] Merge bundle/command into bundle/core

Posted by gn...@apache.org.
http://git-wip-us.apache.org/repos/asf/karaf/blob/d0180939/bundle/core/src/main/java/org/apache/karaf/bundle/command/ShowBundleTree.java
----------------------------------------------------------------------
diff --git a/bundle/core/src/main/java/org/apache/karaf/bundle/command/ShowBundleTree.java b/bundle/core/src/main/java/org/apache/karaf/bundle/command/ShowBundleTree.java
new file mode 100644
index 0000000..a83ce39
--- /dev/null
+++ b/bundle/core/src/main/java/org/apache/karaf/bundle/command/ShowBundleTree.java
@@ -0,0 +1,245 @@
+/*
+ * 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.karaf.bundle.command;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.felix.utils.manifest.Clause;
+import org.apache.felix.utils.manifest.Parser;
+import org.apache.felix.utils.version.VersionRange;
+import org.apache.felix.utils.version.VersionTable;
+import org.apache.karaf.bundle.command.bundletree.Node;
+import org.apache.karaf.bundle.command.bundletree.Tree;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.Constants;
+import org.osgi.framework.wiring.BundleCapability;
+import org.osgi.framework.wiring.BundleRevision;
+import org.osgi.framework.wiring.BundleRevisions;
+import org.osgi.framework.wiring.BundleWire;
+import org.osgi.framework.wiring.BundleWiring;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import static java.lang.String.format;
+
+/**
+ * Command for showing the full tree of bundles that have been used to resolve
+ * a given bundle.
+ */
+@Command(scope = "bundle", name = "tree-show", description = "Shows the tree of bundles based on the wiring information.")
+@Service
+public class ShowBundleTree extends BundleCommand {
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(ShowBundleTree.class);
+    private Tree<Bundle> tree;
+
+    public ShowBundleTree() {
+        super(false);
+    }
+
+    @Override
+    protected void doExecute(Bundle bundle) throws Exception {
+        long start = System.currentTimeMillis();
+        // let's do the real work here
+        printHeader(bundle);
+        tree = new Tree<Bundle>(bundle);
+        createTree(bundle);
+        printTree(tree);
+        printDuplicatePackages(tree);
+        LOGGER.debug(format("Dependency tree calculated in %d ms",
+                            System.currentTimeMillis() - start));
+    }
+    
+    /**
+     * Return a String representation of a bundle state
+     */
+    private String getState(Bundle bundle) {
+        switch (bundle.getState()) {
+            case Bundle.UNINSTALLED : return "UNINSTALLED";
+            case Bundle.INSTALLED : return "INSTALLED";
+            case Bundle.RESOLVED: return "RESOLVED";
+            case Bundle.STARTING : return "STARTING";
+            case Bundle.STOPPING : return "STOPPING";
+            case Bundle.ACTIVE : return "ACTIVE";
+            default : return "UNKNOWN";
+        }
+    }
+
+    /*
+     * Print the header
+     */
+    private void printHeader(Bundle bundle) {
+        System.out.printf("Bundle %s [%s] is currently %s%n",
+                bundle.getSymbolicName(),
+                bundle.getBundleId(),
+                getState(bundle));
+    }
+
+    /*
+     * Print the dependency tree
+     */
+    private void printTree(Tree<Bundle> tree) {
+        System.out.printf("%n");
+        tree.write(System.out, new Tree.Converter<Bundle>() {
+
+            public String toString(Node<Bundle> node) {
+                return String.format("%s [%s]",
+                                     node.getValue().getSymbolicName(),
+                                     node.getValue().getBundleId());
+            }
+        });
+    }
+
+    /*
+     * Check for bundles in the tree exporting the same package
+     * as a possible cause for 'Unresolved constraint...' on a uses-conflict
+     */
+    private void printDuplicatePackages(Tree<Bundle> tree) {
+        Set<Bundle> bundles = tree.flatten();
+        Map<String, Set<Bundle>> exports = new HashMap<String, Set<Bundle>>();
+
+        for (Bundle bundle : bundles) {
+            for (BundleRevision revision : bundle.adapt(BundleRevisions.class).getRevisions()) {
+                BundleWiring wiring = revision.getWiring();
+                if (wiring != null) {
+                    List<BundleWire> wires = wiring.getProvidedWires(BundleRevision.PACKAGE_NAMESPACE);
+                    if (wires != null) {
+                        for (BundleWire wire : wires) {
+                            String name = wire.getCapability().getAttributes().get(BundleRevision.PACKAGE_NAMESPACE).toString();
+                            if (exports.get(name) == null) {
+                                exports.put(name, new HashSet<Bundle>());
+                            }
+                            exports.get(name).add(bundle);
+                        }
+                    }
+                }
+            }
+        }
+
+        for (String pkg : exports.keySet()) {
+            if (exports.get(pkg).size() > 1) {
+                System.out.printf("%n");
+                System.out.printf("WARNING: multiple bundles are exporting package %s%n", pkg);
+                for (Bundle bundle : exports.get(pkg)) {
+                    System.out.printf("- %s%n", bundle);
+                }
+            }
+        }
+    }
+
+    /*
+     * Creates the bundle tree
+     */
+    protected void createTree(Bundle bundle) {
+        if (bundle.getState() >= Bundle.RESOLVED) {
+            createNode(tree);
+        } else {
+            createNodesForImports(tree, bundle);
+            System.out.print("\nWarning: the below tree is a rough approximation of a possible resolution");
+        }
+    }
+
+    /*
+     * Creates nodes for the imports of the bundle (instead of reporting wiring information
+     */
+    private void createNodesForImports(Node<Bundle> node, Bundle bundle) {
+        Clause[] imports = Parser.parseHeader(bundle.getHeaders().get("Import-Package"));
+        Clause[] exports = Parser.parseHeader(bundle.getHeaders().get("Export-Package"));
+        for (Clause i : imports) {
+            boolean exported = false;
+            for (Clause e : exports) {
+                if (e.getName().equals(i.getName())) {
+                    exported = true;
+                    break;
+                }
+            }
+            if (!exported) {
+                createNodeForImport(node, bundle, i);
+            }
+        }
+    }
+
+    /*
+     * Create a child node for a given import (by finding a matching export in the currently installed bundles)
+     */
+    private void createNodeForImport(Node<Bundle> node, Bundle bundle, Clause i) {
+        VersionRange range = VersionRange.parseVersionRange(i.getAttribute(Constants.VERSION_ATTRIBUTE));
+        boolean foundMatch = false;
+        for (Bundle b : bundleContext.getBundles()) {
+            BundleWiring wiring = b.adapt(BundleWiring.class);
+            if (wiring != null) {
+                List<BundleCapability> caps = wiring.getCapabilities(BundleRevision.PACKAGE_NAMESPACE);
+                if (caps != null) {
+                    for (BundleCapability cap : caps) {
+                        String n = getAttribute(cap, BundleRevision.PACKAGE_NAMESPACE);
+                        String v = getAttribute(cap, Constants.VERSION_ATTRIBUTE);
+                        if (i.getName().equals(n) && range.contains(VersionTable.getVersion(v))) {
+                            boolean existing = tree.flatten().contains(b);
+                            System.out.printf("- import %s: resolved using %s%n", i, b);
+                            foundMatch = true;
+                            if (!node.hasChild(b)) {
+                                Node<Bundle> child = node.addChild(b);
+                                if (!existing) {
+                                    createNode(child);
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        if (!foundMatch) {
+            System.out.printf("- import %s: WARNING - unable to find matching export%n", i);
+        }
+    }
+
+    private String getAttribute(BundleCapability capability, String name) {
+        Object o = capability.getAttributes().get(name);
+        return o != null ? o.toString() : null;
+    }
+
+    /*
+    * Creates a node in the bundle tree
+    */
+    private void createNode(Node<Bundle> node) {
+        Bundle bundle = node.getValue();
+        Collection<Bundle> exporters = new HashSet<Bundle>();
+        exporters.addAll(bundleService.getWiredBundles(bundle).values());
+
+        for (Bundle exporter : exporters) {
+            if (node.hasAncestor(exporter)) {                
+                LOGGER.debug(format("Skipping %s (already exists in the current branch)", exporter));
+            } else {
+                boolean existing = tree.flatten().contains(exporter);
+                LOGGER.debug(format("Adding %s as a dependency for %s", exporter, bundle));
+                Node<Bundle> child = node.addChild(exporter);
+                if (existing) {
+                    LOGGER.debug(format("Skipping children of %s (already exists in another branch)", exporter));
+                } else {
+                    createNode(child);
+                }
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d0180939/bundle/core/src/main/java/org/apache/karaf/bundle/command/Start.java
----------------------------------------------------------------------
diff --git a/bundle/core/src/main/java/org/apache/karaf/bundle/command/Start.java b/bundle/core/src/main/java/org/apache/karaf/bundle/command/Start.java
new file mode 100644
index 0000000..48e90fa
--- /dev/null
+++ b/bundle/core/src/main/java/org/apache/karaf/bundle/command/Start.java
@@ -0,0 +1,32 @@
+/*
+ * 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.karaf.bundle.command;
+
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.osgi.framework.Bundle;
+
+@Command(scope = "bundle", name = "start", description = "Starts bundles.")
+@Service
+public class Start extends BundlesCommandWithConfirmation {
+
+    @Override
+    protected void executeOnBundle(Bundle bundle) throws Exception {
+        bundle.start();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d0180939/bundle/core/src/main/java/org/apache/karaf/bundle/command/StartLevel.java
----------------------------------------------------------------------
diff --git a/bundle/core/src/main/java/org/apache/karaf/bundle/command/StartLevel.java b/bundle/core/src/main/java/org/apache/karaf/bundle/command/StartLevel.java
new file mode 100644
index 0000000..30bec0f
--- /dev/null
+++ b/bundle/core/src/main/java/org/apache/karaf/bundle/command/StartLevel.java
@@ -0,0 +1,64 @@
+/*
+ * 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.karaf.bundle.command;
+
+import org.apache.karaf.shell.api.action.Argument;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.console.Session;
+import org.apache.karaf.shell.api.action.lifecycle.Reference;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.startlevel.BundleStartLevel;
+
+@Command(scope = "bundle", name = "start-level", description = "Gets or sets the start level of a bundle.")
+@Service
+public class StartLevel extends BundleCommandWithConfirmation {
+
+    @Argument(index = 1, name = "startLevel", description = "The bundle's new start level", required = false, multiValued = false)
+    Integer level;
+
+    @Reference
+    Session session;
+
+    protected void doExecute(Bundle bundle) throws Exception {
+        // Get package instance service.
+        BundleStartLevel bsl = bundle.adapt(BundleStartLevel.class);
+        if (bsl == null) {
+            System.out.println("StartLevel service is unavailable.");
+            return;
+        }
+        if (level == null) {
+            System.out.println("Level " + bsl.getStartLevel());
+        }
+        else if ((level < 50) && (bsl.getStartLevel() > 50) && !force){
+            for (;;) {
+                String msg = "You are about to designate bundle as a system bundle.  Do you wish to continue (yes/no): ";
+                String str = session.readLine(msg, null);
+                if ("yes".equalsIgnoreCase(str)) {
+                    bsl.setStartLevel(level);
+                    break;
+                } else if ("no".equalsIgnoreCase(str)) {
+                    break;
+                }
+            }
+
+        } else {
+            bsl.setStartLevel(level);
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d0180939/bundle/core/src/main/java/org/apache/karaf/bundle/command/Stop.java
----------------------------------------------------------------------
diff --git a/bundle/core/src/main/java/org/apache/karaf/bundle/command/Stop.java b/bundle/core/src/main/java/org/apache/karaf/bundle/command/Stop.java
new file mode 100644
index 0000000..0b0fed2
--- /dev/null
+++ b/bundle/core/src/main/java/org/apache/karaf/bundle/command/Stop.java
@@ -0,0 +1,44 @@
+/*
+ * 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.karaf.bundle.command;
+
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.Option;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.osgi.framework.Bundle;
+
+@Command(scope = "bundle", name = "stop", description = "Stop bundles.")
+@Service
+public class Stop extends BundlesCommandWithConfirmation {
+    
+	@Option(name = "-t", aliases={"--transient"}, description="Keep the bundle as auto-start", required = false, multiValued = false)
+	boolean transientStop;
+	
+    public Stop() {
+        this.errorMessage = "Unable to stop bundle";
+    }
+
+    @Override
+    protected void executeOnBundle(Bundle bundle) throws Exception {
+    	if (transientStop) {
+    		bundle.stop(Bundle.STOP_TRANSIENT);
+    	} else {
+    		bundle.stop();
+    	}
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d0180939/bundle/core/src/main/java/org/apache/karaf/bundle/command/Uninstall.java
----------------------------------------------------------------------
diff --git a/bundle/core/src/main/java/org/apache/karaf/bundle/command/Uninstall.java b/bundle/core/src/main/java/org/apache/karaf/bundle/command/Uninstall.java
new file mode 100644
index 0000000..67b5b14
--- /dev/null
+++ b/bundle/core/src/main/java/org/apache/karaf/bundle/command/Uninstall.java
@@ -0,0 +1,36 @@
+/*
+ * 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.karaf.bundle.command;
+
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.osgi.framework.Bundle;
+
+@Command(scope = "bundle", name = "uninstall", description = "Uninstall bundles.")
+@Service
+public class Uninstall extends BundlesCommandWithConfirmation {
+    
+    public Uninstall() {
+        this.errorMessage = "Unable to uninstall bundle";
+    }
+
+    @Override
+    protected void executeOnBundle(Bundle bundle) throws Exception {
+        bundle.uninstall();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d0180939/bundle/core/src/main/java/org/apache/karaf/bundle/command/Update.java
----------------------------------------------------------------------
diff --git a/bundle/core/src/main/java/org/apache/karaf/bundle/command/Update.java b/bundle/core/src/main/java/org/apache/karaf/bundle/command/Update.java
new file mode 100644
index 0000000..71ae74d
--- /dev/null
+++ b/bundle/core/src/main/java/org/apache/karaf/bundle/command/Update.java
@@ -0,0 +1,48 @@
+/*
+ * 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.karaf.bundle.command;
+
+import java.io.InputStream;
+import java.net.URL;
+
+import org.apache.karaf.shell.api.action.Argument;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.osgi.framework.Bundle;
+
+@Command(scope = "bundle", name = "update", description = "Update bundle.")
+@Service
+public class Update extends BundleCommandWithConfirmation {
+
+    @Argument(index = 1, name = "location", description = "The bundles update location", required = false, multiValued = false)
+    String location;
+
+    protected void doExecute(Bundle bundle) throws Exception {
+        InputStream is = null;
+        if (location != null) {
+            try {
+                is = new URL(location).openStream();
+                bundle.update(is);
+            } finally {
+                is.close();
+            }
+        } else {
+            bundle.update();
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d0180939/bundle/core/src/main/java/org/apache/karaf/bundle/command/Watch.java
----------------------------------------------------------------------
diff --git a/bundle/core/src/main/java/org/apache/karaf/bundle/command/Watch.java b/bundle/core/src/main/java/org/apache/karaf/bundle/command/Watch.java
new file mode 100644
index 0000000..9203f59
--- /dev/null
+++ b/bundle/core/src/main/java/org/apache/karaf/bundle/command/Watch.java
@@ -0,0 +1,128 @@
+/*
+ * 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.karaf.bundle.command;
+
+import java.util.List;
+
+import org.apache.karaf.bundle.core.BundleWatcher;
+import org.apache.karaf.shell.api.action.Action;
+import org.apache.karaf.shell.api.action.Argument;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.Option;
+import org.apache.karaf.shell.api.action.lifecycle.Reference;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.Constants;
+
+@Command(scope = "bundle", name = "watch", description = "Watches and updates bundles", detailedDescription = "Watches the local maven repo for changes in snapshot jars and redploys changed jars")
+@Service
+public class Watch implements Action {
+
+    @Argument(index = 0, name = "urls", description = "The bundle IDs or URLs", required = false, multiValued = true)
+    List<String> urls;
+
+    @Option(name = "-i", aliases = {}, description = "Watch interval", required = false, multiValued = false)
+    private long interval;
+
+    @Option(name = "--start", description = "Starts watching the selected bundles", required = false, multiValued = false)
+    protected boolean start;
+
+    @Option(name = "--stop", description = "Stops watching all bundles", required = false, multiValued = false)
+    protected boolean stop;
+
+    @Option(name = "--remove", description = "Removes bundles from the watch list", required = false, multiValued = false)
+    protected boolean remove;
+
+    @Option(name = "--list", description = "Displays the watch list", required = false, multiValued = false)
+    protected boolean list;
+
+    @Reference
+    private BundleWatcher bundleWatcher;
+
+    public void setBundleWatcher(BundleWatcher bundleWatcher) {
+        this.bundleWatcher = bundleWatcher;
+    }
+
+    @Override
+    public Object execute() throws Exception {
+        if (start && stop) {
+            System.err.println("Please use only one of --start and --stop options!");
+            return null;
+        }
+
+        if (interval > 0) {
+            System.out.println("Setting watch interval to " + interval + " ms");
+            bundleWatcher.setInterval(interval);
+        }
+        if (stop) {
+            System.out.println("Stopping watch");
+            bundleWatcher.stop();
+        }
+        if (urls != null) {
+            if (remove) {
+                for (String url : urls) {
+                    bundleWatcher.remove(url);
+                }
+            } else {
+                for (String url : urls) {
+                    bundleWatcher.add(url);
+                }
+            }
+        }
+        if (start) {
+            System.out.println("Starting watch");
+            bundleWatcher.start();
+        }
+
+        if (list) { //List the watched bundles.
+            String format = "%-40s %6s %-80s";
+            System.out.println(String.format(format, "URL", "ID", "Bundle Name"));
+            for (String url : bundleWatcher.getWatchURLs()) {
+
+                List<Bundle> bundleList = bundleWatcher.getBundlesByURL(url);
+                if (bundleList != null && bundleList.size() > 0) {
+                    for (Bundle bundle : bundleList) {
+                        System.out.println(String.format(format, url, bundle.getBundleId(), bundle.getHeaders().get(Constants.BUNDLE_NAME)));
+                    }
+                } else {
+                    System.out.println(String.format(format, url, "", ""));
+                }
+            }
+        } else {
+            List<String> urls = bundleWatcher.getWatchURLs();
+            if (urls != null && urls.size()>0) {
+                System.out.println("Watched URLs/IDs: ");
+                for (String url : bundleWatcher.getWatchURLs()) {
+                    System.out.println(url);
+                }
+            } else {
+                System.out.println("No watched URLs/IDs");
+            }
+        }
+
+        return null;
+    }
+
+}
+
+
+
+
+
+
+
+

http://git-wip-us.apache.org/repos/asf/karaf/blob/d0180939/bundle/core/src/main/java/org/apache/karaf/bundle/command/bundletree/Node.java
----------------------------------------------------------------------
diff --git a/bundle/core/src/main/java/org/apache/karaf/bundle/command/bundletree/Node.java b/bundle/core/src/main/java/org/apache/karaf/bundle/command/bundletree/Node.java
new file mode 100644
index 0000000..fe4dc2a
--- /dev/null
+++ b/bundle/core/src/main/java/org/apache/karaf/bundle/command/bundletree/Node.java
@@ -0,0 +1,159 @@
+/*
+ * 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.karaf.bundle.command.bundletree;
+
+import java.io.PrintWriter;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Represents a node in a {@link Tree}
+ */
+public class Node<T> {
+    
+    private final T value;
+    private Node<T> parent;
+    private List<Node<T>> children = new LinkedList<Node<T>>();
+
+    /**
+     * Creates a new node. Only meant for wrapper use,
+     * new nodes should be added using the {@link #addChild(Object)} method
+     *
+     * @param value the node value
+     */
+    protected Node(T value) {
+        super();
+        this.value = value;
+    }
+
+    /**
+     * Creates a new node. Only meant for wrapper use,
+     * new nodes should be added using the {@link #addChild(Object)} method
+     *
+     * @param value the node value
+     */
+    protected Node(T value, Node<T> parent) {
+        this(value);
+        this.parent = parent;
+    }
+
+    /**
+     * Access the node's value
+     */
+    public T getValue() {
+        return value;
+    }
+
+    /**
+     * Access the node's child nodes
+     */
+    public List<Node<T>> getChildren() {
+        return children;
+    }
+
+    /**
+     * Adds a child to this node
+     *
+     * @param value the child's value
+     * @return the child node
+     */
+    public Node<T> addChild(T value) {
+        Node<T> node = new Node<T>(value, this);
+        children.add(node);
+        return node;
+    }
+
+    /**
+     * Give a set of values in the tree.
+     *
+     * @return
+     */
+    public Set<T> flatten() {
+        Set<T> result = new HashSet<T>();
+        result.add(getValue());
+        for (Node<T> child : getChildren()) {
+            result.addAll(child.flatten());
+        }
+        return result;
+    }
+
+    /**
+     * Check if the node has an ancestor that represents the given value
+     *
+     * @param value the node value
+     * @return <code>true</code> it there's an ancestor that represents the value
+     */
+    public boolean hasAncestor(T value) {
+        if (parent == null) {
+            return false;
+        } else {
+            return value.equals(parent.value) || parent.hasAncestor(value);
+        }
+    }
+    
+    public boolean hasChild(T value) {
+        for (Node<T> child : getChildren()) {
+            if (value.equals(child.getValue())) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /*
+     * Write this node to the PrintWriter.  It should be indented one step
+     * further for every element in the indents array.  If an element in the
+     * array is <code>true</code>, there should be a | to connect to the next
+     * sibling.
+     */
+    protected void write(PrintWriter writer, Tree.Converter<T> converter, boolean... indents) {
+        for (boolean indent : indents) {
+            writer.printf("%-3s", indent ? "|" : "");
+        }
+        writer.printf("+- %s%n", converter.toString(this));
+        for (Node<T> child : getChildren()) {
+            child.write(writer, converter, concat(indents, hasNextSibling()));
+        }
+    }
+
+    /*
+     * Is this node the last child node for its parent
+     * or is there a next sibling?
+     */
+    private boolean hasNextSibling() {
+        if (parent == null) {
+            return false;
+        } else {
+            return parent.getChildren().size() > 1
+                    && parent.getChildren().indexOf(this) < parent.getChildren().size() - 1;
+        }
+    }
+
+    /*
+     * Add an element to the end of the array
+     */
+    private boolean[] concat(boolean[] array, boolean element) {
+        boolean[] result = new boolean[array.length + 1];
+        for (int i = 0 ; i < array.length ; i++) {
+            result[i] = array[i];
+        }
+        result[array.length] = element;
+        return result;
+    }
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d0180939/bundle/core/src/main/java/org/apache/karaf/bundle/command/bundletree/Tree.java
----------------------------------------------------------------------
diff --git a/bundle/core/src/main/java/org/apache/karaf/bundle/command/bundletree/Tree.java b/bundle/core/src/main/java/org/apache/karaf/bundle/command/bundletree/Tree.java
new file mode 100644
index 0000000..7a7b64e
--- /dev/null
+++ b/bundle/core/src/main/java/org/apache/karaf/bundle/command/bundletree/Tree.java
@@ -0,0 +1,100 @@
+/*
+ * 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.karaf.bundle.command.bundletree;
+
+import java.io.PrintStream;
+import java.io.PrintWriter;
+
+/**
+ * Represents a tree that can be written to the console.
+ *
+ * The output will look like this:
+ * <pre>
+ * root
+ * +- child1
+ * |  +- grandchild
+ * +- child2
+ * </pre>
+ */
+public class Tree<T> extends Node<T> {
+
+    /**
+     * Creates a new tree with the given root node
+     *
+     * @param root the root node
+     */
+    public Tree(T root) {
+        super(root);
+    }
+
+    /**
+     * Write the tree to a PrintStream, using the default toString() method to output the node values
+     *
+     * @param stream
+     */
+    public void write(PrintStream stream) {
+        write(new PrintWriter(stream));
+    }
+
+    /**
+     * Write the tree to a PrintStream, using the provided converter to output the node values
+     *
+     * @param stream
+     * @param converter
+     */
+    public void write(PrintStream stream, Converter<T> converter) {
+        write(new PrintWriter(stream), converter);
+    }
+
+    /**
+     * Write the tree to a PrintWriter, using the default toString() method to output the node values
+     *
+     * @param writer
+     */
+    public void write(PrintWriter writer) {
+        write(writer, new Converter() {
+            public String toString(Node node) {
+                return node.getValue().toString();
+            }
+        });
+    }
+
+    /**
+     * Write the tree to a PrintWriter, using the provided converter to output the node values
+     *
+     * @param writer
+     * @param converter
+     */
+    public void write(PrintWriter writer, Converter<T> converter) {
+        writer.printf("%s%n", converter.toString(this));
+        for (Node<T> child : getChildren()) {
+            child.write(writer, converter);
+        }
+        writer.flush();
+    }
+
+    /**
+     * Interface to convert node values to string
+     *
+     * @param <T> the object type for the node value
+     */
+    public static interface Converter<T> {
+
+        public String toString(Node<T> node);
+
+    }
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d0180939/bundle/core/src/main/java/org/apache/karaf/bundle/command/wikidoc/AnsiPrintingWikiVisitor.java
----------------------------------------------------------------------
diff --git a/bundle/core/src/main/java/org/apache/karaf/bundle/command/wikidoc/AnsiPrintingWikiVisitor.java b/bundle/core/src/main/java/org/apache/karaf/bundle/command/wikidoc/AnsiPrintingWikiVisitor.java
new file mode 100644
index 0000000..077cfef
--- /dev/null
+++ b/bundle/core/src/main/java/org/apache/karaf/bundle/command/wikidoc/AnsiPrintingWikiVisitor.java
@@ -0,0 +1,58 @@
+/*
+ * 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.karaf.bundle.command.wikidoc;
+
+import java.io.PrintStream;
+
+import org.fusesource.jansi.Ansi;
+import org.fusesource.jansi.Ansi.Attribute;
+import org.fusesource.jansi.Ansi.Color;
+
+/**
+ * Translates the Wiki tags to Ansi escape sequences to display them on the console
+ */
+public class AnsiPrintingWikiVisitor implements WikiVisitor {
+	private PrintStream out;
+	
+	public AnsiPrintingWikiVisitor(PrintStream out) {
+		this.out = out;
+	}
+	
+	@Override
+	public void heading(int level, String header) {
+		this.out.print(Ansi.ansi().a(Attribute.INTENSITY_BOLD).a(header)
+				.a(Attribute.INTENSITY_BOLD_OFF).toString());
+	}
+	
+	@Override
+	public void link(String target, String title) {
+		this.out.print(Ansi.ansi().fg(Color.YELLOW) 
+				.a(target).fg(Color.DEFAULT));
+	}
+
+	@Override
+	public void enumeration(String text) {
+		this.out.print(Ansi.ansi().a(" * ").fg(Color.CYAN).a(text).fg(Color.DEFAULT).a(" "));
+	}
+
+	@Override
+	public void text(String text) {
+		this.out.print(text);
+	}
+
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d0180939/bundle/core/src/main/java/org/apache/karaf/bundle/command/wikidoc/WikiParser.java
----------------------------------------------------------------------
diff --git a/bundle/core/src/main/java/org/apache/karaf/bundle/command/wikidoc/WikiParser.java b/bundle/core/src/main/java/org/apache/karaf/bundle/command/wikidoc/WikiParser.java
new file mode 100644
index 0000000..8ec3d5b
--- /dev/null
+++ b/bundle/core/src/main/java/org/apache/karaf/bundle/command/wikidoc/WikiParser.java
@@ -0,0 +1,86 @@
+/*
+ * 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.karaf.bundle.command.wikidoc;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.Reader;
+import java.util.StringTokenizer;
+
+/**
+ * Parses wiki syntax from a reader and calls a Wikivisitor with the 
+ * tokens it finds
+ */
+public class WikiParser {
+	WikiVisitor visitor;
+	
+	public WikiParser(WikiVisitor visitor) {
+		this.visitor = visitor;
+	}
+
+	public void parse(String line) {
+		StringTokenizer tokenizer = new StringTokenizer(line , "[h*", true);
+		while (tokenizer.hasMoreTokens()) {
+			String token = tokenizer.nextToken();
+			if ("[".equals(token)) {
+				parseLink(tokenizer);
+			} else if ("h".equals(token)) {
+				parseHeading(tokenizer);
+			} else if ("*".equals(token)){
+				parseEnumeration(tokenizer);
+			} else {
+				visitor.text(token);
+			}
+		}
+	}
+	
+	private void parseEnumeration(StringTokenizer tokenizer) {
+		String text = tokenizer.nextToken("-\n");
+		visitor.enumeration(text.trim());
+	}
+
+	private void parseHeading(StringTokenizer tokenizer) {
+		String level = tokenizer.nextToken("123456789");
+		if (!level.matches("[123456789]")) {
+			visitor.text("h" + level);
+			return;
+		}
+		String dot = tokenizer.nextToken(".\n");
+		if (!".".equals(dot)) {
+			visitor.text("h" + level + dot);
+			return;
+		}
+		String heading = tokenizer.hasMoreTokens() ? tokenizer.nextToken("\n") : "";
+		visitor.heading(new Integer(level), heading.trim());
+	}
+
+	private void parseLink(StringTokenizer tokenizer) {
+		String token = tokenizer.nextToken("]");
+		visitor.link(token, "");
+		tokenizer.nextToken();
+	}
+
+	public void parse(Reader reader) throws IOException {
+		BufferedReader br = new BufferedReader(reader);
+		String line;
+		while ((line = br.readLine()) != null) {
+			parse(line);
+			visitor.text("\n");
+		}
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d0180939/bundle/core/src/main/java/org/apache/karaf/bundle/command/wikidoc/WikiVisitor.java
----------------------------------------------------------------------
diff --git a/bundle/core/src/main/java/org/apache/karaf/bundle/command/wikidoc/WikiVisitor.java b/bundle/core/src/main/java/org/apache/karaf/bundle/command/wikidoc/WikiVisitor.java
new file mode 100644
index 0000000..b4a5fb3
--- /dev/null
+++ b/bundle/core/src/main/java/org/apache/karaf/bundle/command/wikidoc/WikiVisitor.java
@@ -0,0 +1,29 @@
+/*
+ * 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.karaf.bundle.command.wikidoc;
+
+/**
+ * Will be used by WikiParser to call the respective handler when it recognizes the tag 
+ */
+public interface WikiVisitor {
+
+	void link(String target, String title);
+	void heading(int level, String title);
+	void enumeration(String text);
+	void text(String text);
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/karaf/blob/d0180939/bundle/core/src/test/java/org/apache/karaf/bundle/command/ListServicesTest.java
----------------------------------------------------------------------
diff --git a/bundle/core/src/test/java/org/apache/karaf/bundle/command/ListServicesTest.java b/bundle/core/src/test/java/org/apache/karaf/bundle/command/ListServicesTest.java
new file mode 100644
index 0000000..876f605
--- /dev/null
+++ b/bundle/core/src/test/java/org/apache/karaf/bundle/command/ListServicesTest.java
@@ -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.karaf.bundle.command;
+
+import java.util.Arrays;
+import java.util.Collections;
+
+import org.apache.karaf.bundle.core.internal.BundleServiceImpl;
+import org.junit.Test;
+import org.osgi.framework.BundleContext;
+
+public class ListServicesTest {
+
+    private ListBundleServices listServices;
+
+    @SuppressWarnings("unchecked")
+    public ListServicesTest() {
+        listServices = new ListBundleServices();
+        BundleContext bundleContext = new TestBundleFactory().createBundleContext();
+        listServices.setBundleContext(bundleContext);
+        listServices.setBundleService(new BundleServiceImpl(bundleContext));
+    }
+    
+    @Test
+    public void listAllShort() throws Exception {
+        System.out.println("listAllShort");
+        listServices.execute();
+    }
+
+    
+    @Test
+    public void listAllLong() throws Exception {
+        System.out.println("listAllLong");
+        listServices.ids = Arrays.asList(new String[]{"1", "2"});
+        listServices.execute();
+    }
+
+    @Test
+    public void listAllLongServiceUse() throws Exception {
+        System.out.println("listAllLongServicesUse");
+        listServices.ids = Arrays.asList(new String[]{"1", "2"});
+        listServices.inUse = true;
+        listServices.execute();
+    }
+
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d0180939/bundle/core/src/test/java/org/apache/karaf/bundle/command/TestBundleFactory.java
----------------------------------------------------------------------
diff --git a/bundle/core/src/test/java/org/apache/karaf/bundle/command/TestBundleFactory.java b/bundle/core/src/test/java/org/apache/karaf/bundle/command/TestBundleFactory.java
new file mode 100644
index 0000000..27e4a63
--- /dev/null
+++ b/bundle/core/src/test/java/org/apache/karaf/bundle/command/TestBundleFactory.java
@@ -0,0 +1,104 @@
+/*
+ * 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.karaf.bundle.command;
+
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
+
+import java.util.Collections;
+import java.util.Dictionary;
+import java.util.Hashtable;
+
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceReference;
+
+public class TestBundleFactory {
+    ServiceReference<?> createServiceRef(Object ... keyProp) {
+        ServiceReference<?> serviceRef = createMock(ServiceReference.class);
+        if (keyProp.length % 2 != 0) {
+            throw new IllegalArgumentException("");
+        }
+        Hashtable<String, Object> keyPropMap = new Hashtable<String, Object>();
+        int c = 0;
+        while (c < keyProp.length) {
+            String key = (String)keyProp[c++];
+            Object value = (Object)keyProp[c++];
+            keyPropMap.put(key, value);
+            expect(serviceRef.getProperty(key)).andReturn(value).anyTimes();
+        }
+        expect(serviceRef.getPropertyKeys()).andReturn(Collections.list(keyPropMap.keys()).toArray(new String[]{})).anyTimes();
+        return serviceRef;
+    }
+    
+    Bundle createBundle(long id, String name) {
+        Bundle bundle = createMock(Bundle.class);
+        expect(bundle.getBundleId()).andReturn(id).anyTimes();
+        Dictionary<String, String> headers = new Hashtable<String, String>();
+        headers.put(Constants.BUNDLE_NAME, name);
+        expect(bundle.getHeaders()).andReturn(headers).anyTimes();
+        return bundle;
+    }
+    
+    private Bundle[] createBundles() {
+        Bundle bundle1 = createBundle(1, "Bundle A");
+        Bundle bundle2 = createBundle(2, "Bundle B");
+        Bundle bundle3 = createBundle(3, "Bundle C");
+
+        ServiceReference<?> ref1 = createServiceRef(Constants.OBJECTCLASS, new String[]{"org.example.MyService"},
+            "key1", "value1");
+        ServiceReference<?> ref2 = createServiceRef(Constants.OBJECTCLASS, new String[]{"org.example.OtherService"}, "key2", 1);
+
+        addRegisteredServices(bundle1, ref1, ref2);
+        addRegisteredServices(bundle2, ref2);
+        expect(bundle3.getRegisteredServices()).andReturn(null).anyTimes();
+
+        expect(bundle1.getServicesInUse()).andReturn(null).anyTimes();
+        addUsedServices(bundle2, ref1);
+        addUsedServices(bundle3, ref1, ref2);
+        
+        expect(ref1.getUsingBundles()).andReturn(new Bundle[]{bundle2, bundle3}).anyTimes();
+        expect(ref2.getUsingBundles()).andReturn(new Bundle[]{bundle3}).anyTimes();
+
+        replay(bundle1, bundle2, bundle3, ref1, ref2);
+        return new Bundle[] { bundle1, bundle2, bundle3 };
+    }
+    
+    private void addUsedServices(Bundle bundle, ServiceReference<?> ... refs) {
+        expect(bundle.getServicesInUse()).andReturn(refs).anyTimes();
+    }
+    
+    private void addRegisteredServices(Bundle bundle, ServiceReference<?> ... refs) {
+        expect(bundle.getRegisteredServices()).andReturn(refs).anyTimes();
+        for (ServiceReference<?> ref : refs) {
+            expect(ref.getBundle()).andReturn(bundle);
+        }
+    }
+
+    public BundleContext createBundleContext() {
+        BundleContext bundleContext = createMock(BundleContext.class);
+        Bundle[] bundles = createBundles();
+        expect(bundleContext.getBundles()).andReturn(bundles).anyTimes();
+        expect(bundleContext.getBundle(0)).andReturn(null).anyTimes();
+        expect(bundleContext.getBundle(1)).andReturn(bundles[0]).anyTimes();
+        expect(bundleContext.getBundle(2)).andReturn(bundles[1]).anyTimes();
+        replay(bundleContext);
+        return bundleContext;
+    }
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d0180939/bundle/core/src/test/java/org/apache/karaf/bundle/command/bundletree/TreeTest.java
----------------------------------------------------------------------
diff --git a/bundle/core/src/test/java/org/apache/karaf/bundle/command/bundletree/TreeTest.java b/bundle/core/src/test/java/org/apache/karaf/bundle/command/bundletree/TreeTest.java
new file mode 100644
index 0000000..df0d7d6
--- /dev/null
+++ b/bundle/core/src/test/java/org/apache/karaf/bundle/command/bundletree/TreeTest.java
@@ -0,0 +1,135 @@
+/*
+ * 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.karaf.bundle.command.bundletree;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.util.Set;
+
+import org.apache.karaf.bundle.command.bundletree.Node;
+import org.apache.karaf.bundle.command.bundletree.Tree;
+import org.junit.Test;
+
+/**
+ * Test cases for {@link org.apache.karaf.shell.dev.util.Tree}
+ * and {@link org.apache.karaf.shell.dev.util.Node}
+ */
+public class TreeTest {
+
+    @Test
+    public void writeTreeWithOneChild() throws IOException {
+        Tree<String> tree = new Tree<String>("root");
+        tree.addChild("child");
+
+        BufferedReader reader = read(tree);
+
+        assertEquals("root"     , reader.readLine());
+        assertEquals("+- child" , reader.readLine());
+    }
+
+    @Test
+    public void writeTreeWithOneChildAndNodeConverter() throws IOException {
+        Tree<String> tree = new Tree<String>("root");
+        tree.addChild("child");
+
+        StringWriter writer = new StringWriter();
+        tree.write(new PrintWriter(writer), new Tree.Converter<String>() {
+            public String toString(Node<String> node) {
+                return "my " + node.getValue();
+            }
+        });
+
+        BufferedReader reader = new BufferedReader(new StringReader(writer.getBuffer().toString()));
+
+        assertEquals("my root"     , reader.readLine());
+        assertEquals("+- my child" , reader.readLine());
+    }
+
+    @Test
+    public void writeTreeWithChildAndGrandChild() throws IOException {
+        Tree<String> tree = new Tree<String>("root");
+        Node<String> node = tree.addChild("child");
+        node.addChild("grandchild");
+
+        BufferedReader reader = read(tree);
+
+        assertEquals("root"            , reader.readLine());
+        assertEquals("+- child"        , reader.readLine());
+        assertEquals("   +- grandchild", reader.readLine());
+    }
+
+    @Test
+    public void writeTreeWithTwoChildrenAndOneGrandchild() throws IOException {
+        Tree<String> tree = new Tree<String>("root");
+        Node<String> child = tree.addChild("child1");
+        child.addChild("grandchild");
+        tree.addChild("child2");
+
+        BufferedReader reader = read(tree);
+
+        assertEquals("root"            , reader.readLine());
+        assertEquals("+- child1"       , reader.readLine());
+        assertEquals("|  +- grandchild", reader.readLine());
+        assertEquals("+- child2"       , reader.readLine());
+    }
+
+    @Test
+    public void flattenTree() throws IOException {
+        Tree<String> tree = new Tree<String>("root");
+        Node<String> child1 = tree.addChild("child1");
+        child1.addChild("grandchild");
+        Node child2 = tree.addChild("child2");
+        child2.addChild("grandchild");
+
+        Set<String> elements = tree.flatten();
+        assertNotNull(elements);
+        assertEquals(4, elements.size());
+        assertTrue(elements.contains("root"));
+        assertTrue(elements.contains("child1"));
+        assertTrue(elements.contains("child2"));
+        assertTrue(elements.contains("grandchild"));
+    }
+
+    @Test
+    public void hasAncestor() throws IOException {
+        Tree<String> tree = new Tree<String>("root");
+        Node<String> child1 = tree.addChild("child1");
+        child1.addChild("grandchild");
+        Node child2 = tree.addChild("child2");
+        Node node = child2.addChild("grandchild2");
+
+        assertTrue(node.hasAncestor("child2"));
+        assertTrue(node.hasAncestor("root"));
+        assertFalse(node.hasAncestor("child1"));
+    }
+
+    private BufferedReader read(Tree<String> tree) {
+        StringWriter writer = new StringWriter();
+        tree.write(new PrintWriter(writer));
+
+        BufferedReader reader = new BufferedReader(new StringReader(writer.getBuffer().toString()));
+        return reader;
+    }
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d0180939/bundle/core/src/test/java/org/apache/karaf/bundle/command/wikidoc/WikiParserTest.java
----------------------------------------------------------------------
diff --git a/bundle/core/src/test/java/org/apache/karaf/bundle/command/wikidoc/WikiParserTest.java b/bundle/core/src/test/java/org/apache/karaf/bundle/command/wikidoc/WikiParserTest.java
new file mode 100644
index 0000000..37101c3
--- /dev/null
+++ b/bundle/core/src/test/java/org/apache/karaf/bundle/command/wikidoc/WikiParserTest.java
@@ -0,0 +1,94 @@
+/*
+ * 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.karaf.bundle.command.wikidoc;
+
+import java.io.IOException;
+import java.io.StringReader;
+
+import org.easymock.EasyMock;
+import org.junit.Test;
+
+public class WikiParserTest {
+
+	private static final String TESTDOC = 
+		"h1. myTestdoc\n" +
+		"\n" +
+		"Some text\n" +
+		"* enumeration\n" +
+		" some text [a link] some more text\n" +
+		"h1 is no heading";
+	
+	private static final String HEADINGCASES = 
+		"h1.\n" +
+		"hf.";
+
+	@Test
+	public void parseTestDoc() throws IOException {
+		WikiVisitor visitor = EasyMock.createStrictMock(WikiVisitor.class);
+		visitor.heading(1, "myTestdoc");
+		EasyMock.expectLastCall();
+		visitor.text("\n");
+		EasyMock.expectLastCall();
+		visitor.text("\n");
+		EasyMock.expectLastCall();
+		visitor.text("Some text");
+		EasyMock.expectLastCall();
+		visitor.text("\n");
+		EasyMock.expectLastCall();
+		visitor.enumeration("enumeration");
+		EasyMock.expectLastCall();
+		visitor.text("\n");
+		EasyMock.expectLastCall();		
+		visitor.text(" some text ");
+		EasyMock.expectLastCall();
+		visitor.link("a link", "");
+		EasyMock.expectLastCall();
+		visitor.text(" some more text");
+		EasyMock.expectLastCall();
+		visitor.text("\n");
+		EasyMock.expectLastCall();
+		visitor.text("h1 is no heading");
+		EasyMock.expectLastCall();
+		visitor.text("\n");
+		EasyMock.expectLastCall();
+
+		EasyMock.replay(visitor);
+		WikiParser parser = new WikiParser(visitor);
+		parser.parse(new StringReader(TESTDOC));
+		EasyMock.verify(visitor);
+	}
+	
+	@Test
+	public void parseHeadingSpecialCases() throws IOException {
+		WikiVisitor visitor = EasyMock.createStrictMock(WikiVisitor.class);
+
+		visitor.heading(1, "");
+		EasyMock.expectLastCall();
+		visitor.text("\n");
+		EasyMock.expectLastCall();
+
+		visitor.text("hf.");
+		EasyMock.expectLastCall();
+		visitor.text("\n");
+		EasyMock.expectLastCall();
+		
+		EasyMock.replay(visitor);
+		WikiParser parser = new WikiParser(visitor);
+		parser.parse(new StringReader(HEADINGCASES));
+		EasyMock.verify(visitor);
+	}
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d0180939/bundle/pom.xml
----------------------------------------------------------------------
diff --git a/bundle/pom.xml b/bundle/pom.xml
index 894b64d..9900396 100644
--- a/bundle/pom.xml
+++ b/bundle/pom.xml
@@ -35,7 +35,6 @@
 
     <modules>
         <module>core</module>
-        <module>command</module>
         <module>blueprintstate</module>
         <module>springstate</module>
     </modules>


[54/59] [abbrv] [KARAF-2852] Merge region/core and region/command

Posted by gn...@apache.org.
http://git-wip-us.apache.org/repos/asf/karaf/blob/1bcdb173/region/src/main/java/org/apache/karaf/region/commands/AddRegionCommand.java
----------------------------------------------------------------------
diff --git a/region/src/main/java/org/apache/karaf/region/commands/AddRegionCommand.java b/region/src/main/java/org/apache/karaf/region/commands/AddRegionCommand.java
new file mode 100644
index 0000000..22c817b
--- /dev/null
+++ b/region/src/main/java/org/apache/karaf/region/commands/AddRegionCommand.java
@@ -0,0 +1,38 @@
+/*
+ * 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.karaf.region.commands;
+
+import java.util.List;
+
+import org.apache.karaf.shell.api.action.Argument;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.eclipse.equinox.region.RegionDigraph;
+
+@Command(scope = "region", name = "region-add", description = "Adds a list of regions to the region digraph service.")
+@Service
+public class AddRegionCommand extends RegionCommandSupport {
+
+    @Argument(index = 0, name = "name", description = "Regions to add to the region digraph service separated by whitespaces.", required = true, multiValued = true)
+    List<String> regions;
+
+    protected void doExecute(RegionDigraph regionDigraph) throws Exception {
+        for (String region : regions) {
+            regionDigraph.createRegion(region);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/1bcdb173/region/src/main/java/org/apache/karaf/region/commands/InfoCommand.java
----------------------------------------------------------------------
diff --git a/region/src/main/java/org/apache/karaf/region/commands/InfoCommand.java b/region/src/main/java/org/apache/karaf/region/commands/InfoCommand.java
new file mode 100644
index 0000000..7c71e36
--- /dev/null
+++ b/region/src/main/java/org/apache/karaf/region/commands/InfoCommand.java
@@ -0,0 +1,117 @@
+/*
+ * 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.karaf.region.commands;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.karaf.shell.api.action.Argument;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.Option;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.eclipse.equinox.region.Region;
+import org.eclipse.equinox.region.RegionDigraph;
+import org.eclipse.equinox.region.RegionFilter;
+import org.osgi.framework.Bundle;
+
+@Command(scope = "region", name = "info", description = "Prints information about region digraph.")
+@Service
+public class InfoCommand extends RegionCommandSupport {
+
+    @Option(name = "-v", aliases = "--verbose", required = false, description = "Show all info.")
+    boolean verbose;
+
+    @Option(name = "-b", aliases = "--bundles", required = false, description = "Show bundles in each region.")
+    boolean bundles;
+
+    @Option(name = "-f", aliases = "--filters", required = false, description = "Show filters.")
+    boolean filters;
+
+    @Option(name = "-n", aliases = "--namespaces", required = false, description = "Show namespaces in each filter.")
+    boolean namespaces;
+
+    @Argument(index = 0, name = "regions", description = "Regions to provide detailed info for.", required = false, multiValued = true)
+    List<String> regions;
+
+    protected void doExecute(RegionDigraph regionDigraph) throws Exception {
+        System.out.println("Regions");
+        if (regions == null) {
+            for (Region region : regionDigraph.getRegions()) {
+                showRegion(region);
+            }
+        } else {
+            bundles = true;
+            filters = true;
+            namespaces = true;
+            for (String regionName : regions) {
+                Region region = regionDigraph.getRegion(regionName);
+                if (region == null) {
+                    System.out.println("No region " + regionName);
+                } else {
+                    showRegion(region);
+                }
+            }
+        }
+    }
+
+    private void showRegion(Region region) {
+        System.out.println(region.getName());
+        if (verbose || bundles) {
+            for (Long id : region.getBundleIds()) {
+                Bundle b = bundleContext.getBundle(id);
+                System.out.println("  " + id + "  " + getStateString(b) + b);
+            }
+        }
+        if (verbose || filters || namespaces) {
+            for (RegionDigraph.FilteredRegion f : region.getEdges()) {
+                System.out.println("  filter to " + f.getRegion().getName());
+                if (verbose || namespaces) {
+                    RegionFilter rf = f.getFilter();
+                    for (Map.Entry<String, Collection<String>> policy : rf.getSharingPolicy().entrySet()) {
+                        String namespace = policy.getKey();
+                        System.out.println("  namespace: " + namespace);
+                        for (String e : policy.getValue()) {
+                            System.out.println("    " + e);
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    public String getStateString(Bundle bundle) {
+        if (bundle == null) {
+            return "Bundle null";
+        }
+        int state = bundle.getState();
+        if (state == Bundle.ACTIVE) {
+            return "Active     ";
+        } else if (state == Bundle.INSTALLED) {
+            return "Installed  ";
+        } else if (state == Bundle.RESOLVED) {
+            return "Resolved   ";
+        } else if (state == Bundle.STARTING) {
+            return "Starting   ";
+        } else if (state == Bundle.STOPPING) {
+            return "Stopping   ";
+        } else {
+            return "Unknown    ";
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/1bcdb173/region/src/main/java/org/apache/karaf/region/commands/RegionCommandSupport.java
----------------------------------------------------------------------
diff --git a/region/src/main/java/org/apache/karaf/region/commands/RegionCommandSupport.java b/region/src/main/java/org/apache/karaf/region/commands/RegionCommandSupport.java
new file mode 100644
index 0000000..bcdfb6c
--- /dev/null
+++ b/region/src/main/java/org/apache/karaf/region/commands/RegionCommandSupport.java
@@ -0,0 +1,79 @@
+/*
+ * 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.karaf.region.commands;
+
+import java.io.PrintStream;
+
+import org.apache.karaf.shell.api.action.Action;
+import org.apache.karaf.shell.api.action.lifecycle.Reference;
+import org.eclipse.equinox.region.Region;
+import org.eclipse.equinox.region.RegionDigraph;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleException;
+import org.osgi.framework.ServiceReference;
+
+public abstract class RegionCommandSupport implements Action {
+
+    protected static final char VERSION_DELIM = ',';
+
+    @Reference
+    BundleContext bundleContext;
+
+    @Override
+    public Object execute() throws Exception {
+        // Get repository instance service.
+        ServiceReference ref = bundleContext.getServiceReference(RegionDigraph.class.getName());
+        if (ref == null) {
+            System.out.println("RegionDigraph service is unavailable.");
+            return null;
+        }
+        try {
+            RegionDigraph admin = (RegionDigraph) bundleContext.getService(ref);
+            if (admin == null) {
+                System.out.println("RegionDigraph service is unavailable.");
+                return null;
+            }
+
+            doExecute(admin);
+        }
+        finally {
+            bundleContext.ungetService(ref);
+        }
+        return null;
+    }
+
+    abstract void doExecute(RegionDigraph admin) throws Exception;
+
+    protected void printUnderline(PrintStream out, int length)
+    {
+        for (int i = 0; i < length; i++)
+        {
+            out.print('-');
+        }
+        out.println("");
+    }
+
+
+    protected Region getRegion(RegionDigraph regionDigraph, String region) throws BundleException {
+        Region r = regionDigraph.getRegion(region);
+        if (r == null) {
+            System.out.println("No region: " + region + ", creating it");
+            r = regionDigraph.createRegion(region);
+        }
+        return r;
+    }
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/1bcdb173/region/src/main/java/org/apache/karaf/region/commands/util/FileUtil.java
----------------------------------------------------------------------
diff --git a/region/src/main/java/org/apache/karaf/region/commands/util/FileUtil.java b/region/src/main/java/org/apache/karaf/region/commands/util/FileUtil.java
new file mode 100644
index 0000000..07c39e9
--- /dev/null
+++ b/region/src/main/java/org/apache/karaf/region/commands/util/FileUtil.java
@@ -0,0 +1,177 @@
+/*
+ * 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.karaf.region.commands.util;
+
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.PrintStream;
+import java.net.URL;
+import java.net.URLConnection;
+import java.util.jar.JarEntry;
+import java.util.jar.JarInputStream;
+
+public class FileUtil
+{
+    public static void downloadSource(
+        PrintStream out, PrintStream err,
+        URL srcURL, String dirStr, boolean extract)
+    {
+        // Get the file name from the URL.
+        String fileName = (srcURL.getFile().lastIndexOf('/') > 0)
+            ? srcURL.getFile().substring(srcURL.getFile().lastIndexOf('/') + 1)
+            : srcURL.getFile();
+
+        try
+        {
+            out.println("Connecting...");
+
+            File dir = new File(dirStr);
+            if (!dir.exists())
+            {
+                err.println("Destination directory does not exist.");
+            }
+            File file = new File(dir, fileName);
+
+            OutputStream os = new FileOutputStream(file);
+            URLConnection conn = srcURL.openConnection();
+            int total = conn.getContentLength();
+            InputStream is = conn.getInputStream();
+
+            if (total > 0)
+            {
+                out.println("Downloading " + fileName
+                    + " ( " + total + " bytes ).");
+            }
+            else
+            {
+                out.println("Downloading " + fileName + ".");
+            }
+            byte[] buffer = new byte[4096];
+            int count = 0;
+            for (int len = is.read(buffer); len > 0; len = is.read(buffer))
+            {
+                count += len;
+                os.write(buffer, 0, len);
+            }
+
+            os.close();
+            is.close();
+
+            if (extract)
+            {
+                is = new FileInputStream(file);
+                JarInputStream jis = new JarInputStream(is);
+                out.println("Extracting...");
+                unjar(jis, dir);
+                jis.close();
+                file.delete();
+            }
+        }
+        catch (Exception ex)
+        {
+            err.println(ex);
+        }
+    }
+
+    public static void unjar(JarInputStream jis, File dir)
+        throws IOException
+    {
+        // Reusable buffer.
+        byte[] buffer = new byte[4096];
+
+        // Loop through JAR entries.
+        for (JarEntry je = jis.getNextJarEntry();
+             je != null;
+             je = jis.getNextJarEntry())
+        {
+            if (je.getName().startsWith("/"))
+            {
+                throw new IOException("JAR resource cannot contain absolute paths.");
+            }
+
+            File target = new File(dir, je.getName());
+
+            // Check to see if the JAR entry is a directory.
+            if (je.isDirectory())
+            {
+                if (!target.exists())
+                {
+                    if (!target.mkdirs())
+                    {
+                        throw new IOException("Unable to create target directory: "
+                            + target);
+                    }
+                }
+                // Just continue since directories do not have content to copy.
+                continue;
+            }
+
+            int lastIndex = je.getName().lastIndexOf('/');
+            String name = (lastIndex >= 0) ?
+                je.getName().substring(lastIndex + 1) : je.getName();
+            String destination = (lastIndex >= 0) ?
+                je.getName().substring(0, lastIndex) : "";
+
+            // JAR files use '/', so convert it to platform separator.
+            destination = destination.replace('/', File.separatorChar);
+            copy(jis, dir, name, destination, buffer);
+        }
+    }
+
+    public static void copy(
+        InputStream is, File dir, String destName, String destDir, byte[] buffer)
+        throws IOException
+    {
+        if (destDir == null)
+        {
+            destDir = "";
+        }
+
+        // Make sure the target directory exists and
+        // that is actually a directory.
+        File targetDir = new File(dir, destDir);
+        if (!targetDir.exists())
+        {
+            if (!targetDir.mkdirs())
+            {
+                throw new IOException("Unable to create target directory: "
+                    + targetDir);
+            }
+        }
+        else if (!targetDir.isDirectory())
+        {
+            throw new IOException("Target is not a directory: "
+                + targetDir);
+        }
+
+        BufferedOutputStream bos = new BufferedOutputStream(
+            new FileOutputStream(new File(targetDir, destName)));
+        int count = 0;
+        while ((count = is.read(buffer)) > 0)
+        {
+            bos.write(buffer, 0, count);
+        }
+        bos.close();
+    }
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/1bcdb173/region/src/main/java/org/apache/karaf/region/persist/internal/Activator.java
----------------------------------------------------------------------
diff --git a/region/src/main/java/org/apache/karaf/region/persist/internal/Activator.java b/region/src/main/java/org/apache/karaf/region/persist/internal/Activator.java
new file mode 100644
index 0000000..aa7215f
--- /dev/null
+++ b/region/src/main/java/org/apache/karaf/region/persist/internal/Activator.java
@@ -0,0 +1,91 @@
+/*
+ * 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.karaf.region.persist.internal;
+
+import java.util.concurrent.atomic.AtomicReference;
+
+import org.apache.karaf.features.RegionsPersistence;
+import org.apache.karaf.util.tracker.SingleServiceTracker;
+import org.eclipse.equinox.region.RegionDigraph;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceRegistration;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class Activator implements BundleActivator {
+
+    private static final Logger log = LoggerFactory.getLogger(Activator.class);
+
+    private SingleServiceTracker<RegionDigraph> tracker;
+    private final AtomicReference<RegionsPersistenceImpl> persistence = new AtomicReference<RegionsPersistenceImpl>();
+    private final AtomicReference<RegionsBundleTracker> bundleTracker = new AtomicReference<RegionsBundleTracker>();
+    private ServiceRegistration<RegionsPersistence> reg;
+
+    @Override
+    public void start(final BundleContext bundleContext) throws Exception {
+        tracker = new SingleServiceTracker<RegionDigraph>(bundleContext, RegionDigraph.class, new SingleServiceTracker.SingleServiceListener() {
+            public void serviceFound() {
+                log.debug("Found RegionDigraph service, initializing");
+                RegionDigraph regionDigraph = tracker.getService();
+                Bundle framework = bundleContext.getBundle(0);
+                RegionsPersistenceImpl persistence = null;
+                try {
+                    persistence = new RegionsPersistenceImpl(regionDigraph, framework);
+                    reg = bundleContext.registerService(RegionsPersistence.class, persistence, null);
+
+                    RegionsBundleTracker bundleTracker = new RegionsBundleTracker();
+                    bundleTracker.start(bundleContext, persistence);
+                    Activator.this.bundleTracker.set(bundleTracker);
+                } catch (Exception e) {
+                    log.info("Could not create RegionsPersistenceImpl", e);
+                }
+                Activator.this.persistence.set(persistence);
+            }
+
+            public void serviceLost() {
+                if (reg != null) {
+                    reg.unregister();
+                    reg = null;
+                }
+                Activator.this.persistence.set(null);
+                Activator.this.bundleTracker.set(null);
+            }
+
+            public void serviceReplaced() {
+                //??
+            }
+        });
+        tracker.open();
+    }
+
+    @Override
+    public void stop(BundleContext bundleContext) throws Exception {
+        tracker.close();
+        persistence.set(null);
+        RegionsBundleTracker tracker = bundleTracker.getAndSet(null);
+        if (tracker != null) {
+            tracker.stop();
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/1bcdb173/region/src/main/java/org/apache/karaf/region/persist/internal/RegionsBundleTracker.java
----------------------------------------------------------------------
diff --git a/region/src/main/java/org/apache/karaf/region/persist/internal/RegionsBundleTracker.java b/region/src/main/java/org/apache/karaf/region/persist/internal/RegionsBundleTracker.java
new file mode 100644
index 0000000..7035303
--- /dev/null
+++ b/region/src/main/java/org/apache/karaf/region/persist/internal/RegionsBundleTracker.java
@@ -0,0 +1,77 @@
+/*
+ * 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.karaf.region.persist.internal;
+
+import org.apache.karaf.features.RegionsPersistence;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleEvent;
+import org.osgi.framework.BundleException;
+import org.osgi.util.tracker.BundleTracker;
+import org.osgi.util.tracker.BundleTrackerCustomizer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class RegionsBundleTracker {
+    private static final Logger log = LoggerFactory.getLogger(RegionsBundleTracker.class);
+
+    private BundleTracker bundleTracker;
+    private RegionsPersistence regionsPersistence;
+
+    void start(BundleContext bundleContext, RegionsPersistence regionsPersistence) {
+        this.regionsPersistence = regionsPersistence;
+        int stateMask = Bundle.INSTALLED;
+        bundleTracker = new BundleTracker<Bundle>(bundleContext, stateMask, new BundleTrackerCustomizer<Bundle>() {
+            @Override
+            public Bundle addingBundle(Bundle bundle, BundleEvent bundleEvent) {
+                return RegionsBundleTracker.this.addingBundle(bundle);
+            }
+
+            @Override
+            public void modifiedBundle(Bundle bundle, BundleEvent bundleEvent, Bundle o) {
+            }
+
+            @Override
+            public void removedBundle(Bundle bundle, BundleEvent bundleEvent, Bundle o) {
+            }
+        });
+        bundleTracker.open();
+    }
+
+    private Bundle addingBundle(Bundle bundle) {
+        String region = bundle.getHeaders().get("Region");
+        if (region != null) {
+            try {
+                regionsPersistence.install(bundle, region);
+                log.debug("Installed bundle " + bundle + " in region " + region);
+                return bundle;
+            } catch (BundleException e) {
+                log.info("Could not install bundle " + bundle + " in region " + region, e);
+            }
+        }
+        return null;
+    }
+
+    void stop() {
+        bundleTracker.close();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/1bcdb173/region/src/main/java/org/apache/karaf/region/persist/internal/RegionsPersistenceImpl.java
----------------------------------------------------------------------
diff --git a/region/src/main/java/org/apache/karaf/region/persist/internal/RegionsPersistenceImpl.java b/region/src/main/java/org/apache/karaf/region/persist/internal/RegionsPersistenceImpl.java
new file mode 100644
index 0000000..dcf5d26
--- /dev/null
+++ b/region/src/main/java/org/apache/karaf/region/persist/internal/RegionsPersistenceImpl.java
@@ -0,0 +1,203 @@
+/*
+ * 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.karaf.region.persist.internal;
+
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.Reader;
+import java.io.Writer;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Marshaller;
+import javax.xml.bind.Unmarshaller;
+
+import org.apache.karaf.features.RegionsPersistence;
+import org.apache.karaf.region.persist.internal.model.FilterAttributeType;
+import org.apache.karaf.region.persist.internal.model.FilterBundleType;
+import org.apache.karaf.region.persist.internal.model.FilterNamespaceType;
+import org.apache.karaf.region.persist.internal.model.FilterPackageType;
+import org.apache.karaf.region.persist.internal.model.FilterType;
+import org.apache.karaf.region.persist.internal.model.RegionBundleType;
+import org.apache.karaf.region.persist.internal.model.RegionType;
+import org.apache.karaf.region.persist.internal.model.RegionsType;
+import org.apache.karaf.region.persist.internal.util.ManifestHeaderProcessor;
+import org.eclipse.equinox.region.Region;
+import org.eclipse.equinox.region.RegionDigraph;
+import org.eclipse.equinox.region.RegionFilterBuilder;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleException;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.wiring.BundleCapability;
+import org.osgi.framework.wiring.BundleRevision;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class RegionsPersistenceImpl implements RegionsPersistence {
+
+    private static final Logger log = LoggerFactory.getLogger(RegionsPersistenceImpl.class);
+
+    private JAXBContext jaxbContext;
+    private RegionDigraph regionDigraph;
+    private Region kernel;
+    private Bundle framework;
+
+    public RegionsPersistenceImpl(RegionDigraph regionDigraph, Bundle framework) throws JAXBException, BundleException, IOException, InvalidSyntaxException {
+        log.info("Loading region digraph persistence");
+        this.framework = framework;
+        this.regionDigraph = regionDigraph;
+        kernel = regionDigraph.getRegion(0);
+        jaxbContext = JAXBContext.newInstance(RegionsType.class);
+        load();
+    }
+
+    @Override
+    public void install(Bundle b, String regionName) throws BundleException {
+        Region region = regionDigraph.getRegion(regionName);
+        if (region == null) {
+            region = regionDigraph.createRegion(regionName);
+        }
+        kernel.removeBundle(b);
+        region.addBundle(b);
+    }
+
+    void save(RegionsType regionsType, Writer out) throws JAXBException {
+        Marshaller marshaller = jaxbContext.createMarshaller();
+        marshaller.marshal(regionsType, out);
+    }
+
+    void load() throws IOException, BundleException, JAXBException, InvalidSyntaxException {
+        if (this.regionDigraph.getRegions().size() <= 1) {
+            File etc = new File(System.getProperty("karaf.etc"));
+            File regionsConfig = new File(etc, "regions-config.xml");
+            if (regionsConfig.exists()) {
+                log.info("initializing region digraph from etc/regions-config.xml");
+                Reader in = new FileReader(regionsConfig);
+                try {
+                        load(this.regionDigraph, in);
+                    } finally {
+                        in.close();
+                    }
+            } else {
+                log.info("no regions config file");
+            }
+        }
+
+    }
+
+    void  load(RegionDigraph regionDigraph, Reader in) throws JAXBException, BundleException, InvalidSyntaxException {
+        RegionsType regionsType = load(in);
+        load(regionsType, regionDigraph);
+    }
+
+    RegionsType load(Reader in) throws JAXBException {
+        Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
+        return (RegionsType) unmarshaller.unmarshal(in);
+    }
+
+    void load(RegionsType regionsType, RegionDigraph regionDigraph) throws BundleException, InvalidSyntaxException {
+        BundleContext frameworkContext = framework.getBundleContext();
+        for (RegionType regionType: regionsType.getRegion()) {
+            String name = regionType.getName();
+            log.debug("Creating region: " + name);
+            Region region = regionDigraph.createRegion(name);
+            for (RegionBundleType bundleType: regionType.getBundle()) {
+                if (bundleType.getId() != null) {
+                    region.addBundle(bundleType.getId());
+                } else {
+                    Bundle b = frameworkContext.getBundle(bundleType.getLocation());
+                    region.addBundle(b);
+                }
+            }
+        }
+        for (FilterType filterType: regionsType.getFilter()) {
+            Region from = regionDigraph.getRegion(filterType.getFrom());
+            Region to = regionDigraph.getRegion(filterType.getTo());
+            log.debug("Creating filter between " + from.getName() + " to " + to.getName());
+            RegionFilterBuilder builder = regionDigraph.createRegionFilterBuilder();
+            for (FilterBundleType bundleType: filterType.getBundle()) {
+                String symbolicName = bundleType.getSymbolicName();
+                String version = bundleType.getVersion();
+                if (bundleType.getId() != null) {
+                    Bundle b = frameworkContext.getBundle(bundleType.getId());
+                    symbolicName = b.getSymbolicName();
+                    version = b.getVersion().toString();
+                }
+                String namespace = BundleRevision.BUNDLE_NAMESPACE;
+                List<FilterAttributeType> attributeTypes = bundleType.getAttribute();
+                buildFilter(symbolicName, version, namespace, attributeTypes, builder);
+            }
+            for (FilterPackageType packageType: filterType.getPackage()) {
+                String packageName = packageType.getName();
+                String version = packageType.getVersion();
+                String namespace = BundleRevision.PACKAGE_NAMESPACE;
+                List<FilterAttributeType> attributeTypes = packageType.getAttribute();
+                buildFilter(packageName, version, namespace, attributeTypes, builder);
+            }
+            if (to == kernel) {
+                //add framework exports
+                BundleRevision rev = framework.adapt(BundleRevision.class);
+                List<BundleCapability> caps = rev.getDeclaredCapabilities(BundleRevision.PACKAGE_NAMESPACE);
+                for (BundleCapability cap : caps) {
+                    String filter = ManifestHeaderProcessor.generateFilter(filter(cap.getAttributes()));
+                    builder.allow(BundleRevision.PACKAGE_NAMESPACE, filter);
+                }
+            }
+            //TODO explicit services?
+            for (FilterNamespaceType namespaceType: filterType.getNamespace()) {
+                String namespace = namespaceType.getName();
+                HashMap<String, Object> attributes = new HashMap<String, Object>();
+                for (FilterAttributeType attributeType: namespaceType.getAttribute()) {
+                    attributes.put(attributeType.getName(), attributeType.getValue());
+                }
+                String filter = ManifestHeaderProcessor.generateFilter(attributes);
+                builder.allow(namespace, filter);
+            }
+            regionDigraph.connect(from, builder.build(), to);
+        }
+    }
+
+    private Map<String, Object> filter(Map<String, Object> attributes) {
+        Map<String, Object> result = new HashMap<String, Object>(attributes);
+        result.remove("bundle-version");
+        result.remove("bundle-symbolic-name");
+        return result;
+    }
+
+    private void buildFilter(String packageName, String version, String namespace, List<FilterAttributeType> attributeTypes, RegionFilterBuilder builder) throws InvalidSyntaxException {
+        HashMap<String, Object> attributes = new HashMap<String, Object>();
+        if (namespace != null) {
+            attributes.put(namespace, packageName);
+        }
+        if (version != null) {
+            attributes.put("version", version);
+        }
+        for (FilterAttributeType attributeType: attributeTypes) {
+            attributes.put(attributeType.getName(), attributeType.getValue());
+        }
+        String filter = ManifestHeaderProcessor.generateFilter(attributes);
+        builder.allow(namespace, filter);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/1bcdb173/region/src/main/java/org/apache/karaf/region/persist/internal/model/FilterAttributeType.java
----------------------------------------------------------------------
diff --git a/region/src/main/java/org/apache/karaf/region/persist/internal/model/FilterAttributeType.java b/region/src/main/java/org/apache/karaf/region/persist/internal/model/FilterAttributeType.java
new file mode 100644
index 0000000..857c2b3
--- /dev/null
+++ b/region/src/main/java/org/apache/karaf/region/persist/internal/model/FilterAttributeType.java
@@ -0,0 +1,94 @@
+//
+// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, vhudson-jaxb-ri-2.1-833 
+// See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a> 
+// Any modifications to this file will be lost upon recompilation of the source schema. 
+// Generated on: 2011.10.28 at 03:20:55 PM PDT 
+//
+
+
+package org.apache.karaf.region.persist.internal.model;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlType;
+
+
+/**
+ * <p>Java class for filterAttributeType complex type.
+ * 
+ * <p>The following schema fragment specifies the expected content contained within this class.
+ * 
+ * <pre>
+ * &lt;complexType name="filterAttributeType">
+ *   &lt;complexContent>
+ *     &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       &lt;sequence>
+ *       &lt;/sequence>
+ *       &lt;attribute name="name" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
+ *       &lt;attribute name="value" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
+ *     &lt;/restriction>
+ *   &lt;/complexContent>
+ * &lt;/complexType>
+ * </pre>
+ * 
+ * 
+ */
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "filterAttributeType")
+public class FilterAttributeType {
+
+    @XmlAttribute(required = true)
+    protected String name;
+    @XmlAttribute(required = true)
+    protected String value;
+
+    /**
+     * Gets the value of the name property.
+     * 
+     * @return
+     *     possible object is
+     *     {@link String }
+     *     
+     */
+    public String getName() {
+        return name;
+    }
+
+    /**
+     * Sets the value of the name property.
+     * 
+     * @param value
+     *     allowed object is
+     *     {@link String }
+     *     
+     */
+    public void setName(String value) {
+        this.name = value;
+    }
+
+    /**
+     * Gets the value of the value property.
+     * 
+     * @return
+     *     possible object is
+     *     {@link String }
+     *     
+     */
+    public String getValue() {
+        return value;
+    }
+
+    /**
+     * Sets the value of the value property.
+     * 
+     * @param value
+     *     allowed object is
+     *     {@link String }
+     *     
+     */
+    public void setValue(String value) {
+        this.value = value;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/1bcdb173/region/src/main/java/org/apache/karaf/region/persist/internal/model/FilterBundleType.java
----------------------------------------------------------------------
diff --git a/region/src/main/java/org/apache/karaf/region/persist/internal/model/FilterBundleType.java b/region/src/main/java/org/apache/karaf/region/persist/internal/model/FilterBundleType.java
new file mode 100644
index 0000000..a9a9fbb
--- /dev/null
+++ b/region/src/main/java/org/apache/karaf/region/persist/internal/model/FilterBundleType.java
@@ -0,0 +1,156 @@
+//
+// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, vhudson-jaxb-ri-2.1-833 
+// See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a> 
+// Any modifications to this file will be lost upon recompilation of the source schema. 
+// Generated on: 2011.10.28 at 03:20:55 PM PDT 
+//
+
+
+package org.apache.karaf.region.persist.internal.model;
+
+import java.util.ArrayList;
+import java.util.List;
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlType;
+
+
+/**
+ * <p>Java class for filterBundleType complex type.
+ * 
+ * <p>The following schema fragment specifies the expected content contained within this class.
+ * 
+ * <pre>
+ * &lt;complexType name="filterBundleType">
+ *   &lt;complexContent>
+ *     &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       &lt;sequence>
+ *         &lt;element name="attribute" type="{http://karaf.apache.org/xmlns/region/v1.0.0}filterAttributeType" maxOccurs="unbounded" minOccurs="0"/>
+ *       &lt;/sequence>
+ *       &lt;attribute name="id" type="{http://www.w3.org/2001/XMLSchema}long" />
+ *       &lt;attribute name="symbolic-name" type="{http://www.w3.org/2001/XMLSchema}string" />
+ *       &lt;attribute name="version" type="{http://www.w3.org/2001/XMLSchema}string" />
+ *     &lt;/restriction>
+ *   &lt;/complexContent>
+ * &lt;/complexType>
+ * </pre>
+ * 
+ * 
+ */
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "filterBundleType", propOrder = {
+    "attribute"
+})
+public class FilterBundleType {
+
+    protected List<FilterAttributeType> attribute;
+    @XmlAttribute
+    protected Long id;
+    @XmlAttribute(name = "symbolic-name")
+    protected String symbolicName;
+    @XmlAttribute
+    protected String version;
+
+    /**
+     * Gets the value of the attribute property.
+     * 
+     * <p>
+     * This accessor method returns a reference to the live list,
+     * not a snapshot. Therefore any modification you make to the
+     * returned list will be present inside the JAXB object.
+     * This is why there is not a <CODE>set</CODE> method for the attribute property.
+     * 
+     * <p>
+     * For example, to add a new item, do as follows:
+     * <pre>
+     *    getAttribute().add(newItem);
+     * </pre>
+     * 
+     * 
+     * <p>
+     * Objects of the following type(s) are allowed in the list
+     * {@link FilterAttributeType }
+     * 
+     * 
+     */
+    public List<FilterAttributeType> getAttribute() {
+        if (attribute == null) {
+            attribute = new ArrayList<FilterAttributeType>();
+        }
+        return this.attribute;
+    }
+
+    /**
+     * Gets the value of the id property.
+     * 
+     * @return
+     *     possible object is
+     *     {@link Long }
+     *     
+     */
+    public Long getId() {
+        return id;
+    }
+
+    /**
+     * Sets the value of the id property.
+     * 
+     * @param value
+     *     allowed object is
+     *     {@link Long }
+     *     
+     */
+    public void setId(Long value) {
+        this.id = value;
+    }
+
+    /**
+     * Gets the value of the symbolicName property.
+     * 
+     * @return
+     *     possible object is
+     *     {@link String }
+     *     
+     */
+    public String getSymbolicName() {
+        return symbolicName;
+    }
+
+    /**
+     * Sets the value of the symbolicName property.
+     * 
+     * @param value
+     *     allowed object is
+     *     {@link String }
+     *     
+     */
+    public void setSymbolicName(String value) {
+        this.symbolicName = value;
+    }
+
+    /**
+     * Gets the value of the version property.
+     * 
+     * @return
+     *     possible object is
+     *     {@link String }
+     *     
+     */
+    public String getVersion() {
+        return version;
+    }
+
+    /**
+     * Sets the value of the version property.
+     * 
+     * @param value
+     *     allowed object is
+     *     {@link String }
+     *     
+     */
+    public void setVersion(String value) {
+        this.version = value;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/1bcdb173/region/src/main/java/org/apache/karaf/region/persist/internal/model/FilterNamespaceType.java
----------------------------------------------------------------------
diff --git a/region/src/main/java/org/apache/karaf/region/persist/internal/model/FilterNamespaceType.java b/region/src/main/java/org/apache/karaf/region/persist/internal/model/FilterNamespaceType.java
new file mode 100644
index 0000000..52b937a
--- /dev/null
+++ b/region/src/main/java/org/apache/karaf/region/persist/internal/model/FilterNamespaceType.java
@@ -0,0 +1,102 @@
+//
+// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, vhudson-jaxb-ri-2.1-833 
+// See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a> 
+// Any modifications to this file will be lost upon recompilation of the source schema. 
+// Generated on: 2011.10.28 at 03:20:55 PM PDT 
+//
+
+
+package org.apache.karaf.region.persist.internal.model;
+
+import java.util.ArrayList;
+import java.util.List;
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlType;
+
+
+/**
+ * <p>Java class for filterNamespaceType complex type.
+ * 
+ * <p>The following schema fragment specifies the expected content contained within this class.
+ * 
+ * <pre>
+ * &lt;complexType name="filterNamespaceType">
+ *   &lt;complexContent>
+ *     &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       &lt;sequence>
+ *         &lt;element name="attribute" type="{http://karaf.apache.org/xmlns/region/v1.0.0}filterAttributeType" maxOccurs="unbounded" minOccurs="0"/>
+ *       &lt;/sequence>
+ *       &lt;attribute name="name" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
+ *     &lt;/restriction>
+ *   &lt;/complexContent>
+ * &lt;/complexType>
+ * </pre>
+ * 
+ * 
+ */
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "filterNamespaceType", propOrder = {
+    "attribute"
+})
+public class FilterNamespaceType {
+
+    protected List<FilterAttributeType> attribute;
+    @XmlAttribute(required = true)
+    protected String name;
+
+    /**
+     * Gets the value of the attribute property.
+     * 
+     * <p>
+     * This accessor method returns a reference to the live list,
+     * not a snapshot. Therefore any modification you make to the
+     * returned list will be present inside the JAXB object.
+     * This is why there is not a <CODE>set</CODE> method for the attribute property.
+     * 
+     * <p>
+     * For example, to add a new item, do as follows:
+     * <pre>
+     *    getAttribute().add(newItem);
+     * </pre>
+     * 
+     * 
+     * <p>
+     * Objects of the following type(s) are allowed in the list
+     * {@link FilterAttributeType }
+     * 
+     * 
+     */
+    public List<FilterAttributeType> getAttribute() {
+        if (attribute == null) {
+            attribute = new ArrayList<FilterAttributeType>();
+        }
+        return this.attribute;
+    }
+
+    /**
+     * Gets the value of the name property.
+     * 
+     * @return
+     *     possible object is
+     *     {@link String }
+     *     
+     */
+    public String getName() {
+        return name;
+    }
+
+    /**
+     * Sets the value of the name property.
+     * 
+     * @param value
+     *     allowed object is
+     *     {@link String }
+     *     
+     */
+    public void setName(String value) {
+        this.name = value;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/1bcdb173/region/src/main/java/org/apache/karaf/region/persist/internal/model/FilterPackageType.java
----------------------------------------------------------------------
diff --git a/region/src/main/java/org/apache/karaf/region/persist/internal/model/FilterPackageType.java b/region/src/main/java/org/apache/karaf/region/persist/internal/model/FilterPackageType.java
new file mode 100644
index 0000000..b4216ee
--- /dev/null
+++ b/region/src/main/java/org/apache/karaf/region/persist/internal/model/FilterPackageType.java
@@ -0,0 +1,129 @@
+//
+// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, vhudson-jaxb-ri-2.1-833 
+// See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a> 
+// Any modifications to this file will be lost upon recompilation of the source schema. 
+// Generated on: 2011.10.28 at 03:20:55 PM PDT 
+//
+
+
+package org.apache.karaf.region.persist.internal.model;
+
+import java.util.ArrayList;
+import java.util.List;
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlType;
+
+
+/**
+ * <p>Java class for filterPackageType complex type.
+ * 
+ * <p>The following schema fragment specifies the expected content contained within this class.
+ * 
+ * <pre>
+ * &lt;complexType name="filterPackageType">
+ *   &lt;complexContent>
+ *     &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       &lt;sequence>
+ *         &lt;element name="attribute" type="{http://karaf.apache.org/xmlns/region/v1.0.0}filterAttributeType" maxOccurs="unbounded" minOccurs="0"/>
+ *       &lt;/sequence>
+ *       &lt;attribute name="name" type="{http://www.w3.org/2001/XMLSchema}string" />
+ *       &lt;attribute name="version" type="{http://www.w3.org/2001/XMLSchema}string" />
+ *     &lt;/restriction>
+ *   &lt;/complexContent>
+ * &lt;/complexType>
+ * </pre>
+ * 
+ * 
+ */
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "filterPackageType", propOrder = {
+    "attribute"
+})
+public class FilterPackageType {
+
+    protected List<FilterAttributeType> attribute;
+    @XmlAttribute
+    protected String name;
+    @XmlAttribute
+    protected String version;
+
+    /**
+     * Gets the value of the attribute property.
+     * 
+     * <p>
+     * This accessor method returns a reference to the live list,
+     * not a snapshot. Therefore any modification you make to the
+     * returned list will be present inside the JAXB object.
+     * This is why there is not a <CODE>set</CODE> method for the attribute property.
+     * 
+     * <p>
+     * For example, to add a new item, do as follows:
+     * <pre>
+     *    getAttribute().add(newItem);
+     * </pre>
+     * 
+     * 
+     * <p>
+     * Objects of the following type(s) are allowed in the list
+     * {@link FilterAttributeType }
+     * 
+     * 
+     */
+    public List<FilterAttributeType> getAttribute() {
+        if (attribute == null) {
+            attribute = new ArrayList<FilterAttributeType>();
+        }
+        return this.attribute;
+    }
+
+    /**
+     * Gets the value of the name property.
+     * 
+     * @return
+     *     possible object is
+     *     {@link String }
+     *     
+     */
+    public String getName() {
+        return name;
+    }
+
+    /**
+     * Sets the value of the name property.
+     * 
+     * @param value
+     *     allowed object is
+     *     {@link String }
+     *     
+     */
+    public void setName(String value) {
+        this.name = value;
+    }
+
+    /**
+     * Gets the value of the version property.
+     * 
+     * @return
+     *     possible object is
+     *     {@link String }
+     *     
+     */
+    public String getVersion() {
+        return version;
+    }
+
+    /**
+     * Sets the value of the version property.
+     * 
+     * @param value
+     *     allowed object is
+     *     {@link String }
+     *     
+     */
+    public void setVersion(String value) {
+        this.version = value;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/1bcdb173/region/src/main/java/org/apache/karaf/region/persist/internal/model/FilterType.java
----------------------------------------------------------------------
diff --git a/region/src/main/java/org/apache/karaf/region/persist/internal/model/FilterType.java b/region/src/main/java/org/apache/karaf/region/persist/internal/model/FilterType.java
new file mode 100644
index 0000000..f4d1352
--- /dev/null
+++ b/region/src/main/java/org/apache/karaf/region/persist/internal/model/FilterType.java
@@ -0,0 +1,195 @@
+//
+// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, vhudson-jaxb-ri-2.1-833 
+// See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a> 
+// Any modifications to this file will be lost upon recompilation of the source schema. 
+// Generated on: 2011.10.28 at 03:20:55 PM PDT 
+//
+
+
+package org.apache.karaf.region.persist.internal.model;
+
+import java.util.ArrayList;
+import java.util.List;
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlType;
+
+
+/**
+ * <p>Java class for filterType complex type.
+ * 
+ * <p>The following schema fragment specifies the expected content contained within this class.
+ * 
+ * <pre>
+ * &lt;complexType name="filterType">
+ *   &lt;complexContent>
+ *     &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       &lt;sequence>
+ *         &lt;element name="bundle" type="{http://karaf.apache.org/xmlns/region/v1.0.0}filterBundleType" maxOccurs="unbounded" minOccurs="0"/>
+ *         &lt;element name="package" type="{http://karaf.apache.org/xmlns/region/v1.0.0}filterPackageType" maxOccurs="unbounded" minOccurs="0"/>
+ *         &lt;element name="namespace" type="{http://karaf.apache.org/xmlns/region/v1.0.0}filterNamespaceType" maxOccurs="unbounded" minOccurs="0"/>
+ *       &lt;/sequence>
+ *       &lt;attribute name="from" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
+ *       &lt;attribute name="to" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
+ *     &lt;/restriction>
+ *   &lt;/complexContent>
+ * &lt;/complexType>
+ * </pre>
+ * 
+ * 
+ */
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "filterType", propOrder = {
+    "bundle",
+    "_package",
+    "namespace"
+})
+public class FilterType {
+
+    protected List<FilterBundleType> bundle;
+    @XmlElement(name = "package")
+    protected List<FilterPackageType> _package;
+    protected List<FilterNamespaceType> namespace;
+    @XmlAttribute(required = true)
+    protected String from;
+    @XmlAttribute(required = true)
+    protected String to;
+
+    /**
+     * Gets the value of the bundle property.
+     * 
+     * <p>
+     * This accessor method returns a reference to the live list,
+     * not a snapshot. Therefore any modification you make to the
+     * returned list will be present inside the JAXB object.
+     * This is why there is not a <CODE>set</CODE> method for the bundle property.
+     * 
+     * <p>
+     * For example, to add a new item, do as follows:
+     * <pre>
+     *    getBundle().add(newItem);
+     * </pre>
+     * 
+     * 
+     * <p>
+     * Objects of the following type(s) are allowed in the list
+     * {@link FilterBundleType }
+     * 
+     * 
+     */
+    public List<FilterBundleType> getBundle() {
+        if (bundle == null) {
+            bundle = new ArrayList<FilterBundleType>();
+        }
+        return this.bundle;
+    }
+
+    /**
+     * Gets the value of the package property.
+     * 
+     * <p>
+     * This accessor method returns a reference to the live list,
+     * not a snapshot. Therefore any modification you make to the
+     * returned list will be present inside the JAXB object.
+     * This is why there is not a <CODE>set</CODE> method for the package property.
+     * 
+     * <p>
+     * For example, to add a new item, do as follows:
+     * <pre>
+     *    getPackage().add(newItem);
+     * </pre>
+     * 
+     * 
+     * <p>
+     * Objects of the following type(s) are allowed in the list
+     * {@link FilterPackageType }
+     * 
+     * 
+     */
+    public List<FilterPackageType> getPackage() {
+        if (_package == null) {
+            _package = new ArrayList<FilterPackageType>();
+        }
+        return this._package;
+    }
+
+    /**
+     * Gets the value of the namespace property.
+     * 
+     * <p>
+     * This accessor method returns a reference to the live list,
+     * not a snapshot. Therefore any modification you make to the
+     * returned list will be present inside the JAXB object.
+     * This is why there is not a <CODE>set</CODE> method for the namespace property.
+     * 
+     * <p>
+     * For example, to add a new item, do as follows:
+     * <pre>
+     *    getNamespace().add(newItem);
+     * </pre>
+     * 
+     * 
+     * <p>
+     * Objects of the following type(s) are allowed in the list
+     * {@link FilterNamespaceType }
+     * 
+     * 
+     */
+    public List<FilterNamespaceType> getNamespace() {
+        if (namespace == null) {
+            namespace = new ArrayList<FilterNamespaceType>();
+        }
+        return this.namespace;
+    }
+
+    /**
+     * Gets the value of the from property.
+     * 
+     * @return
+     *     possible object is
+     *     {@link String }
+     *     
+     */
+    public String getFrom() {
+        return from;
+    }
+
+    /**
+     * Sets the value of the from property.
+     * 
+     * @param value
+     *     allowed object is
+     *     {@link String }
+     *     
+     */
+    public void setFrom(String value) {
+        this.from = value;
+    }
+
+    /**
+     * Gets the value of the to property.
+     * 
+     * @return
+     *     possible object is
+     *     {@link String }
+     *     
+     */
+    public String getTo() {
+        return to;
+    }
+
+    /**
+     * Sets the value of the to property.
+     * 
+     * @param value
+     *     allowed object is
+     *     {@link String }
+     *     
+     */
+    public void setTo(String value) {
+        this.to = value;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/1bcdb173/region/src/main/java/org/apache/karaf/region/persist/internal/model/ObjectFactory.java
----------------------------------------------------------------------
diff --git a/region/src/main/java/org/apache/karaf/region/persist/internal/model/ObjectFactory.java b/region/src/main/java/org/apache/karaf/region/persist/internal/model/ObjectFactory.java
new file mode 100644
index 0000000..54f5f3c
--- /dev/null
+++ b/region/src/main/java/org/apache/karaf/region/persist/internal/model/ObjectFactory.java
@@ -0,0 +1,116 @@
+//
+// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, vhudson-jaxb-ri-2.1-833 
+// See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a> 
+// Any modifications to this file will be lost upon recompilation of the source schema. 
+// Generated on: 2011.10.28 at 03:20:55 PM PDT 
+//
+
+
+package org.apache.karaf.region.persist.internal.model;
+
+import javax.xml.bind.JAXBElement;
+import javax.xml.bind.annotation.XmlElementDecl;
+import javax.xml.bind.annotation.XmlRegistry;
+import javax.xml.namespace.QName;
+
+
+/**
+ * This object contains factory methods for each 
+ * Java content interface and Java element interface 
+ * generated in the org.apache.karaf.region.persist.internal.model package. 
+ * <p>An ObjectFactory allows you to programatically 
+ * construct new instances of the Java representation 
+ * for XML content. The Java representation of XML 
+ * content can consist of schema derived interfaces 
+ * and classes representing the binding of schema 
+ * type definitions, element declarations and model 
+ * groups.  Factory methods for each of these are 
+ * provided in this class.
+ * 
+ */
+@XmlRegistry
+public class ObjectFactory {
+
+    private final static QName _Regions_QNAME = new QName("http://karaf.apache.org/xmlns/region/v1.0.0", "regions");
+
+    /**
+     * Create a new ObjectFactory that can be used to create new instances of schema derived classes for package: org.apache.karaf.region.persist.internal.model
+     * 
+     */
+    public ObjectFactory() {
+    }
+
+    /**
+     * Create an instance of {@link FilterNamespaceType }
+     * 
+     */
+    public FilterNamespaceType createFilterNamespaceType() {
+        return new FilterNamespaceType();
+    }
+
+    /**
+     * Create an instance of {@link FilterType }
+     * 
+     */
+    public FilterType createFilterType() {
+        return new FilterType();
+    }
+
+    /**
+     * Create an instance of {@link RegionBundleType }
+     * 
+     */
+    public RegionBundleType createRegionBundleType() {
+        return new RegionBundleType();
+    }
+
+    /**
+     * Create an instance of {@link FilterBundleType }
+     * 
+     */
+    public FilterBundleType createFilterBundleType() {
+        return new FilterBundleType();
+    }
+
+    /**
+     * Create an instance of {@link FilterPackageType }
+     * 
+     */
+    public FilterPackageType createFilterPackageType() {
+        return new FilterPackageType();
+    }
+
+    /**
+     * Create an instance of {@link FilterAttributeType }
+     * 
+     */
+    public FilterAttributeType createFilterAttributeType() {
+        return new FilterAttributeType();
+    }
+
+    /**
+     * Create an instance of {@link RegionType }
+     * 
+     */
+    public RegionType createRegionType() {
+        return new RegionType();
+    }
+
+    /**
+     * Create an instance of {@link RegionsType }
+     * 
+     */
+    public RegionsType createRegionsType() {
+        return new RegionsType();
+    }
+
+    /**
+     * Create an instance of {@link JAXBElement }{@code <}{@link RegionsType }{@code >}}
+     * 
+     */
+    @XmlElementDecl(namespace = "http://karaf.apache.org/xmlns/region/v1.0.0", name = "regions")
+    public JAXBElement<RegionsType> createRegions(RegionsType value) {
+        return new JAXBElement<RegionsType>(_Regions_QNAME, RegionsType.class, null, value);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/1bcdb173/region/src/main/java/org/apache/karaf/region/persist/internal/model/RegionBundleType.java
----------------------------------------------------------------------
diff --git a/region/src/main/java/org/apache/karaf/region/persist/internal/model/RegionBundleType.java b/region/src/main/java/org/apache/karaf/region/persist/internal/model/RegionBundleType.java
new file mode 100644
index 0000000..7ba3585
--- /dev/null
+++ b/region/src/main/java/org/apache/karaf/region/persist/internal/model/RegionBundleType.java
@@ -0,0 +1,94 @@
+//
+// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, vhudson-jaxb-ri-2.1-833 
+// See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a> 
+// Any modifications to this file will be lost upon recompilation of the source schema. 
+// Generated on: 2011.10.28 at 03:20:55 PM PDT 
+//
+
+
+package org.apache.karaf.region.persist.internal.model;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlType;
+
+
+/**
+ * <p>Java class for regionBundleType complex type.
+ * 
+ * <p>The following schema fragment specifies the expected content contained within this class.
+ * 
+ * <pre>
+ * &lt;complexType name="regionBundleType">
+ *   &lt;complexContent>
+ *     &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       &lt;sequence>
+ *       &lt;/sequence>
+ *       &lt;attribute name="id" type="{http://www.w3.org/2001/XMLSchema}long" />
+ *       &lt;attribute name="location" type="{http://www.w3.org/2001/XMLSchema}string" />
+ *     &lt;/restriction>
+ *   &lt;/complexContent>
+ * &lt;/complexType>
+ * </pre>
+ * 
+ * 
+ */
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "regionBundleType")
+public class RegionBundleType {
+
+    @XmlAttribute
+    protected Long id;
+    @XmlAttribute
+    protected String location;
+
+    /**
+     * Gets the value of the id property.
+     * 
+     * @return
+     *     possible object is
+     *     {@link Long }
+     *     
+     */
+    public Long getId() {
+        return id;
+    }
+
+    /**
+     * Sets the value of the id property.
+     * 
+     * @param value
+     *     allowed object is
+     *     {@link Long }
+     *     
+     */
+    public void setId(Long value) {
+        this.id = value;
+    }
+
+    /**
+     * Gets the value of the location property.
+     * 
+     * @return
+     *     possible object is
+     *     {@link String }
+     *     
+     */
+    public String getLocation() {
+        return location;
+    }
+
+    /**
+     * Sets the value of the location property.
+     * 
+     * @param value
+     *     allowed object is
+     *     {@link String }
+     *     
+     */
+    public void setLocation(String value) {
+        this.location = value;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/1bcdb173/region/src/main/java/org/apache/karaf/region/persist/internal/model/RegionType.java
----------------------------------------------------------------------
diff --git a/region/src/main/java/org/apache/karaf/region/persist/internal/model/RegionType.java b/region/src/main/java/org/apache/karaf/region/persist/internal/model/RegionType.java
new file mode 100644
index 0000000..f7a810d
--- /dev/null
+++ b/region/src/main/java/org/apache/karaf/region/persist/internal/model/RegionType.java
@@ -0,0 +1,106 @@
+//
+// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, vhudson-jaxb-ri-2.1-833 
+// See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a> 
+// Any modifications to this file will be lost upon recompilation of the source schema. 
+// Generated on: 2011.10.28 at 03:20:55 PM PDT 
+//
+
+
+package org.apache.karaf.region.persist.internal.model;
+
+import java.util.ArrayList;
+import java.util.List;
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlType;
+
+
+/**
+ * 
+ *                 Regions element
+ *             
+ * 
+ * <p>Java class for regionType complex type.
+ * 
+ * <p>The following schema fragment specifies the expected content contained within this class.
+ * 
+ * <pre>
+ * &lt;complexType name="regionType">
+ *   &lt;complexContent>
+ *     &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       &lt;sequence>
+ *         &lt;element name="bundle" type="{http://karaf.apache.org/xmlns/region/v1.0.0}regionBundleType" maxOccurs="unbounded" minOccurs="0"/>
+ *       &lt;/sequence>
+ *       &lt;attribute name="name" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
+ *     &lt;/restriction>
+ *   &lt;/complexContent>
+ * &lt;/complexType>
+ * </pre>
+ * 
+ * 
+ */
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "regionType", propOrder = {
+    "bundle"
+})
+public class RegionType {
+
+    protected List<RegionBundleType> bundle;
+    @XmlAttribute(required = true)
+    protected String name;
+
+    /**
+     * Gets the value of the bundle property.
+     * 
+     * <p>
+     * This accessor method returns a reference to the live list,
+     * not a snapshot. Therefore any modification you make to the
+     * returned list will be present inside the JAXB object.
+     * This is why there is not a <CODE>set</CODE> method for the bundle property.
+     * 
+     * <p>
+     * For example, to add a new item, do as follows:
+     * <pre>
+     *    getBundle().add(newItem);
+     * </pre>
+     * 
+     * 
+     * <p>
+     * Objects of the following type(s) are allowed in the list
+     * {@link RegionBundleType }
+     * 
+     * 
+     */
+    public List<RegionBundleType> getBundle() {
+        if (bundle == null) {
+            bundle = new ArrayList<RegionBundleType>();
+        }
+        return this.bundle;
+    }
+
+    /**
+     * Gets the value of the name property.
+     * 
+     * @return
+     *     possible object is
+     *     {@link String }
+     *     
+     */
+    public String getName() {
+        return name;
+    }
+
+    /**
+     * Sets the value of the name property.
+     * 
+     * @param value
+     *     allowed object is
+     *     {@link String }
+     *     
+     */
+    public void setName(String value) {
+        this.name = value;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/1bcdb173/region/src/main/java/org/apache/karaf/region/persist/internal/model/RegionsType.java
----------------------------------------------------------------------
diff --git a/region/src/main/java/org/apache/karaf/region/persist/internal/model/RegionsType.java b/region/src/main/java/org/apache/karaf/region/persist/internal/model/RegionsType.java
new file mode 100644
index 0000000..be172e4
--- /dev/null
+++ b/region/src/main/java/org/apache/karaf/region/persist/internal/model/RegionsType.java
@@ -0,0 +1,112 @@
+//
+// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, vhudson-jaxb-ri-2.1-833 
+// See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a> 
+// Any modifications to this file will be lost upon recompilation of the source schema. 
+// Generated on: 2011.10.28 at 03:20:55 PM PDT 
+//
+
+
+package org.apache.karaf.region.persist.internal.model;
+
+import java.util.ArrayList;
+import java.util.List;
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlType;
+
+
+/**
+ * 
+ *                 Regions element
+ *             
+ * 
+ * <p>Java class for regionsType complex type.
+ * 
+ * <p>The following schema fragment specifies the expected content contained within this class.
+ * 
+ * <pre>
+ * &lt;complexType name="regionsType">
+ *   &lt;complexContent>
+ *     &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       &lt;sequence>
+ *         &lt;element name="region" type="{http://karaf.apache.org/xmlns/region/v1.0.0}regionType" maxOccurs="unbounded" minOccurs="0"/>
+ *         &lt;element name="filter" type="{http://karaf.apache.org/xmlns/region/v1.0.0}filterType" maxOccurs="unbounded" minOccurs="0"/>
+ *       &lt;/sequence>
+ *     &lt;/restriction>
+ *   &lt;/complexContent>
+ * &lt;/complexType>
+ * </pre>
+ * 
+ * 
+ */
+@XmlRootElement(name = "regions")
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "regionsType", propOrder = {
+    "region",
+    "filter"
+})
+public class RegionsType {
+
+    protected List<RegionType> region;
+    protected List<FilterType> filter;
+
+    /**
+     * Gets the value of the region property.
+     * 
+     * <p>
+     * This accessor method returns a reference to the live list,
+     * not a snapshot. Therefore any modification you make to the
+     * returned list will be present inside the JAXB object.
+     * This is why there is not a <CODE>set</CODE> method for the region property.
+     * 
+     * <p>
+     * For example, to add a new item, do as follows:
+     * <pre>
+     *    getRegion().add(newItem);
+     * </pre>
+     * 
+     * 
+     * <p>
+     * Objects of the following type(s) are allowed in the list
+     * {@link RegionType }
+     * 
+     * 
+     */
+    public List<RegionType> getRegion() {
+        if (region == null) {
+            region = new ArrayList<RegionType>();
+        }
+        return this.region;
+    }
+
+    /**
+     * Gets the value of the filter property.
+     * 
+     * <p>
+     * This accessor method returns a reference to the live list,
+     * not a snapshot. Therefore any modification you make to the
+     * returned list will be present inside the JAXB object.
+     * This is why there is not a <CODE>set</CODE> method for the filter property.
+     * 
+     * <p>
+     * For example, to add a new item, do as follows:
+     * <pre>
+     *    getFilter().add(newItem);
+     * </pre>
+     * 
+     * 
+     * <p>
+     * Objects of the following type(s) are allowed in the list
+     * {@link FilterType }
+     * 
+     * 
+     */
+    public List<FilterType> getFilter() {
+        if (filter == null) {
+            filter = new ArrayList<FilterType>();
+        }
+        return this.filter;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/1bcdb173/region/src/main/java/org/apache/karaf/region/persist/internal/model/package-info.java
----------------------------------------------------------------------
diff --git a/region/src/main/java/org/apache/karaf/region/persist/internal/model/package-info.java b/region/src/main/java/org/apache/karaf/region/persist/internal/model/package-info.java
new file mode 100644
index 0000000..cae062c
--- /dev/null
+++ b/region/src/main/java/org/apache/karaf/region/persist/internal/model/package-info.java
@@ -0,0 +1,9 @@
+//
+// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, vhudson-jaxb-ri-2.1-833 
+// See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a> 
+// Any modifications to this file will be lost upon recompilation of the source schema. 
+// Generated on: 2011.10.28 at 03:20:55 PM PDT 
+//
+
+@javax.xml.bind.annotation.XmlSchema(namespace = "http://karaf.apache.org/xmlns/region/v1.0.0", elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED)
+package org.apache.karaf.region.persist.internal.model;


[43/59] [abbrv] git commit: [KARAF-2852] Merge http/core and http/command

Posted by gn...@apache.org.
[KARAF-2852] Merge http/core and http/command


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

Branch: refs/heads/master
Commit: d5ce026b7cb83259d0f2515d9fc090b887ce4d3b
Parents: 0a100d76
Author: Guillaume Nodet <gn...@gmail.com>
Authored: Thu Apr 10 09:11:33 2014 +0200
Committer: Guillaume Nodet <gn...@gmail.com>
Committed: Thu Apr 10 16:02:33 2014 +0200

----------------------------------------------------------------------
 .../standard/src/main/feature/feature.xml       |   1 -
 http/NOTICE                                     |  71 ++++++++++++
 http/command/NOTICE                             |  71 ------------
 http/command/pom.xml                            | 114 -------------------
 .../karaf/http/command/ServletListCommand.java  |  62 ----------
 .../src/main/resources/OSGI-INF/bundle.info     |  15 ---
 http/core/NOTICE                                |  71 ------------
 http/core/pom.xml                               | 102 -----------------
 .../org/apache/karaf/http/core/HttpMBean.java   |  35 ------
 .../org/apache/karaf/http/core/ServletInfo.java |  85 --------------
 .../apache/karaf/http/core/ServletService.java  |  25 ----
 .../karaf/http/core/internal/HttpMBeanImpl.java |  72 ------------
 .../http/core/internal/ServletEventHandler.java |  41 -------
 .../http/core/internal/ServletServiceImpl.java  |  68 -----------
 .../http/core/internal/osgi/Activator.java      |  40 -------
 .../src/main/resources/OSGI-INF/bundle.info     |  19 ----
 .../http/core/internal/HttpMBeanImplTest.java   |  37 ------
 http/pom.xml                                    |  92 +++++++++++++--
 .../karaf/http/command/ServletListCommand.java  |  62 ++++++++++
 .../org/apache/karaf/http/core/HttpMBean.java   |  35 ++++++
 .../org/apache/karaf/http/core/ServletInfo.java |  85 ++++++++++++++
 .../apache/karaf/http/core/ServletService.java  |  25 ++++
 .../karaf/http/core/internal/HttpMBeanImpl.java |  72 ++++++++++++
 .../http/core/internal/ServletEventHandler.java |  41 +++++++
 .../http/core/internal/ServletServiceImpl.java  |  68 +++++++++++
 .../http/core/internal/osgi/Activator.java      |  40 +++++++
 http/src/main/resources/OSGI-INF/bundle.info    |  19 ++++
 .../http/core/internal/HttpMBeanImplTest.java   |  37 ++++++
 28 files changed, 639 insertions(+), 866 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/karaf/blob/d5ce026b/assemblies/features/standard/src/main/feature/feature.xml
----------------------------------------------------------------------
diff --git a/assemblies/features/standard/src/main/feature/feature.xml b/assemblies/features/standard/src/main/feature/feature.xml
index fae3b4f..4c2be08 100644
--- a/assemblies/features/standard/src/main/feature/feature.xml
+++ b/assemblies/features/standard/src/main/feature/feature.xml
@@ -170,7 +170,6 @@
     <feature name="http" version="${project.version}" resolver="(obr)" description="Implementation of the OSGI HTTP Service">
         <feature>pax-http</feature>
         <bundle start-level="30">mvn:org.apache.karaf.http/org.apache.karaf.http.core/${project.version}</bundle>
-        <bundle start-level="30">mvn:org.apache.karaf.http/org.apache.karaf.http.command/${project.version}</bundle>
     </feature>
 
     <feature name="http-whiteboard" description="Provide HTTP Whiteboard pattern support" version="${project.version}" resolver="(obr)">

http://git-wip-us.apache.org/repos/asf/karaf/blob/d5ce026b/http/NOTICE
----------------------------------------------------------------------
diff --git a/http/NOTICE b/http/NOTICE
new file mode 100644
index 0000000..b70f1f9
--- /dev/null
+++ b/http/NOTICE
@@ -0,0 +1,71 @@
+Apache Karaf
+Copyright 2010-2014 The Apache Software Foundation
+
+
+I. Included Software
+
+This product includes software developed at
+The Apache Software Foundation (http://www.apache.org/).
+Licensed under the Apache License 2.0.
+
+This product uses software developed at
+The OSGi Alliance (http://www.osgi.org/).
+Copyright (c) OSGi Alliance (2000, 2010).
+Licensed under the Apache License 2.0.
+
+This product includes software developed at
+OW2 (http://www.ow2.org/).
+Licensed under the BSD License.
+
+This product includes software developed at
+OPS4J (http://www.ops4j.org/).
+Licensed under the Apache License 2.0.
+
+This product includes software developed at
+Eclipse Foundation (http://www.eclipse.org/).
+Licensed under the EPL.
+
+This product includes software written by
+Antony Lesuisse.
+Licensed under Public Domain.
+
+
+II. Used Software
+
+This product uses software developed at
+FUSE Source (http://www.fusesource.org/).
+Licensed under the Apache License 2.0.
+
+This product uses software developed at
+AOP Alliance (http://aopalliance.sourceforge.net/).
+Licensed under the Public Domain.
+
+This product uses software developed at
+Tanuki Software (http://www.tanukisoftware.com/).
+Licensed under the Apache License 2.0.
+
+This product uses software developed at
+Jasypt (http://jasypt.sourceforge.net/).
+Licensed under the Apache License 2.0.
+
+This product uses software developed at
+JLine (http://jline.sourceforge.net).
+Licensed under the BSD License.
+
+This product uses software developed at
+SLF4J (http://www.slf4j.org/).
+Licensed under the MIT License.
+
+This product uses software developed at
+SpringSource (http://www.springsource.org/).
+Licensed under the Apache License 2.0.
+
+This product includes software from http://www.json.org.
+Copyright (c) 2002 JSON.org
+
+
+III. License Summary
+- Apache License 2.0
+- BSD License
+- EPL License
+- MIT License

http://git-wip-us.apache.org/repos/asf/karaf/blob/d5ce026b/http/command/NOTICE
----------------------------------------------------------------------
diff --git a/http/command/NOTICE b/http/command/NOTICE
deleted file mode 100644
index b70f1f9..0000000
--- a/http/command/NOTICE
+++ /dev/null
@@ -1,71 +0,0 @@
-Apache Karaf
-Copyright 2010-2014 The Apache Software Foundation
-
-
-I. Included Software
-
-This product includes software developed at
-The Apache Software Foundation (http://www.apache.org/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-The OSGi Alliance (http://www.osgi.org/).
-Copyright (c) OSGi Alliance (2000, 2010).
-Licensed under the Apache License 2.0.
-
-This product includes software developed at
-OW2 (http://www.ow2.org/).
-Licensed under the BSD License.
-
-This product includes software developed at
-OPS4J (http://www.ops4j.org/).
-Licensed under the Apache License 2.0.
-
-This product includes software developed at
-Eclipse Foundation (http://www.eclipse.org/).
-Licensed under the EPL.
-
-This product includes software written by
-Antony Lesuisse.
-Licensed under Public Domain.
-
-
-II. Used Software
-
-This product uses software developed at
-FUSE Source (http://www.fusesource.org/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-AOP Alliance (http://aopalliance.sourceforge.net/).
-Licensed under the Public Domain.
-
-This product uses software developed at
-Tanuki Software (http://www.tanukisoftware.com/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-Jasypt (http://jasypt.sourceforge.net/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-JLine (http://jline.sourceforge.net).
-Licensed under the BSD License.
-
-This product uses software developed at
-SLF4J (http://www.slf4j.org/).
-Licensed under the MIT License.
-
-This product uses software developed at
-SpringSource (http://www.springsource.org/).
-Licensed under the Apache License 2.0.
-
-This product includes software from http://www.json.org.
-Copyright (c) 2002 JSON.org
-
-
-III. License Summary
-- Apache License 2.0
-- BSD License
-- EPL License
-- MIT License

http://git-wip-us.apache.org/repos/asf/karaf/blob/d5ce026b/http/command/pom.xml
----------------------------------------------------------------------
diff --git a/http/command/pom.xml b/http/command/pom.xml
deleted file mode 100644
index 0cee04f..0000000
--- a/http/command/pom.xml
+++ /dev/null
@@ -1,114 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-
-    <!--
-
-        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.
-    -->
-
-	<modelVersion>4.0.0</modelVersion>
-
-	<parent>
-		<groupId>org.apache.karaf.http</groupId>
-		<artifactId>http</artifactId>
-		<version>4.0.0-SNAPSHOT</version>
-        <relativePath>../pom.xml</relativePath>
-	</parent>
-
-	<artifactId>org.apache.karaf.http.command</artifactId>
-	<packaging>bundle</packaging>
-	<name>Apache Karaf :: HTTP :: Commands</name>
-	<description>This bundle provides Karaf shell commands to list details of the http service.</description>
-
-	<properties>
-		<appendedResourcesDirectory>${basedir}/../../etc/appended-resources</appendedResourcesDirectory>
-	</properties>
-
-	<dependencies>
-		<dependency>
-			<groupId>org.apache.karaf.shell</groupId>
-			<artifactId>org.apache.karaf.shell.core</artifactId>
-		</dependency>
-        <dependency>
-            <groupId>org.apache.karaf.http</groupId>
-            <artifactId>org.apache.karaf.http.core</artifactId>
-        </dependency>
-
-		<dependency>
-            <groupId>org.osgi</groupId>
-            <artifactId>org.osgi.core</artifactId>
-			<scope>provided</scope>
-		</dependency>
-		<dependency>
-			<groupId>org.apache.felix</groupId>
-			<artifactId>org.apache.felix.utils</artifactId>
-			<scope>provided</scope>
-		</dependency>
-		<dependency>
-			<groupId>org.ops4j.pax.web</groupId>
-			<artifactId>pax-web-spi</artifactId>
-			<scope>provided</scope>
-		</dependency>
-		<dependency>
-			<groupId>${servlet.spec.groupId}</groupId>
-			<artifactId>${servlet.spec.artifactId}</artifactId>
-			<scope>provided</scope>
-		</dependency>
-		<dependency>
-			<groupId>org.apache.karaf</groupId>
-			<artifactId>org.apache.karaf.util</artifactId>
-			<scope>compile</scope>
-		</dependency>
-	</dependencies>
-
-	<build>
-		<resources>
-			<resource>
-				<directory>${project.basedir}/src/main/resources</directory>
-				<includes>
-					<include>**/*</include>
-				</includes>
-			</resource>
-			<resource>
-				<directory>${project.basedir}/src/main/resources</directory>
-				<filtering>true</filtering>
-				<includes>
-					<include>**/*.info</include>
-				</includes>
-			</resource>
-		</resources>
-		<plugins>
-			<plugin>
-				<groupId>org.apache.felix</groupId>
-				<artifactId>maven-bundle-plugin</artifactId>
-				<configuration>
-					<instructions>
-						<Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
-						<Export-Package>${project.artifactId}*;version=${project.version}</Export-Package>
-						<Private-Package>
-							org.apache.felix.utils.version,
-							org.apache.felix.utils.manifest,
-							org.apache.karaf.util;-split-package:=merge-first
-                        </Private-Package>
-                        <Karaf-Commands>*</Karaf-Commands>
-						<_versionpolicy>${bnd.version.policy}</_versionpolicy>
-					</instructions>
-				</configuration>
-			</plugin>
-		</plugins>
-	</build>
-
-</project>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/karaf/blob/d5ce026b/http/command/src/main/java/org/apache/karaf/http/command/ServletListCommand.java
----------------------------------------------------------------------
diff --git a/http/command/src/main/java/org/apache/karaf/http/command/ServletListCommand.java b/http/command/src/main/java/org/apache/karaf/http/command/ServletListCommand.java
deleted file mode 100644
index 1932499..0000000
--- a/http/command/src/main/java/org/apache/karaf/http/command/ServletListCommand.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/* 
- * 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.karaf.http.command;
-
-import java.util.Arrays;
-
-import org.apache.karaf.http.core.ServletInfo;
-import org.apache.karaf.http.core.ServletService;
-import org.apache.karaf.shell.api.action.Action;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Option;
-import org.apache.karaf.shell.api.action.lifecycle.Reference;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.apache.karaf.shell.support.table.Col;
-import org.apache.karaf.shell.support.table.ShellTable;
-
-@Command(scope = "http", name = "list", description = "Lists details for servlets.")
-@Service
-public class ServletListCommand implements Action {
-
-    @Option(name = "--no-format", description = "Disable table rendered output", required = false, multiValued = false)
-    boolean noFormat;
-
-    @Reference
-    private ServletService servletService;
-    
-    @Override
-    public Object execute() throws Exception {
-        ShellTable table = new ShellTable();
-        table.column(new Col("ID"));
-        table.column(new Col("Servlet"));
-        table.column(new Col("Servlet-Name"));
-        table.column(new Col("State"));
-        table.column(new Col("Alias"));
-        table.column(new Col("Url"));
-
-        for (ServletInfo info : servletService.getServlets()) {
-            table.addRow().addContent(info.getBundle().getBundleId(), info.getClassName(), info.getName(),
-                                      info.getStateString(), info.getAlias(), Arrays.toString(info.getUrls()));
-        }
-        table.print(System.out, !noFormat);
-        return null;
-    }
-
-    public void setServletService(ServletService servletService) {
-        this.servletService = servletService;
-    }
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d5ce026b/http/command/src/main/resources/OSGI-INF/bundle.info
----------------------------------------------------------------------
diff --git a/http/command/src/main/resources/OSGI-INF/bundle.info b/http/command/src/main/resources/OSGI-INF/bundle.info
deleted file mode 100644
index 06c9582..0000000
--- a/http/command/src/main/resources/OSGI-INF/bundle.info
+++ /dev/null
@@ -1,15 +0,0 @@
-h1. Synopsis
-
-${project.name}
-
-${project.description}
-
-Maven URL:
-[mvn:${project.groupId}/${project.artifactId}/${project.version}]
-
-h1. Description
-
-This bundle provides Karaf shell commands to interact with http servlets.
-
-The following commands are available:
-* http:list - Lists details for servlets.

http://git-wip-us.apache.org/repos/asf/karaf/blob/d5ce026b/http/core/NOTICE
----------------------------------------------------------------------
diff --git a/http/core/NOTICE b/http/core/NOTICE
deleted file mode 100644
index b70f1f9..0000000
--- a/http/core/NOTICE
+++ /dev/null
@@ -1,71 +0,0 @@
-Apache Karaf
-Copyright 2010-2014 The Apache Software Foundation
-
-
-I. Included Software
-
-This product includes software developed at
-The Apache Software Foundation (http://www.apache.org/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-The OSGi Alliance (http://www.osgi.org/).
-Copyright (c) OSGi Alliance (2000, 2010).
-Licensed under the Apache License 2.0.
-
-This product includes software developed at
-OW2 (http://www.ow2.org/).
-Licensed under the BSD License.
-
-This product includes software developed at
-OPS4J (http://www.ops4j.org/).
-Licensed under the Apache License 2.0.
-
-This product includes software developed at
-Eclipse Foundation (http://www.eclipse.org/).
-Licensed under the EPL.
-
-This product includes software written by
-Antony Lesuisse.
-Licensed under Public Domain.
-
-
-II. Used Software
-
-This product uses software developed at
-FUSE Source (http://www.fusesource.org/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-AOP Alliance (http://aopalliance.sourceforge.net/).
-Licensed under the Public Domain.
-
-This product uses software developed at
-Tanuki Software (http://www.tanukisoftware.com/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-Jasypt (http://jasypt.sourceforge.net/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-JLine (http://jline.sourceforge.net).
-Licensed under the BSD License.
-
-This product uses software developed at
-SLF4J (http://www.slf4j.org/).
-Licensed under the MIT License.
-
-This product uses software developed at
-SpringSource (http://www.springsource.org/).
-Licensed under the Apache License 2.0.
-
-This product includes software from http://www.json.org.
-Copyright (c) 2002 JSON.org
-
-
-III. License Summary
-- Apache License 2.0
-- BSD License
-- EPL License
-- MIT License

http://git-wip-us.apache.org/repos/asf/karaf/blob/d5ce026b/http/core/pom.xml
----------------------------------------------------------------------
diff --git a/http/core/pom.xml b/http/core/pom.xml
deleted file mode 100644
index e09d764..0000000
--- a/http/core/pom.xml
+++ /dev/null
@@ -1,102 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-
-    <!--
-
-        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.
-    -->
-
-    <modelVersion>4.0.0</modelVersion>
-
-    <parent>
-        <groupId>org.apache.karaf.http</groupId>
-        <artifactId>http</artifactId>
-        <version>4.0.0-SNAPSHOT</version>
-        <relativePath>../pom.xml</relativePath>
-    </parent>
-
-    <artifactId>org.apache.karaf.http.core</artifactId>
-    <packaging>bundle</packaging>
-    <name>Apache Karaf :: HTTP :: Core</name>
-    <description>This bundle provides HTTP core services</description>
-
-    <properties>
-        <appendedResourcesDirectory>${basedir}/../../../etc/appended-resources/</appendedResourcesDirectory>
-    </properties>
-
-    <dependencies>
-        <dependency>
-            <groupId>org.osgi</groupId>
-            <artifactId>org.osgi.core</artifactId>
-            <scope>provided</scope>
-        </dependency>
-		<dependency>
-			<groupId>org.ops4j.pax.web</groupId>
-			<artifactId>pax-web-spi</artifactId>
-			<scope>provided</scope>
-		</dependency>
-		<dependency>
-			<groupId>${servlet.spec.groupId}</groupId>
-			<artifactId>${servlet.spec.artifactId}</artifactId>
-			<scope>provided</scope>
-		</dependency>
-        <dependency>
-            <groupId>org.apache.karaf</groupId>
-            <artifactId>org.apache.karaf.util</artifactId>
-            <scope>provided</scope>
-        </dependency>
-    </dependencies>
-
-    <build>
-        <resources>
-            <resource>
-                <directory>src/main/resources</directory>
-                <includes>
-                    <include>**/*</include>
-                </includes>
-            </resource>
-            <resource>
-                <directory>src/main/resources</directory>
-                <filtering>true</filtering>
-                <includes>
-                    <include>**/*.info</include>
-                </includes>
-            </resource>
-        </resources>
-        <plugins>
-            <plugin>
-                <groupId>org.apache.felix</groupId>
-                <artifactId>maven-bundle-plugin</artifactId>
-                <configuration>
-                    <instructions>
-                        <Export-Package>
-                            org.apache.karaf.http.core
-                        </Export-Package>
-                        <Private-Package>
-                            org.apache.karaf.http.core.internal,
-                            org.apache.karaf.http.core.internal.osgi,
-                            org.apache.karaf.util.tracker
-                        </Private-Package>
-                        <Bundle-Activator>
-                            org.apache.karaf.http.core.internal.osgi.Activator
-                        </Bundle-Activator>
-                    </instructions>
-                </configuration>
-            </plugin>
-        </plugins>
-    </build>
-
-</project>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/karaf/blob/d5ce026b/http/core/src/main/java/org/apache/karaf/http/core/HttpMBean.java
----------------------------------------------------------------------
diff --git a/http/core/src/main/java/org/apache/karaf/http/core/HttpMBean.java b/http/core/src/main/java/org/apache/karaf/http/core/HttpMBean.java
deleted file mode 100644
index bebbd29..0000000
--- a/http/core/src/main/java/org/apache/karaf/http/core/HttpMBean.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * 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.karaf.http.core;
-
-import javax.management.MBeanException;
-import javax.management.openmbean.TabularData;
-
-/**
- * HTTP MBean.
- */
-public interface HttpMBean {
-
-    /**
-     * List details for servlets.
-     *
-     * @return a tabular view of the servlets information.
-     * @throws Exception
-     */
-    TabularData getServlets() throws MBeanException;
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d5ce026b/http/core/src/main/java/org/apache/karaf/http/core/ServletInfo.java
----------------------------------------------------------------------
diff --git a/http/core/src/main/java/org/apache/karaf/http/core/ServletInfo.java b/http/core/src/main/java/org/apache/karaf/http/core/ServletInfo.java
deleted file mode 100644
index 9fc83df..0000000
--- a/http/core/src/main/java/org/apache/karaf/http/core/ServletInfo.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * 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.karaf.http.core;
-
-import org.ops4j.pax.web.service.spi.WebEvent;
-import org.osgi.framework.Bundle;
-
-public class ServletInfo {
-    private String name;
-    private Bundle bundle;
-    private String className;
-    private String alias;
-    private int state;
-    private String[] urls;
-
-    public String getName() {
-        return name;
-    }
-    public void setName(String name) {
-        this.name = name;
-    }
-    public Bundle getBundle() {
-        return bundle;
-    }
-    public void setBundle(Bundle bundle) {
-        this.bundle = bundle;
-    }
-    public String getClassName() {
-        return className;
-    }
-    public void setClassName(String className) {
-        this.className = className;
-    }
-    public int getState() {
-        return state;
-    }
-    public void setState(int state) {
-        this.state = state;
-    }
-    public String getAlias() {
-        return alias;
-    }
-    public void setAlias(String alias) {
-        this.alias = alias;
-    }
-    public String[] getUrls() {
-        return urls;
-    }
-    public void setUrls(String[] urls) {
-        this.urls = urls;
-    }
-    
-    public String getStateString() {
-        switch (state) {
-            case WebEvent.DEPLOYING:
-                return "Deploying  ";
-            case WebEvent.DEPLOYED:
-                return "Deployed   ";
-            case WebEvent.UNDEPLOYING:
-                return "Undeploying";
-            case WebEvent.UNDEPLOYED:
-                return "Undeployed ";
-            case WebEvent.FAILED:
-                return "Failed     ";
-            case WebEvent.WAITING:
-                return "Waiting    ";
-            default:
-                return "Failed     ";
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d5ce026b/http/core/src/main/java/org/apache/karaf/http/core/ServletService.java
----------------------------------------------------------------------
diff --git a/http/core/src/main/java/org/apache/karaf/http/core/ServletService.java b/http/core/src/main/java/org/apache/karaf/http/core/ServletService.java
deleted file mode 100644
index fd9b24a..0000000
--- a/http/core/src/main/java/org/apache/karaf/http/core/ServletService.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * 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.karaf.http.core;
-
-import java.util.List;
-
-public interface ServletService {
-
-    List<ServletInfo> getServlets();
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d5ce026b/http/core/src/main/java/org/apache/karaf/http/core/internal/HttpMBeanImpl.java
----------------------------------------------------------------------
diff --git a/http/core/src/main/java/org/apache/karaf/http/core/internal/HttpMBeanImpl.java b/http/core/src/main/java/org/apache/karaf/http/core/internal/HttpMBeanImpl.java
deleted file mode 100644
index 563af61..0000000
--- a/http/core/src/main/java/org/apache/karaf/http/core/internal/HttpMBeanImpl.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * 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.karaf.http.core.internal;
-
-import java.util.Arrays;
-import java.util.List;
-
-import javax.management.MBeanException;
-import javax.management.NotCompliantMBeanException;
-import javax.management.StandardMBean;
-import javax.management.openmbean.CompositeData;
-import javax.management.openmbean.CompositeDataSupport;
-import javax.management.openmbean.CompositeType;
-import javax.management.openmbean.OpenType;
-import javax.management.openmbean.SimpleType;
-import javax.management.openmbean.TabularData;
-import javax.management.openmbean.TabularDataSupport;
-import javax.management.openmbean.TabularType;
-
-import org.apache.karaf.http.core.HttpMBean;
-import org.apache.karaf.http.core.ServletInfo;
-import org.apache.karaf.http.core.ServletService;
-
-/**
- * Implementation of the HTTP MBean.
- */
-public class HttpMBeanImpl extends StandardMBean implements HttpMBean {
-    private ServletService servletService;
-
-    public HttpMBeanImpl(ServletService servletService) throws NotCompliantMBeanException {
-        super(HttpMBean.class);
-        this.servletService = servletService;
-    }
-
-    public TabularData getServlets() throws MBeanException {
-        try {
-            CompositeType servletType = new CompositeType("Servlet", "HTTP Servlet",
-                new String[]{"Bundle-ID", "Servlet", "Servlet Name", "State", "Alias", "URL"},
-                new String[]{"ID of the bundle that registered the servlet", "Class name of the servlet", "Servlet Name", "Current state of the servlet", "Aliases of the servlet", "URL of the servlet"},
-                new OpenType[]{SimpleType.LONG, SimpleType.STRING, SimpleType.STRING, SimpleType.STRING, SimpleType.STRING, SimpleType.STRING});
-            TabularType tableType = new TabularType("Servlets", "Table of all HTTP servlets", servletType, new String[]{"Bundle-ID", "Servlet Name", "State"});
-            TabularData table = new TabularDataSupport(tableType);
-            List<ServletInfo> servletInfos = servletService.getServlets();
-            for (ServletInfo info : servletInfos) {
-            
-                CompositeData data = new CompositeDataSupport(servletType,
-                        new String[]{"Bundle-ID", "Servlet", "Servlet Name", "State", "Alias", "URL"},
-                        new Object[]{info.getBundle().getBundleId(), info.getClassName(), info.getName(), info.getStateString(), info.getAlias(), Arrays.toString(info.getUrls())});
-                table.put(data);
-            
-            }
-            return table;
-        } catch (Exception e) {
-            throw new MBeanException(null, e.getMessage());
-        }
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d5ce026b/http/core/src/main/java/org/apache/karaf/http/core/internal/ServletEventHandler.java
----------------------------------------------------------------------
diff --git a/http/core/src/main/java/org/apache/karaf/http/core/internal/ServletEventHandler.java b/http/core/src/main/java/org/apache/karaf/http/core/internal/ServletEventHandler.java
deleted file mode 100644
index 2733175..0000000
--- a/http/core/src/main/java/org/apache/karaf/http/core/internal/ServletEventHandler.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/* 
- * 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.karaf.http.core.internal;
-
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.Map;
-
-import org.ops4j.pax.web.service.spi.ServletEvent;
-import org.ops4j.pax.web.service.spi.ServletListener;
-
-public class ServletEventHandler implements ServletListener {
-
-	Map<String, ServletEvent> servletEvents =  new HashMap<String, ServletEvent>();
-	
-	public void servletEvent(ServletEvent event) {
-		servletEvents.put(event.getServletName(), event);
-	}
-
-	/**
-	 * @return the servletEvents
-	 */
-	public Collection<ServletEvent> getServletEvents() {
-		return servletEvents.values();
-	}
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d5ce026b/http/core/src/main/java/org/apache/karaf/http/core/internal/ServletServiceImpl.java
----------------------------------------------------------------------
diff --git a/http/core/src/main/java/org/apache/karaf/http/core/internal/ServletServiceImpl.java b/http/core/src/main/java/org/apache/karaf/http/core/internal/ServletServiceImpl.java
deleted file mode 100644
index 8733ae4..0000000
--- a/http/core/src/main/java/org/apache/karaf/http/core/internal/ServletServiceImpl.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * 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.karaf.http.core.internal;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-
-import javax.servlet.Servlet;
-
-import org.apache.karaf.http.core.ServletInfo;
-import org.apache.karaf.http.core.ServletService;
-import org.ops4j.pax.web.service.spi.ServletEvent;
-
-public class ServletServiceImpl implements ServletService {
-    private ServletEventHandler servletEventHandler;
-
-    public ServletServiceImpl(ServletEventHandler servletEventHandler) {
-        this.servletEventHandler = servletEventHandler;
-    }
-
-    @Override
-    public List<ServletInfo> getServlets() {
-        List<ServletInfo> servletInfos = new ArrayList<ServletInfo>();
-        Collection<ServletEvent> events = servletEventHandler.getServletEvents();
-        for (ServletEvent event : events) {
-            Servlet servlet = event.getServlet();
-            String servletClassName = " ";
-            if (servlet != null) {
-                servletClassName = servlet.getClass().getName();
-                servletClassName = servletClassName.substring(servletClassName.lastIndexOf(".") + 1,
-                                                              servletClassName.length());
-            }
-            String servletName = event.getServletName() != null ? event.getServletName() : " ";
-            if (servletName.contains(".")) {
-                servletName = servletName.substring(servletName.lastIndexOf(".") + 1, servletName.length());
-            }
-
-            String alias = event.getAlias() != null ? event.getAlias() : " ";
-
-            String[] urls = (String[])(event.getUrlParameter() != null ? event.getUrlParameter() : new String[] {""});
-            ServletInfo info = new ServletInfo();
-            info.setBundle(event.getBundle());
-            info.setName(servletName);
-            info.setClassName(servletClassName);
-            info.setState(event.getType());
-            info.setAlias(alias);
-            info.setUrls(urls);
-            servletInfos.add(info);
-        }
-        return servletInfos;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d5ce026b/http/core/src/main/java/org/apache/karaf/http/core/internal/osgi/Activator.java
----------------------------------------------------------------------
diff --git a/http/core/src/main/java/org/apache/karaf/http/core/internal/osgi/Activator.java b/http/core/src/main/java/org/apache/karaf/http/core/internal/osgi/Activator.java
deleted file mode 100644
index a294229..0000000
--- a/http/core/src/main/java/org/apache/karaf/http/core/internal/osgi/Activator.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * 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.karaf.http.core.internal.osgi;
-
-import org.apache.karaf.http.core.ServletService;
-import org.apache.karaf.http.core.internal.HttpMBeanImpl;
-import org.apache.karaf.http.core.internal.ServletEventHandler;
-import org.apache.karaf.http.core.internal.ServletServiceImpl;
-import org.apache.karaf.util.tracker.BaseActivator;
-import org.ops4j.pax.web.service.spi.ServletListener;
-
-public class Activator extends BaseActivator {
-
-    @Override
-    protected void doStart() throws Exception {
-        ServletEventHandler servletEventHandler = new ServletEventHandler();
-        register(ServletListener.class, servletEventHandler);
-
-        ServletServiceImpl servletService = new ServletServiceImpl(servletEventHandler);
-        register(ServletService.class, servletService);
-
-        HttpMBeanImpl httpMBean = new HttpMBeanImpl(servletService);
-        registerMBean(httpMBean, "type=http");
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d5ce026b/http/core/src/main/resources/OSGI-INF/bundle.info
----------------------------------------------------------------------
diff --git a/http/core/src/main/resources/OSGI-INF/bundle.info b/http/core/src/main/resources/OSGI-INF/bundle.info
deleted file mode 100644
index 31222c7..0000000
--- a/http/core/src/main/resources/OSGI-INF/bundle.info
+++ /dev/null
@@ -1,19 +0,0 @@
-h1. Synopsis
-
-${project.name}
-
-${project.description}
-
-Maven URL:
-[mvn:${project.groupId}/${project.artifactId}/${project.version}]
-
-h1. Description
-
-The http mbean management bundle exposes a HTTP MBean that can be used with any JMX client (for instance JConsole).
-
-The HTTP MBean allows quite the same actions that can be performed using http:* commands:
-  * list()
-
-h1. See also
-
-  * Monitoring and Administration using JMX - section of the Karaf User Guide

http://git-wip-us.apache.org/repos/asf/karaf/blob/d5ce026b/http/core/src/test/java/org/apache/karaf/http/core/internal/HttpMBeanImplTest.java
----------------------------------------------------------------------
diff --git a/http/core/src/test/java/org/apache/karaf/http/core/internal/HttpMBeanImplTest.java b/http/core/src/test/java/org/apache/karaf/http/core/internal/HttpMBeanImplTest.java
deleted file mode 100644
index cb2f8fd..0000000
--- a/http/core/src/test/java/org/apache/karaf/http/core/internal/HttpMBeanImplTest.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * 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.karaf.http.core.internal;
-
-import java.lang.management.ManagementFactory;
-
-import javax.management.MBeanServer;
-import javax.management.ObjectName;
-import javax.management.openmbean.TabularData;
-
-import org.junit.Test;
-
-public class HttpMBeanImplTest {
-
-    @Test
-    public void testRegisterMBean() throws Exception {
-        HttpMBeanImpl httpMBean = new HttpMBeanImpl(new ServletServiceImpl(new ServletEventHandler()));
-        MBeanServer mbeanServer = ManagementFactory.getPlatformMBeanServer();
-        mbeanServer.registerMBean(httpMBean, new ObjectName("org.apache.karaf:type=http,name=root"));
-        
-        TabularData data = httpMBean.getServlets();
-    }
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d5ce026b/http/pom.xml
----------------------------------------------------------------------
diff --git a/http/pom.xml b/http/pom.xml
index 0a77680..e162765 100644
--- a/http/pom.xml
+++ b/http/pom.xml
@@ -29,13 +29,89 @@
     </parent>
 
     <groupId>org.apache.karaf.http</groupId>
-    <artifactId>http</artifactId>
-    <packaging>pom</packaging>
-    <name>Apache Karaf :: HTTP</name>
+    <artifactId>org.apache.karaf.http.core</artifactId>
+    <packaging>bundle</packaging>
+    <name>Apache Karaf :: HTTP :: Core</name>
+    <description>This bundle provides HTTP core services</description>
 
-    <modules>
-        <module>core</module>
-        <module>command</module>
-    </modules>
+    <properties>
+        <appendedResourcesDirectory>${basedir}/../../../etc/appended-resources/</appendedResourcesDirectory>
+    </properties>
 
-</project>
+    <dependencies>
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>org.osgi.core</artifactId>
+            <scope>provided</scope>
+        </dependency>
+		<dependency>
+			<groupId>org.ops4j.pax.web</groupId>
+			<artifactId>pax-web-spi</artifactId>
+			<scope>provided</scope>
+		</dependency>
+		<dependency>
+			<groupId>${servlet.spec.groupId}</groupId>
+			<artifactId>${servlet.spec.artifactId}</artifactId>
+			<scope>provided</scope>
+		</dependency>
+        <dependency>
+            <groupId>org.apache.karaf</groupId>
+            <artifactId>org.apache.karaf.util</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.felix</groupId>
+            <artifactId>org.apache.felix.utils</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.karaf.shell</groupId>
+            <artifactId>org.apache.karaf.shell.core</artifactId>
+            <optional>true</optional>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <resources>
+            <resource>
+                <directory>src/main/resources</directory>
+                <includes>
+                    <include>**/*</include>
+                </includes>
+            </resource>
+            <resource>
+                <directory>src/main/resources</directory>
+                <filtering>true</filtering>
+                <includes>
+                    <include>**/*.info</include>
+                </includes>
+            </resource>
+        </resources>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+                <configuration>
+                    <instructions>
+                        <Export-Package>
+                            org.apache.karaf.http.core,
+                        </Export-Package>
+                        <Private-Package>
+                            org.apache.karaf.http.command,
+                            org.apache.karaf.http.core.internal,
+                            org.apache.karaf.http.core.internal.osgi,
+                            org.apache.karaf.util.tracker,
+                            org.apache.felix.utils.version,
+                            org.apache.felix.utils.manifest,
+                        </Private-Package>
+                        <Bundle-Activator>
+                            org.apache.karaf.http.core.internal.osgi.Activator
+                        </Bundle-Activator>
+                        <Karaf-Commands>*</Karaf-Commands>
+                    </instructions>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/karaf/blob/d5ce026b/http/src/main/java/org/apache/karaf/http/command/ServletListCommand.java
----------------------------------------------------------------------
diff --git a/http/src/main/java/org/apache/karaf/http/command/ServletListCommand.java b/http/src/main/java/org/apache/karaf/http/command/ServletListCommand.java
new file mode 100644
index 0000000..1932499
--- /dev/null
+++ b/http/src/main/java/org/apache/karaf/http/command/ServletListCommand.java
@@ -0,0 +1,62 @@
+/* 
+ * 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.karaf.http.command;
+
+import java.util.Arrays;
+
+import org.apache.karaf.http.core.ServletInfo;
+import org.apache.karaf.http.core.ServletService;
+import org.apache.karaf.shell.api.action.Action;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.Option;
+import org.apache.karaf.shell.api.action.lifecycle.Reference;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.apache.karaf.shell.support.table.Col;
+import org.apache.karaf.shell.support.table.ShellTable;
+
+@Command(scope = "http", name = "list", description = "Lists details for servlets.")
+@Service
+public class ServletListCommand implements Action {
+
+    @Option(name = "--no-format", description = "Disable table rendered output", required = false, multiValued = false)
+    boolean noFormat;
+
+    @Reference
+    private ServletService servletService;
+    
+    @Override
+    public Object execute() throws Exception {
+        ShellTable table = new ShellTable();
+        table.column(new Col("ID"));
+        table.column(new Col("Servlet"));
+        table.column(new Col("Servlet-Name"));
+        table.column(new Col("State"));
+        table.column(new Col("Alias"));
+        table.column(new Col("Url"));
+
+        for (ServletInfo info : servletService.getServlets()) {
+            table.addRow().addContent(info.getBundle().getBundleId(), info.getClassName(), info.getName(),
+                                      info.getStateString(), info.getAlias(), Arrays.toString(info.getUrls()));
+        }
+        table.print(System.out, !noFormat);
+        return null;
+    }
+
+    public void setServletService(ServletService servletService) {
+        this.servletService = servletService;
+    }
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d5ce026b/http/src/main/java/org/apache/karaf/http/core/HttpMBean.java
----------------------------------------------------------------------
diff --git a/http/src/main/java/org/apache/karaf/http/core/HttpMBean.java b/http/src/main/java/org/apache/karaf/http/core/HttpMBean.java
new file mode 100644
index 0000000..bebbd29
--- /dev/null
+++ b/http/src/main/java/org/apache/karaf/http/core/HttpMBean.java
@@ -0,0 +1,35 @@
+/*
+ * 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.karaf.http.core;
+
+import javax.management.MBeanException;
+import javax.management.openmbean.TabularData;
+
+/**
+ * HTTP MBean.
+ */
+public interface HttpMBean {
+
+    /**
+     * List details for servlets.
+     *
+     * @return a tabular view of the servlets information.
+     * @throws Exception
+     */
+    TabularData getServlets() throws MBeanException;
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d5ce026b/http/src/main/java/org/apache/karaf/http/core/ServletInfo.java
----------------------------------------------------------------------
diff --git a/http/src/main/java/org/apache/karaf/http/core/ServletInfo.java b/http/src/main/java/org/apache/karaf/http/core/ServletInfo.java
new file mode 100644
index 0000000..9fc83df
--- /dev/null
+++ b/http/src/main/java/org/apache/karaf/http/core/ServletInfo.java
@@ -0,0 +1,85 @@
+/*
+ * 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.karaf.http.core;
+
+import org.ops4j.pax.web.service.spi.WebEvent;
+import org.osgi.framework.Bundle;
+
+public class ServletInfo {
+    private String name;
+    private Bundle bundle;
+    private String className;
+    private String alias;
+    private int state;
+    private String[] urls;
+
+    public String getName() {
+        return name;
+    }
+    public void setName(String name) {
+        this.name = name;
+    }
+    public Bundle getBundle() {
+        return bundle;
+    }
+    public void setBundle(Bundle bundle) {
+        this.bundle = bundle;
+    }
+    public String getClassName() {
+        return className;
+    }
+    public void setClassName(String className) {
+        this.className = className;
+    }
+    public int getState() {
+        return state;
+    }
+    public void setState(int state) {
+        this.state = state;
+    }
+    public String getAlias() {
+        return alias;
+    }
+    public void setAlias(String alias) {
+        this.alias = alias;
+    }
+    public String[] getUrls() {
+        return urls;
+    }
+    public void setUrls(String[] urls) {
+        this.urls = urls;
+    }
+    
+    public String getStateString() {
+        switch (state) {
+            case WebEvent.DEPLOYING:
+                return "Deploying  ";
+            case WebEvent.DEPLOYED:
+                return "Deployed   ";
+            case WebEvent.UNDEPLOYING:
+                return "Undeploying";
+            case WebEvent.UNDEPLOYED:
+                return "Undeployed ";
+            case WebEvent.FAILED:
+                return "Failed     ";
+            case WebEvent.WAITING:
+                return "Waiting    ";
+            default:
+                return "Failed     ";
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d5ce026b/http/src/main/java/org/apache/karaf/http/core/ServletService.java
----------------------------------------------------------------------
diff --git a/http/src/main/java/org/apache/karaf/http/core/ServletService.java b/http/src/main/java/org/apache/karaf/http/core/ServletService.java
new file mode 100644
index 0000000..fd9b24a
--- /dev/null
+++ b/http/src/main/java/org/apache/karaf/http/core/ServletService.java
@@ -0,0 +1,25 @@
+/*
+ * 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.karaf.http.core;
+
+import java.util.List;
+
+public interface ServletService {
+
+    List<ServletInfo> getServlets();
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d5ce026b/http/src/main/java/org/apache/karaf/http/core/internal/HttpMBeanImpl.java
----------------------------------------------------------------------
diff --git a/http/src/main/java/org/apache/karaf/http/core/internal/HttpMBeanImpl.java b/http/src/main/java/org/apache/karaf/http/core/internal/HttpMBeanImpl.java
new file mode 100644
index 0000000..563af61
--- /dev/null
+++ b/http/src/main/java/org/apache/karaf/http/core/internal/HttpMBeanImpl.java
@@ -0,0 +1,72 @@
+/*
+ * 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.karaf.http.core.internal;
+
+import java.util.Arrays;
+import java.util.List;
+
+import javax.management.MBeanException;
+import javax.management.NotCompliantMBeanException;
+import javax.management.StandardMBean;
+import javax.management.openmbean.CompositeData;
+import javax.management.openmbean.CompositeDataSupport;
+import javax.management.openmbean.CompositeType;
+import javax.management.openmbean.OpenType;
+import javax.management.openmbean.SimpleType;
+import javax.management.openmbean.TabularData;
+import javax.management.openmbean.TabularDataSupport;
+import javax.management.openmbean.TabularType;
+
+import org.apache.karaf.http.core.HttpMBean;
+import org.apache.karaf.http.core.ServletInfo;
+import org.apache.karaf.http.core.ServletService;
+
+/**
+ * Implementation of the HTTP MBean.
+ */
+public class HttpMBeanImpl extends StandardMBean implements HttpMBean {
+    private ServletService servletService;
+
+    public HttpMBeanImpl(ServletService servletService) throws NotCompliantMBeanException {
+        super(HttpMBean.class);
+        this.servletService = servletService;
+    }
+
+    public TabularData getServlets() throws MBeanException {
+        try {
+            CompositeType servletType = new CompositeType("Servlet", "HTTP Servlet",
+                new String[]{"Bundle-ID", "Servlet", "Servlet Name", "State", "Alias", "URL"},
+                new String[]{"ID of the bundle that registered the servlet", "Class name of the servlet", "Servlet Name", "Current state of the servlet", "Aliases of the servlet", "URL of the servlet"},
+                new OpenType[]{SimpleType.LONG, SimpleType.STRING, SimpleType.STRING, SimpleType.STRING, SimpleType.STRING, SimpleType.STRING});
+            TabularType tableType = new TabularType("Servlets", "Table of all HTTP servlets", servletType, new String[]{"Bundle-ID", "Servlet Name", "State"});
+            TabularData table = new TabularDataSupport(tableType);
+            List<ServletInfo> servletInfos = servletService.getServlets();
+            for (ServletInfo info : servletInfos) {
+            
+                CompositeData data = new CompositeDataSupport(servletType,
+                        new String[]{"Bundle-ID", "Servlet", "Servlet Name", "State", "Alias", "URL"},
+                        new Object[]{info.getBundle().getBundleId(), info.getClassName(), info.getName(), info.getStateString(), info.getAlias(), Arrays.toString(info.getUrls())});
+                table.put(data);
+            
+            }
+            return table;
+        } catch (Exception e) {
+            throw new MBeanException(null, e.getMessage());
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d5ce026b/http/src/main/java/org/apache/karaf/http/core/internal/ServletEventHandler.java
----------------------------------------------------------------------
diff --git a/http/src/main/java/org/apache/karaf/http/core/internal/ServletEventHandler.java b/http/src/main/java/org/apache/karaf/http/core/internal/ServletEventHandler.java
new file mode 100644
index 0000000..2733175
--- /dev/null
+++ b/http/src/main/java/org/apache/karaf/http/core/internal/ServletEventHandler.java
@@ -0,0 +1,41 @@
+/* 
+ * 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.karaf.http.core.internal;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.ops4j.pax.web.service.spi.ServletEvent;
+import org.ops4j.pax.web.service.spi.ServletListener;
+
+public class ServletEventHandler implements ServletListener {
+
+	Map<String, ServletEvent> servletEvents =  new HashMap<String, ServletEvent>();
+	
+	public void servletEvent(ServletEvent event) {
+		servletEvents.put(event.getServletName(), event);
+	}
+
+	/**
+	 * @return the servletEvents
+	 */
+	public Collection<ServletEvent> getServletEvents() {
+		return servletEvents.values();
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d5ce026b/http/src/main/java/org/apache/karaf/http/core/internal/ServletServiceImpl.java
----------------------------------------------------------------------
diff --git a/http/src/main/java/org/apache/karaf/http/core/internal/ServletServiceImpl.java b/http/src/main/java/org/apache/karaf/http/core/internal/ServletServiceImpl.java
new file mode 100644
index 0000000..8733ae4
--- /dev/null
+++ b/http/src/main/java/org/apache/karaf/http/core/internal/ServletServiceImpl.java
@@ -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.karaf.http.core.internal;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import javax.servlet.Servlet;
+
+import org.apache.karaf.http.core.ServletInfo;
+import org.apache.karaf.http.core.ServletService;
+import org.ops4j.pax.web.service.spi.ServletEvent;
+
+public class ServletServiceImpl implements ServletService {
+    private ServletEventHandler servletEventHandler;
+
+    public ServletServiceImpl(ServletEventHandler servletEventHandler) {
+        this.servletEventHandler = servletEventHandler;
+    }
+
+    @Override
+    public List<ServletInfo> getServlets() {
+        List<ServletInfo> servletInfos = new ArrayList<ServletInfo>();
+        Collection<ServletEvent> events = servletEventHandler.getServletEvents();
+        for (ServletEvent event : events) {
+            Servlet servlet = event.getServlet();
+            String servletClassName = " ";
+            if (servlet != null) {
+                servletClassName = servlet.getClass().getName();
+                servletClassName = servletClassName.substring(servletClassName.lastIndexOf(".") + 1,
+                                                              servletClassName.length());
+            }
+            String servletName = event.getServletName() != null ? event.getServletName() : " ";
+            if (servletName.contains(".")) {
+                servletName = servletName.substring(servletName.lastIndexOf(".") + 1, servletName.length());
+            }
+
+            String alias = event.getAlias() != null ? event.getAlias() : " ";
+
+            String[] urls = (String[])(event.getUrlParameter() != null ? event.getUrlParameter() : new String[] {""});
+            ServletInfo info = new ServletInfo();
+            info.setBundle(event.getBundle());
+            info.setName(servletName);
+            info.setClassName(servletClassName);
+            info.setState(event.getType());
+            info.setAlias(alias);
+            info.setUrls(urls);
+            servletInfos.add(info);
+        }
+        return servletInfos;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d5ce026b/http/src/main/java/org/apache/karaf/http/core/internal/osgi/Activator.java
----------------------------------------------------------------------
diff --git a/http/src/main/java/org/apache/karaf/http/core/internal/osgi/Activator.java b/http/src/main/java/org/apache/karaf/http/core/internal/osgi/Activator.java
new file mode 100644
index 0000000..a294229
--- /dev/null
+++ b/http/src/main/java/org/apache/karaf/http/core/internal/osgi/Activator.java
@@ -0,0 +1,40 @@
+/*
+ * 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.karaf.http.core.internal.osgi;
+
+import org.apache.karaf.http.core.ServletService;
+import org.apache.karaf.http.core.internal.HttpMBeanImpl;
+import org.apache.karaf.http.core.internal.ServletEventHandler;
+import org.apache.karaf.http.core.internal.ServletServiceImpl;
+import org.apache.karaf.util.tracker.BaseActivator;
+import org.ops4j.pax.web.service.spi.ServletListener;
+
+public class Activator extends BaseActivator {
+
+    @Override
+    protected void doStart() throws Exception {
+        ServletEventHandler servletEventHandler = new ServletEventHandler();
+        register(ServletListener.class, servletEventHandler);
+
+        ServletServiceImpl servletService = new ServletServiceImpl(servletEventHandler);
+        register(ServletService.class, servletService);
+
+        HttpMBeanImpl httpMBean = new HttpMBeanImpl(servletService);
+        registerMBean(httpMBean, "type=http");
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d5ce026b/http/src/main/resources/OSGI-INF/bundle.info
----------------------------------------------------------------------
diff --git a/http/src/main/resources/OSGI-INF/bundle.info b/http/src/main/resources/OSGI-INF/bundle.info
new file mode 100644
index 0000000..31222c7
--- /dev/null
+++ b/http/src/main/resources/OSGI-INF/bundle.info
@@ -0,0 +1,19 @@
+h1. Synopsis
+
+${project.name}
+
+${project.description}
+
+Maven URL:
+[mvn:${project.groupId}/${project.artifactId}/${project.version}]
+
+h1. Description
+
+The http mbean management bundle exposes a HTTP MBean that can be used with any JMX client (for instance JConsole).
+
+The HTTP MBean allows quite the same actions that can be performed using http:* commands:
+  * list()
+
+h1. See also
+
+  * Monitoring and Administration using JMX - section of the Karaf User Guide

http://git-wip-us.apache.org/repos/asf/karaf/blob/d5ce026b/http/src/test/java/org/apache/karaf/http/core/internal/HttpMBeanImplTest.java
----------------------------------------------------------------------
diff --git a/http/src/test/java/org/apache/karaf/http/core/internal/HttpMBeanImplTest.java b/http/src/test/java/org/apache/karaf/http/core/internal/HttpMBeanImplTest.java
new file mode 100644
index 0000000..cb2f8fd
--- /dev/null
+++ b/http/src/test/java/org/apache/karaf/http/core/internal/HttpMBeanImplTest.java
@@ -0,0 +1,37 @@
+/*
+ * 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.karaf.http.core.internal;
+
+import java.lang.management.ManagementFactory;
+
+import javax.management.MBeanServer;
+import javax.management.ObjectName;
+import javax.management.openmbean.TabularData;
+
+import org.junit.Test;
+
+public class HttpMBeanImplTest {
+
+    @Test
+    public void testRegisterMBean() throws Exception {
+        HttpMBeanImpl httpMBean = new HttpMBeanImpl(new ServletServiceImpl(new ServletEventHandler()));
+        MBeanServer mbeanServer = ManagementFactory.getPlatformMBeanServer();
+        mbeanServer.registerMBean(httpMBean, new ObjectName("org.apache.karaf:type=http,name=root"));
+        
+        TabularData data = httpMBean.getServlets();
+    }
+}


[55/59] [abbrv] [KARAF-2852] Merge region/core and region/command

Posted by gn...@apache.org.
http://git-wip-us.apache.org/repos/asf/karaf/blob/1bcdb173/region/core/src/main/java/org/apache/karaf/region/persist/internal/model/FilterType.java
----------------------------------------------------------------------
diff --git a/region/core/src/main/java/org/apache/karaf/region/persist/internal/model/FilterType.java b/region/core/src/main/java/org/apache/karaf/region/persist/internal/model/FilterType.java
deleted file mode 100644
index f4d1352..0000000
--- a/region/core/src/main/java/org/apache/karaf/region/persist/internal/model/FilterType.java
+++ /dev/null
@@ -1,195 +0,0 @@
-//
-// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, vhudson-jaxb-ri-2.1-833 
-// See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a> 
-// Any modifications to this file will be lost upon recompilation of the source schema. 
-// Generated on: 2011.10.28 at 03:20:55 PM PDT 
-//
-
-
-package org.apache.karaf.region.persist.internal.model;
-
-import java.util.ArrayList;
-import java.util.List;
-import javax.xml.bind.annotation.XmlAccessType;
-import javax.xml.bind.annotation.XmlAccessorType;
-import javax.xml.bind.annotation.XmlAttribute;
-import javax.xml.bind.annotation.XmlElement;
-import javax.xml.bind.annotation.XmlType;
-
-
-/**
- * <p>Java class for filterType complex type.
- * 
- * <p>The following schema fragment specifies the expected content contained within this class.
- * 
- * <pre>
- * &lt;complexType name="filterType">
- *   &lt;complexContent>
- *     &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
- *       &lt;sequence>
- *         &lt;element name="bundle" type="{http://karaf.apache.org/xmlns/region/v1.0.0}filterBundleType" maxOccurs="unbounded" minOccurs="0"/>
- *         &lt;element name="package" type="{http://karaf.apache.org/xmlns/region/v1.0.0}filterPackageType" maxOccurs="unbounded" minOccurs="0"/>
- *         &lt;element name="namespace" type="{http://karaf.apache.org/xmlns/region/v1.0.0}filterNamespaceType" maxOccurs="unbounded" minOccurs="0"/>
- *       &lt;/sequence>
- *       &lt;attribute name="from" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
- *       &lt;attribute name="to" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
- *     &lt;/restriction>
- *   &lt;/complexContent>
- * &lt;/complexType>
- * </pre>
- * 
- * 
- */
-@XmlAccessorType(XmlAccessType.FIELD)
-@XmlType(name = "filterType", propOrder = {
-    "bundle",
-    "_package",
-    "namespace"
-})
-public class FilterType {
-
-    protected List<FilterBundleType> bundle;
-    @XmlElement(name = "package")
-    protected List<FilterPackageType> _package;
-    protected List<FilterNamespaceType> namespace;
-    @XmlAttribute(required = true)
-    protected String from;
-    @XmlAttribute(required = true)
-    protected String to;
-
-    /**
-     * Gets the value of the bundle property.
-     * 
-     * <p>
-     * This accessor method returns a reference to the live list,
-     * not a snapshot. Therefore any modification you make to the
-     * returned list will be present inside the JAXB object.
-     * This is why there is not a <CODE>set</CODE> method for the bundle property.
-     * 
-     * <p>
-     * For example, to add a new item, do as follows:
-     * <pre>
-     *    getBundle().add(newItem);
-     * </pre>
-     * 
-     * 
-     * <p>
-     * Objects of the following type(s) are allowed in the list
-     * {@link FilterBundleType }
-     * 
-     * 
-     */
-    public List<FilterBundleType> getBundle() {
-        if (bundle == null) {
-            bundle = new ArrayList<FilterBundleType>();
-        }
-        return this.bundle;
-    }
-
-    /**
-     * Gets the value of the package property.
-     * 
-     * <p>
-     * This accessor method returns a reference to the live list,
-     * not a snapshot. Therefore any modification you make to the
-     * returned list will be present inside the JAXB object.
-     * This is why there is not a <CODE>set</CODE> method for the package property.
-     * 
-     * <p>
-     * For example, to add a new item, do as follows:
-     * <pre>
-     *    getPackage().add(newItem);
-     * </pre>
-     * 
-     * 
-     * <p>
-     * Objects of the following type(s) are allowed in the list
-     * {@link FilterPackageType }
-     * 
-     * 
-     */
-    public List<FilterPackageType> getPackage() {
-        if (_package == null) {
-            _package = new ArrayList<FilterPackageType>();
-        }
-        return this._package;
-    }
-
-    /**
-     * Gets the value of the namespace property.
-     * 
-     * <p>
-     * This accessor method returns a reference to the live list,
-     * not a snapshot. Therefore any modification you make to the
-     * returned list will be present inside the JAXB object.
-     * This is why there is not a <CODE>set</CODE> method for the namespace property.
-     * 
-     * <p>
-     * For example, to add a new item, do as follows:
-     * <pre>
-     *    getNamespace().add(newItem);
-     * </pre>
-     * 
-     * 
-     * <p>
-     * Objects of the following type(s) are allowed in the list
-     * {@link FilterNamespaceType }
-     * 
-     * 
-     */
-    public List<FilterNamespaceType> getNamespace() {
-        if (namespace == null) {
-            namespace = new ArrayList<FilterNamespaceType>();
-        }
-        return this.namespace;
-    }
-
-    /**
-     * Gets the value of the from property.
-     * 
-     * @return
-     *     possible object is
-     *     {@link String }
-     *     
-     */
-    public String getFrom() {
-        return from;
-    }
-
-    /**
-     * Sets the value of the from property.
-     * 
-     * @param value
-     *     allowed object is
-     *     {@link String }
-     *     
-     */
-    public void setFrom(String value) {
-        this.from = value;
-    }
-
-    /**
-     * Gets the value of the to property.
-     * 
-     * @return
-     *     possible object is
-     *     {@link String }
-     *     
-     */
-    public String getTo() {
-        return to;
-    }
-
-    /**
-     * Sets the value of the to property.
-     * 
-     * @param value
-     *     allowed object is
-     *     {@link String }
-     *     
-     */
-    public void setTo(String value) {
-        this.to = value;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/1bcdb173/region/core/src/main/java/org/apache/karaf/region/persist/internal/model/ObjectFactory.java
----------------------------------------------------------------------
diff --git a/region/core/src/main/java/org/apache/karaf/region/persist/internal/model/ObjectFactory.java b/region/core/src/main/java/org/apache/karaf/region/persist/internal/model/ObjectFactory.java
deleted file mode 100644
index 54f5f3c..0000000
--- a/region/core/src/main/java/org/apache/karaf/region/persist/internal/model/ObjectFactory.java
+++ /dev/null
@@ -1,116 +0,0 @@
-//
-// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, vhudson-jaxb-ri-2.1-833 
-// See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a> 
-// Any modifications to this file will be lost upon recompilation of the source schema. 
-// Generated on: 2011.10.28 at 03:20:55 PM PDT 
-//
-
-
-package org.apache.karaf.region.persist.internal.model;
-
-import javax.xml.bind.JAXBElement;
-import javax.xml.bind.annotation.XmlElementDecl;
-import javax.xml.bind.annotation.XmlRegistry;
-import javax.xml.namespace.QName;
-
-
-/**
- * This object contains factory methods for each 
- * Java content interface and Java element interface 
- * generated in the org.apache.karaf.region.persist.internal.model package. 
- * <p>An ObjectFactory allows you to programatically 
- * construct new instances of the Java representation 
- * for XML content. The Java representation of XML 
- * content can consist of schema derived interfaces 
- * and classes representing the binding of schema 
- * type definitions, element declarations and model 
- * groups.  Factory methods for each of these are 
- * provided in this class.
- * 
- */
-@XmlRegistry
-public class ObjectFactory {
-
-    private final static QName _Regions_QNAME = new QName("http://karaf.apache.org/xmlns/region/v1.0.0", "regions");
-
-    /**
-     * Create a new ObjectFactory that can be used to create new instances of schema derived classes for package: org.apache.karaf.region.persist.internal.model
-     * 
-     */
-    public ObjectFactory() {
-    }
-
-    /**
-     * Create an instance of {@link FilterNamespaceType }
-     * 
-     */
-    public FilterNamespaceType createFilterNamespaceType() {
-        return new FilterNamespaceType();
-    }
-
-    /**
-     * Create an instance of {@link FilterType }
-     * 
-     */
-    public FilterType createFilterType() {
-        return new FilterType();
-    }
-
-    /**
-     * Create an instance of {@link RegionBundleType }
-     * 
-     */
-    public RegionBundleType createRegionBundleType() {
-        return new RegionBundleType();
-    }
-
-    /**
-     * Create an instance of {@link FilterBundleType }
-     * 
-     */
-    public FilterBundleType createFilterBundleType() {
-        return new FilterBundleType();
-    }
-
-    /**
-     * Create an instance of {@link FilterPackageType }
-     * 
-     */
-    public FilterPackageType createFilterPackageType() {
-        return new FilterPackageType();
-    }
-
-    /**
-     * Create an instance of {@link FilterAttributeType }
-     * 
-     */
-    public FilterAttributeType createFilterAttributeType() {
-        return new FilterAttributeType();
-    }
-
-    /**
-     * Create an instance of {@link RegionType }
-     * 
-     */
-    public RegionType createRegionType() {
-        return new RegionType();
-    }
-
-    /**
-     * Create an instance of {@link RegionsType }
-     * 
-     */
-    public RegionsType createRegionsType() {
-        return new RegionsType();
-    }
-
-    /**
-     * Create an instance of {@link JAXBElement }{@code <}{@link RegionsType }{@code >}}
-     * 
-     */
-    @XmlElementDecl(namespace = "http://karaf.apache.org/xmlns/region/v1.0.0", name = "regions")
-    public JAXBElement<RegionsType> createRegions(RegionsType value) {
-        return new JAXBElement<RegionsType>(_Regions_QNAME, RegionsType.class, null, value);
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/1bcdb173/region/core/src/main/java/org/apache/karaf/region/persist/internal/model/RegionBundleType.java
----------------------------------------------------------------------
diff --git a/region/core/src/main/java/org/apache/karaf/region/persist/internal/model/RegionBundleType.java b/region/core/src/main/java/org/apache/karaf/region/persist/internal/model/RegionBundleType.java
deleted file mode 100644
index 7ba3585..0000000
--- a/region/core/src/main/java/org/apache/karaf/region/persist/internal/model/RegionBundleType.java
+++ /dev/null
@@ -1,94 +0,0 @@
-//
-// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, vhudson-jaxb-ri-2.1-833 
-// See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a> 
-// Any modifications to this file will be lost upon recompilation of the source schema. 
-// Generated on: 2011.10.28 at 03:20:55 PM PDT 
-//
-
-
-package org.apache.karaf.region.persist.internal.model;
-
-import javax.xml.bind.annotation.XmlAccessType;
-import javax.xml.bind.annotation.XmlAccessorType;
-import javax.xml.bind.annotation.XmlAttribute;
-import javax.xml.bind.annotation.XmlType;
-
-
-/**
- * <p>Java class for regionBundleType complex type.
- * 
- * <p>The following schema fragment specifies the expected content contained within this class.
- * 
- * <pre>
- * &lt;complexType name="regionBundleType">
- *   &lt;complexContent>
- *     &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
- *       &lt;sequence>
- *       &lt;/sequence>
- *       &lt;attribute name="id" type="{http://www.w3.org/2001/XMLSchema}long" />
- *       &lt;attribute name="location" type="{http://www.w3.org/2001/XMLSchema}string" />
- *     &lt;/restriction>
- *   &lt;/complexContent>
- * &lt;/complexType>
- * </pre>
- * 
- * 
- */
-@XmlAccessorType(XmlAccessType.FIELD)
-@XmlType(name = "regionBundleType")
-public class RegionBundleType {
-
-    @XmlAttribute
-    protected Long id;
-    @XmlAttribute
-    protected String location;
-
-    /**
-     * Gets the value of the id property.
-     * 
-     * @return
-     *     possible object is
-     *     {@link Long }
-     *     
-     */
-    public Long getId() {
-        return id;
-    }
-
-    /**
-     * Sets the value of the id property.
-     * 
-     * @param value
-     *     allowed object is
-     *     {@link Long }
-     *     
-     */
-    public void setId(Long value) {
-        this.id = value;
-    }
-
-    /**
-     * Gets the value of the location property.
-     * 
-     * @return
-     *     possible object is
-     *     {@link String }
-     *     
-     */
-    public String getLocation() {
-        return location;
-    }
-
-    /**
-     * Sets the value of the location property.
-     * 
-     * @param value
-     *     allowed object is
-     *     {@link String }
-     *     
-     */
-    public void setLocation(String value) {
-        this.location = value;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/1bcdb173/region/core/src/main/java/org/apache/karaf/region/persist/internal/model/RegionType.java
----------------------------------------------------------------------
diff --git a/region/core/src/main/java/org/apache/karaf/region/persist/internal/model/RegionType.java b/region/core/src/main/java/org/apache/karaf/region/persist/internal/model/RegionType.java
deleted file mode 100644
index f7a810d..0000000
--- a/region/core/src/main/java/org/apache/karaf/region/persist/internal/model/RegionType.java
+++ /dev/null
@@ -1,106 +0,0 @@
-//
-// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, vhudson-jaxb-ri-2.1-833 
-// See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a> 
-// Any modifications to this file will be lost upon recompilation of the source schema. 
-// Generated on: 2011.10.28 at 03:20:55 PM PDT 
-//
-
-
-package org.apache.karaf.region.persist.internal.model;
-
-import java.util.ArrayList;
-import java.util.List;
-import javax.xml.bind.annotation.XmlAccessType;
-import javax.xml.bind.annotation.XmlAccessorType;
-import javax.xml.bind.annotation.XmlAttribute;
-import javax.xml.bind.annotation.XmlType;
-
-
-/**
- * 
- *                 Regions element
- *             
- * 
- * <p>Java class for regionType complex type.
- * 
- * <p>The following schema fragment specifies the expected content contained within this class.
- * 
- * <pre>
- * &lt;complexType name="regionType">
- *   &lt;complexContent>
- *     &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
- *       &lt;sequence>
- *         &lt;element name="bundle" type="{http://karaf.apache.org/xmlns/region/v1.0.0}regionBundleType" maxOccurs="unbounded" minOccurs="0"/>
- *       &lt;/sequence>
- *       &lt;attribute name="name" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
- *     &lt;/restriction>
- *   &lt;/complexContent>
- * &lt;/complexType>
- * </pre>
- * 
- * 
- */
-@XmlAccessorType(XmlAccessType.FIELD)
-@XmlType(name = "regionType", propOrder = {
-    "bundle"
-})
-public class RegionType {
-
-    protected List<RegionBundleType> bundle;
-    @XmlAttribute(required = true)
-    protected String name;
-
-    /**
-     * Gets the value of the bundle property.
-     * 
-     * <p>
-     * This accessor method returns a reference to the live list,
-     * not a snapshot. Therefore any modification you make to the
-     * returned list will be present inside the JAXB object.
-     * This is why there is not a <CODE>set</CODE> method for the bundle property.
-     * 
-     * <p>
-     * For example, to add a new item, do as follows:
-     * <pre>
-     *    getBundle().add(newItem);
-     * </pre>
-     * 
-     * 
-     * <p>
-     * Objects of the following type(s) are allowed in the list
-     * {@link RegionBundleType }
-     * 
-     * 
-     */
-    public List<RegionBundleType> getBundle() {
-        if (bundle == null) {
-            bundle = new ArrayList<RegionBundleType>();
-        }
-        return this.bundle;
-    }
-
-    /**
-     * Gets the value of the name property.
-     * 
-     * @return
-     *     possible object is
-     *     {@link String }
-     *     
-     */
-    public String getName() {
-        return name;
-    }
-
-    /**
-     * Sets the value of the name property.
-     * 
-     * @param value
-     *     allowed object is
-     *     {@link String }
-     *     
-     */
-    public void setName(String value) {
-        this.name = value;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/1bcdb173/region/core/src/main/java/org/apache/karaf/region/persist/internal/model/RegionsType.java
----------------------------------------------------------------------
diff --git a/region/core/src/main/java/org/apache/karaf/region/persist/internal/model/RegionsType.java b/region/core/src/main/java/org/apache/karaf/region/persist/internal/model/RegionsType.java
deleted file mode 100644
index be172e4..0000000
--- a/region/core/src/main/java/org/apache/karaf/region/persist/internal/model/RegionsType.java
+++ /dev/null
@@ -1,112 +0,0 @@
-//
-// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, vhudson-jaxb-ri-2.1-833 
-// See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a> 
-// Any modifications to this file will be lost upon recompilation of the source schema. 
-// Generated on: 2011.10.28 at 03:20:55 PM PDT 
-//
-
-
-package org.apache.karaf.region.persist.internal.model;
-
-import java.util.ArrayList;
-import java.util.List;
-import javax.xml.bind.annotation.XmlAccessType;
-import javax.xml.bind.annotation.XmlAccessorType;
-import javax.xml.bind.annotation.XmlRootElement;
-import javax.xml.bind.annotation.XmlType;
-
-
-/**
- * 
- *                 Regions element
- *             
- * 
- * <p>Java class for regionsType complex type.
- * 
- * <p>The following schema fragment specifies the expected content contained within this class.
- * 
- * <pre>
- * &lt;complexType name="regionsType">
- *   &lt;complexContent>
- *     &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
- *       &lt;sequence>
- *         &lt;element name="region" type="{http://karaf.apache.org/xmlns/region/v1.0.0}regionType" maxOccurs="unbounded" minOccurs="0"/>
- *         &lt;element name="filter" type="{http://karaf.apache.org/xmlns/region/v1.0.0}filterType" maxOccurs="unbounded" minOccurs="0"/>
- *       &lt;/sequence>
- *     &lt;/restriction>
- *   &lt;/complexContent>
- * &lt;/complexType>
- * </pre>
- * 
- * 
- */
-@XmlRootElement(name = "regions")
-@XmlAccessorType(XmlAccessType.FIELD)
-@XmlType(name = "regionsType", propOrder = {
-    "region",
-    "filter"
-})
-public class RegionsType {
-
-    protected List<RegionType> region;
-    protected List<FilterType> filter;
-
-    /**
-     * Gets the value of the region property.
-     * 
-     * <p>
-     * This accessor method returns a reference to the live list,
-     * not a snapshot. Therefore any modification you make to the
-     * returned list will be present inside the JAXB object.
-     * This is why there is not a <CODE>set</CODE> method for the region property.
-     * 
-     * <p>
-     * For example, to add a new item, do as follows:
-     * <pre>
-     *    getRegion().add(newItem);
-     * </pre>
-     * 
-     * 
-     * <p>
-     * Objects of the following type(s) are allowed in the list
-     * {@link RegionType }
-     * 
-     * 
-     */
-    public List<RegionType> getRegion() {
-        if (region == null) {
-            region = new ArrayList<RegionType>();
-        }
-        return this.region;
-    }
-
-    /**
-     * Gets the value of the filter property.
-     * 
-     * <p>
-     * This accessor method returns a reference to the live list,
-     * not a snapshot. Therefore any modification you make to the
-     * returned list will be present inside the JAXB object.
-     * This is why there is not a <CODE>set</CODE> method for the filter property.
-     * 
-     * <p>
-     * For example, to add a new item, do as follows:
-     * <pre>
-     *    getFilter().add(newItem);
-     * </pre>
-     * 
-     * 
-     * <p>
-     * Objects of the following type(s) are allowed in the list
-     * {@link FilterType }
-     * 
-     * 
-     */
-    public List<FilterType> getFilter() {
-        if (filter == null) {
-            filter = new ArrayList<FilterType>();
-        }
-        return this.filter;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/1bcdb173/region/core/src/main/java/org/apache/karaf/region/persist/internal/model/package-info.java
----------------------------------------------------------------------
diff --git a/region/core/src/main/java/org/apache/karaf/region/persist/internal/model/package-info.java b/region/core/src/main/java/org/apache/karaf/region/persist/internal/model/package-info.java
deleted file mode 100644
index cae062c..0000000
--- a/region/core/src/main/java/org/apache/karaf/region/persist/internal/model/package-info.java
+++ /dev/null
@@ -1,9 +0,0 @@
-//
-// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, vhudson-jaxb-ri-2.1-833 
-// See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a> 
-// Any modifications to this file will be lost upon recompilation of the source schema. 
-// Generated on: 2011.10.28 at 03:20:55 PM PDT 
-//
-
-@javax.xml.bind.annotation.XmlSchema(namespace = "http://karaf.apache.org/xmlns/region/v1.0.0", elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED)
-package org.apache.karaf.region.persist.internal.model;

http://git-wip-us.apache.org/repos/asf/karaf/blob/1bcdb173/region/core/src/main/java/org/apache/karaf/region/persist/internal/util/ManifestHeaderProcessor.java
----------------------------------------------------------------------
diff --git a/region/core/src/main/java/org/apache/karaf/region/persist/internal/util/ManifestHeaderProcessor.java b/region/core/src/main/java/org/apache/karaf/region/persist/internal/util/ManifestHeaderProcessor.java
deleted file mode 100644
index 410121c..0000000
--- a/region/core/src/main/java/org/apache/karaf/region/persist/internal/util/ManifestHeaderProcessor.java
+++ /dev/null
@@ -1,661 +0,0 @@
-/*
- * 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.karaf.region.persist.internal.util;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import org.osgi.framework.Constants;
-
-public class ManifestHeaderProcessor
-{
-  public static final String NESTED_FILTER_ATTRIBUTE = "org.apache.aries.application.filter.attribute";
-  private static final Pattern FILTER_ATTR = Pattern.compile("(\\(!)?\\((.*?)([<>]?=)(.*?)\\)\\)?");
-  private static final String LESS_EQ_OP = "<=";
-  private static final String GREATER_EQ_OP = ">=";
-
-  /**
-   * A simple class to associate two types.
-   *
-   */
-  public static class NameValuePair {
-    private String name;
-    private Map<String,String> attributes;
-
-    public NameValuePair(String name, Map<String,String> value)
-    {
-      this.name = name;
-      this.attributes = value;
-    }
-    public String getName()
-    {
-      return name;
-    }
-    public void setName(String name)
-    {
-      this.name = name;
-    }
-
-    public Map<String,String> getAttributes()
-    {
-      return attributes;
-    }
-    public void setAttributes(Map<String,String> value)
-    {
-      this.attributes = value;
-    }
-
-    @Override
-    public String toString(){
-      return "{"+name.toString()+"::"+attributes.toString()+"}";
-    }
-    @Override
-    public int hashCode()
-    {
-      final int prime = 31;
-      int result = 1;
-      result = prime * result + ((name == null) ? 0 : name.hashCode());
-      result = prime * result + ((attributes == null) ? 0 : attributes.hashCode());
-      return result;
-    }
-    @Override
-    public boolean equals(Object obj)
-    {
-      if (this == obj) return true;
-      if (obj == null) return false;
-      if (getClass() != obj.getClass()) return false;
-      final NameValuePair other = (NameValuePair) obj;
-      if (name == null) {
-        if (other.name != null) return false;
-      } else if (!name.equals(other.name)) return false;
-      if (attributes == null) {
-    	  if (other.attributes != null) return false;
-      } else if (!attributes.equals(other.attributes)) return false;
-      return true;
-    }
-  }
-
-  /**
-   * Intended to provide a standard way to add Name/Value's to
-   * aggregations of Name/Value's.
-   *
-   */
-  public static interface NameValueCollection {
-    /**
-     * Add this Name & Value to the collection.
-     * @param n
-     * @param v
-     */
-    public void addToCollection(String n, Map<String,String> v);
-  }
-
-  /**
-   * Map of Name -> Value.
-   *
-   */
-  public static class NameValueMap extends HashMap<String, Map<String,String>> implements NameValueCollection, Map<String, Map<String,String>>{
-	private static final long serialVersionUID = -6446338858542599141L;
-
-	public void addToCollection(String n, Map<String,String> v){
-      this.put(n,v);
-    }
-
-	@Override
-	public String toString(){
-      StringBuilder sb = new StringBuilder();
-      sb.append("{");
-      boolean first=true;
-      for(Map.Entry<String, Map<String,String>> entry : this.entrySet()){
-        if(!first)sb.append(",");
-        first=false;
-        sb.append(entry.getKey()+"->"+entry.getValue());
-      }
-      sb.append("}");
-      return sb.toString();
-    }
-  }
-
-  /**
-   * List of Name/Value
-   *
-   */
-  public static class NameValueList extends ArrayList<NameValuePair> implements NameValueCollection, List<NameValuePair> {
-	private static final long serialVersionUID = 1808636823825029983L;
-
-	public void addToCollection(String n, Map<String,String> v){
-      this.add(new NameValuePair(n,v));
-    }
-	@Override
-    public String toString(){
-      StringBuffer sb = new StringBuffer();
-      sb.append("{");
-      boolean first = true;
-      for(NameValuePair nvp : this){
-        if(!first)sb.append(",");
-        first=false;
-        sb.append(nvp.toString());
-      }
-      sb.append("}");
-      return sb.toString();
-    }
-  }
-
-  /**
-   *
-   * Splits a delimiter separated string, tolerating presence of non separator commas
-   * within double quoted segments.
-   *
-   * Eg.
-   * com.ibm.ws.eba.helloWorldService;version="[1.0.0, 1.0.0]" &
-   * com.ibm.ws.eba.helloWorldService;version="1.0.0"
-   * com.ibm.ws.eba.helloWorld;version="2";bundle-version="[2,30)"
-   * com.acme.foo;weirdAttr="one;two;three";weirdDir:="1;2;3"
-   *  @param value          the value to be split
-   *  @param delimiter      the delimiter string such as ',' etc.
-   *  @return List<String>  the components of the split String in a list
-   */
-  public static List<String> split(String value, String delimiter)
-  {
-    return ManifestHeaderUtils.split(value, delimiter);
-  }
-
-
-  /**
-   * Internal method to parse headers with the format<p>
-   *   [Name](;[Name])*(;[attribute-name]=[attribute-value])*<br>
-   * Eg.<br>
-   *   rumplestiltskin;thing=value;other=something<br>
-   *   littleredridinghood
-   *   bundle1;bundle2;other=things
-   *   bundle1;bundle2
-   *
-   * @param s data to parse
-   * @return a list of NameValuePair, with the Name being the name component,
-   *         and the Value being a NameValueMap of key->value mappings.
-   */
-  private static List<NameValuePair> genericNameWithNameValuePairProcess(String s){
-    String name;
-    Map<String,String> params = null;
-    List<NameValuePair> nameValues = new ArrayList<NameValuePair>();
-    List<String> pkgs = new ArrayList<String>();
-    int index = s.indexOf(";");
-    if(index==-1){
-      name = s;
-      params = new HashMap<String, String>();
-      pkgs.add(name);
-    }else{
-      name = s.substring(0,index).trim();
-      String tail = s.substring(index+1).trim();
-
-      pkgs.add(name); // add the first package
-      StringBuilder parameters = new StringBuilder();
-
-
-      // take into consideration of multiple packages separated by ';'
-      // while they share the same attributes or directives
-      List<String> tailParts = split(tail, ";");
-      boolean firstParameter =false;
-
-      for (String part : tailParts) {
-        // if it is not a parameter and no parameter appears in front of it, it must a package
-        if (!!!(part.contains("=")))  {
-          // Need to make sure no parameter appears before the package, otherwise ignore this string
-          // as this syntax is invalid
-          if (!!!(firstParameter))
-            pkgs.add(part);
-        } else {
-          if (!!!(firstParameter))
-            firstParameter = true;
-
-          parameters.append(part + ";");
-        }
-      }
-
-      if (parameters.length() != 0) {
-        //remove the final ';' if there is one
-        if (parameters.toString().endsWith(";")) {
-
-          parameters = parameters.deleteCharAt(parameters.length() -1);
-        }
-
-        params = genericNameValueProcess(parameters.toString());
-      }
-
-    }
-    for (String pkg : pkgs) {
-      nameValues.add(new NameValuePair(pkg,params));
-    }
-
-    return nameValues;
-
-  }
-
-  /**
-   * Internal method to parse headers with the format<p>
-   *   [attribute-name]=[attribute-value](;[attribute-name]=[attribute-value])*<br>
-   * Eg.<br>
-   *   thing=value;other=something<br>
-   * <p>
-   * Note. Directives (name:=value) are represented in the map with name suffixed by ':'
-   *
-   * @param s data to parse
-   * @return a NameValueMap, with attribute-name -> attribute-value.
-   */
-  private static Map<String,String> genericNameValueProcess(String s){
-    Map<String,String> params = new HashMap<String,String>();
-    List<String> parameters = split(s, ";");
-    for(String parameter : parameters) {
-      List<String> parts = split(parameter,"=");
-      // do a check, otherwise we might get NPE
-      if (parts.size() ==2) {
-        String second = parts.get(1).trim();
-        if (second.startsWith("\"") && second.endsWith("\""))
-          second = second.substring(1,second.length()-1);
-
-        String first = parts.get(0).trim();
-
-        // make sure for directives we clear out any space as in "directive  :=value"
-        if (first.endsWith(":")) {
-            first = first.substring(0, first.length()-1).trim()+":";
-        }
-
-        params.put(first, second);
-      }
-    }
-
-    return params;
-  }
-
-  /**
-   * Processes an import/export style header.. <p>
-   *  pkg1;attrib=value;attrib=value,pkg2;attrib=value,pkg3;attrib=value
-   *
-   * @param out The collection to add each package name + attrib map to.
-   * @param s The data to parse
-   */
-  private static void genericImportExportProcess(NameValueCollection out, String s){
-    List<String> packages = split(s, ",");
-    for(String pkg : packages){
-      List<NameValuePair> ps = genericNameWithNameValuePairProcess(pkg);
-      for (NameValuePair p : ps) {
-        out.addToCollection(p.getName(), p.getAttributes());
-      }
-    }
-  }
-
-  /**
-   * Parse an export style header.<p>
-   *   pkg1;attrib=value;attrib=value,pkg2;attrib=value,pkg3;attrib=value2
-   * <p>
-   * Result is returned as a list, as export does allow duplicate package exports.
-   *
-   * @param s The data to parse.
-   * @return List of NameValuePairs, where each Name in the list is an exported package,
-   *         with its associated Value being a NameValueMap of any attributes declared.
-   */
-  public static List<NameValuePair> parseExportString(String s){
-    NameValueList retval = new NameValueList();
-    genericImportExportProcess(retval, s);
-    return retval;
-  }
-
-  /**
-   * Parse an export style header in a list.<p>
-   *   pkg1;attrib=value;attrib=value
-   *   pkg2;attrib=value
-   *   pkg3;attrib=value2
-   * <p>
-   * Result is returned as a list, as export does allow duplicate package exports.
-   *
-   * @param list The data to parse.
-   * @return List of NameValuePairs, where each Name in the list is an exported package,
-   *         with its associated Value being a NameValueMap of any attributes declared.
-   */
-  public static List<NameValuePair> parseExportList(List<String> list){
-    NameValueList retval = new NameValueList();
-    for(String pkg : list){
-      List<NameValuePair> ps = genericNameWithNameValuePairProcess(pkg);
-      for (NameValuePair p : ps) {
-        retval.addToCollection(p.getName(), p.getAttributes());
-      }
-    }
-    return retval;
-  }
-
-  /**
-   * Parse an import style header.<p>
-   *   pkg1;attrib=value;attrib=value,pkg2;attrib=value,pkg3;attrib=value
-   * <p>
-   * Result is returned as a set, as import does not allow duplicate package imports.
-   *
-   * @param s The data to parse.
-   * @return Map of NameValuePairs, where each Key in the Map is an imported package,
-   *         with its associated Value being a NameValueMap of any attributes declared.
-   */
-  public static Map<String, Map<String, String>> parseImportString(String s){
-    NameValueMap retval = new NameValueMap();
-    genericImportExportProcess(retval, s);
-    return retval;
-  }
-
-  /**
-   * Parse a bundle symbolic name.<p>
-   *   bundlesymbolicname;attrib=value;attrib=value
-   * <p>
-   *
-   * @param s The data to parse.
-   * @return NameValuePair with Name being the BundleSymbolicName,
-   *         and Value being any attribs declared for the name.
-   */
-  public static NameValuePair parseBundleSymbolicName(String s){
-    return genericNameWithNameValuePairProcess(s).get(0); // should just return the first one
-  }
-
-  /**
-   * Parse a version range..
-   *
-   * @param s
-   * @return VersionRange object.
-   * @throws IllegalArgumentException if the String could not be parsed as a VersionRange
-   */
-  public static VersionRange parseVersionRange(String s) throws IllegalArgumentException{
-    return new VersionRange(s);
-  }
-
-  /**
-   * Parse a version range and indicate if the version is an exact version
-   *
-   * @param s
-   * @param exactVersion
-   * @return VersionRange object.
-   * @throws IllegalArgumentException if the String could not be parsed as a VersionRange
-   */
-  public static VersionRange parseVersionRange(String s, boolean exactVersion) throws IllegalArgumentException{
-    return new VersionRange(s, exactVersion);
-  }
-
-  /**
-	 * Generate a filter from a set of attributes. This filter will be suitable
-	 * for presentation to OBR This means that, due to the way OBR works, it
-	 * will include a stanza of the form, (mandatory:<*mandatoryAttribute)
-	 * Filter strings generated by this method will therefore tend to break the
-	 * standard OSGi Filter class. The OBR stanza can be stripped out later if
-	 * required.
-	 *
-	 * @param attribs
-	 * @return filter string
-	 */
-	public static String generateFilter(Map<String, Object> attribs) {
-		StringBuilder filter = new StringBuilder("(&");
-		boolean realAttrib = false;
-		StringBuffer realAttribs = new StringBuffer();
-
-		if (attribs == null) {
-			attribs = new HashMap<String, Object>();
-		}
-
-		for (Map.Entry<String, Object> attrib : attribs.entrySet()) {
-			String attribName = attrib.getKey();
-
-			if (attribName.endsWith(":")) {
-				// skip all directives. It is used to affect the attribs on the
-				// filter xml.
-			} else if ((Constants.VERSION_ATTRIBUTE.equals(attribName))
-					|| (Constants.BUNDLE_VERSION_ATTRIBUTE.equals(attribName))) {
-				// version and bundle-version attrib requires special
-				// conversion.
-				realAttrib = true;
-
-				VersionRange vr = ManifestHeaderProcessor
-						.parseVersionRange(attrib.getValue().toString());
-
-				filter.append("(" + attribName + ">=" + vr.getMinimumVersion());
-
-				if (vr.getMaximumVersion() != null) {
-					filter.append(")(" + attribName + "<=");
-					filter.append(vr.getMaximumVersion());
-				}
-
-				if (vr.getMaximumVersion() != null && vr.isMinimumExclusive()) {
-					filter.append(")(!(" + attribName + "=");
-					filter.append(vr.getMinimumVersion());
-					filter.append(")");
-				}
-
-				if (vr.getMaximumVersion() != null && vr.isMaximumExclusive()) {
-					filter.append(")(!(" + attribName + "=");
-					filter.append(vr.getMaximumVersion());
-					filter.append(")");
-				}
-				filter.append(")");
-
-			} else if (NESTED_FILTER_ATTRIBUTE.equals(attribName)) {
-				// Filters go in whole, no formatting needed
-				realAttrib = true;
-				filter.append(attrib.getValue());
-
-			} else if (Constants.OBJECTCLASS.equals(attribName)) {
-				realAttrib = true;
-				// objectClass has a "," separated list of interfaces
-				String[] values = attrib.getValue().toString().split(",");
-				for (String s : values)
-					filter.append("(" + Constants.OBJECTCLASS + "=" + s + ")");
-
-			} else {
-				// attribName was not version..
-				realAttrib = true;
-
-				filter.append("(" + attribName + "=" + attrib.getValue() + ")");
-				// store all attributes in order to build up the mandatory
-				// filter and separate them with ", "
-				// skip bundle-symbolic-name in the mandatory directive query
-				if (!!!Constants.BUNDLE_SYMBOLICNAME_ATTRIBUTE
-						.equals(attribName)) {
-					realAttribs.append(attribName);
-					realAttribs.append(", ");
-				}
-			}
-		}
-//		/*
-//		 * The following is how OBR makes mandatory attributes work, we require
-//		 * that the set of mandatory attributes on the export is a subset of (or
-//		 * equal to) the set of the attributes we supply.
-//		 */
-//
-//		if (realAttribs.length() > 0) {
-//			String attribStr = (realAttribs.toString()).trim();
-//			// remove the final ,
-//			if ((attribStr.length() > 0) && (attribStr.endsWith(","))) {
-//				attribStr = attribStr.substring(0, attribStr.length() - 1);
-//			}
-//			// build the mandatory filter, e.g.(mandatory:&lt;*company, local)
-//			filter.append("(" + Constants.MANDATORY_DIRECTIVE + ":" + "<*"
-//					+ attribStr + ")");
-//		}
-
-		// Prune (& off the front and ) off end
-		String filterString = filter.toString();
-		int openBraces = 0;
-		for (int i = 0; openBraces < 3; i++) {
-			i = filterString.indexOf('(', i);
-			if (i == -1) {
-				break;
-			} else {
-				openBraces++;
-			}
-		}
-		if (openBraces < 3 && filterString.length() > 2) {
-			filter.delete(0, 2);
-		} else {
-			filter.append(")");
-		}
-
-		String result = "";
-		if (realAttrib != false) {
-			result = filter.toString();
-		}
-		return result;
-	}
-
-	/**
-   * Generate a filter from a set of attributes. This filter will be suitable
-   * for presentation to OBR. This means that, due to the way OBR works, it will
-   * include a stanza of the form, (mandatory:<*mandatoryAttribute) Filter
-   * strings generated by this method will therefore tend to break the standard
-   * OSGi Filter class. The OBR stanza can be stripped out later if required.
-   *
-   * We may wish to consider relocating this method since VersionRange has its
-   * own top level class.
-   *
-   * @param type
-   * @param name
-   * @param attribs
-   * @return filter string
-   */
-  public static String generateFilter(String type, String name,
-      Map<String, Object> attribs) {
-    StringBuffer filter = new StringBuffer();
-    String result;
-    // shortcut for the simple case with no attribs.
-
-    if (attribs == null || attribs.isEmpty())
-      filter.append("(" + type + "=" + name + ")");
-    else {
-      // process all the attribs passed.
-      // find out whether there are attributes on the filter
-
-      filter.append("(&(" + type + "=" + name + ")");
-
-      String filterString = generateFilter(attribs);
-
-      int start = 0;
-      int end = filterString.length();
-      if (filterString.startsWith("(&")) {
-        start = 2;
-        end--;
-      }
-
-      if ("".equals(filterString)) {
-        filter.delete(0, 2);
-      } else {
-        filter.append(filterString, start, end);
-        filter.append(")");
-      }
-    }
-
-    result = filter.toString();
-
-    return result;
-  }
-
-  private static Map<String, String> parseFilterList(String filter) {
-
-    Map<String, String> result = new HashMap<String, String>();
-    Set<String> negatedVersions = new HashSet<String>();
-    Set<String> negatedBundleVersions = new HashSet<String>();
-
-    String lowerVersion = null;
-    String upperVersion = null;
-    String lowerBundleVersion = null;
-    String upperBundleVersion = null;
-
-    Matcher m = FILTER_ATTR.matcher(filter);
-    while (m.find()) {
-      boolean negation = m.group(1) != null;
-      String attr = m.group(2);
-      String op = m.group(3);
-      String value = m.group(4);
-
-      if (Constants.VERSION_ATTRIBUTE.equals(attr)) {
-        if (negation) {
-          negatedVersions.add(value);
-        } else {
-          if (GREATER_EQ_OP.equals(op))
-            lowerVersion = value;
-          else if (LESS_EQ_OP.equals(op))
-            upperVersion = value;
-          else
-            throw new IllegalArgumentException();
-        }
-      } else if (Constants.BUNDLE_VERSION_ATTRIBUTE.equals(attr)) {
-        // bundle-version is like version, but may be specified at the
-        // same time
-        // therefore we have similar code with separate variables
-        if (negation) {
-          negatedBundleVersions.add(value);
-        } else {
-          if (GREATER_EQ_OP.equals(op))
-            lowerBundleVersion = value;
-          else if (LESS_EQ_OP.equals(op))
-            upperBundleVersion = value;
-          else
-            throw new IllegalArgumentException();
-        }
-      } else {
-        result.put(attr, value);
-      }
-    }
-
-    if (lowerVersion != null) {
-      StringBuilder versionAttr = new StringBuilder(lowerVersion);
-      if (upperVersion != null) {
-        versionAttr.append(",").append(upperVersion).insert(0,
-            negatedVersions.contains(lowerVersion) ? '(' : '[').append(
-            negatedVersions.contains(upperVersion) ? ')' : ']');
-      }
-
-      result.put(Constants.VERSION_ATTRIBUTE, versionAttr.toString());
-    }
-    // Do it again for bundle-version
-    if (lowerBundleVersion != null) {
-      StringBuilder versionAttr = new StringBuilder(lowerBundleVersion);
-      if (upperBundleVersion != null) {
-        versionAttr.append(",").append(upperBundleVersion).insert(0,
-            negatedBundleVersions.contains(lowerBundleVersion) ? '(' : '[')
-            .append(
-                negatedBundleVersions.contains(upperBundleVersion) ? ')' : ']');
-      }
-
-      result.put(Constants.BUNDLE_VERSION_ATTRIBUTE, versionAttr.toString());
-    }
-
-    return result;
-  }
-
-  public static Map<String,String> parseFilter(String filter)
-  {
-    Map<String,String> result;
-    if (filter.startsWith("(&")) {
-      result = parseFilterList(filter.substring(2, filter.length()-1));
-    } else {
-      result = parseFilterList(filter);
-    }
-    return result;
-  }
-
-}
-

http://git-wip-us.apache.org/repos/asf/karaf/blob/1bcdb173/region/core/src/main/java/org/apache/karaf/region/persist/internal/util/ManifestHeaderUtils.java
----------------------------------------------------------------------
diff --git a/region/core/src/main/java/org/apache/karaf/region/persist/internal/util/ManifestHeaderUtils.java b/region/core/src/main/java/org/apache/karaf/region/persist/internal/util/ManifestHeaderUtils.java
deleted file mode 100644
index 8c87616..0000000
--- a/region/core/src/main/java/org/apache/karaf/region/persist/internal/util/ManifestHeaderUtils.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * 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.karaf.region.persist.internal.util;
-
-import java.util.ArrayList;
-import java.util.List;
-
-public class ManifestHeaderUtils {
-
-     /**
-     *
-     * Splits a delimiter separated string, tolerating presence of non separator commas
-     * within double quoted segments.
-     *
-     * Eg.
-     * com.ibm.ws.eba.helloWorldService;version="[1.0.0, 1.0.0]" &
-     * com.ibm.ws.eba.helloWorldService;version="1.0.0"
-     * com.ibm.ws.eba.helloWorld;version="2";bundle-version="[2,30)"
-     * com.acme.foo;weirdAttr="one;two;three";weirdDir:="1;2;3"
-     *  @param value          the value to be split
-     *  @param delimiter      the delimiter string such as ',' etc.
-     *  @return List<String>  the components of the split String in a list
-     */
-    public static List<String> split(String value, String delimiter)
-    {
-      List<String> result = new ArrayList<String>();
-      if (value != null) {
-        String[] packages = value.split(delimiter);
-
-        for (int i = 0; i < packages.length; ) {
-          String tmp = packages[i++].trim();
-          // if there is a odd number of " in a string, we need to append
-          while (count(tmp, "\"") % 2 != 0) {
-            // check to see if we need to append the next package[i++]
-              if (i<packages.length)
-                tmp = tmp + delimiter + packages[i++].trim();
-              else
-                // oops. The double quotes are not paired up. We have reached to the end of the string.
-                throw new IllegalArgumentException("Unmatched double quotes: " + tmp);
-          }
-
-          result.add(tmp);
-
-        }
-      }
-      return result;
-    }
-
-    /**
-     * count the number of characters in a string
-     * @param parent The string to be searched
-     * @param subString The substring to be found
-     * @return the number of occurrence of the subString
-     */
-     private static int count(String parent, String subString) {
-
-       int count = 0 ;
-       int i = parent.indexOf(subString);
-       while (i > -1) {
-         if (parent.length() >= i+1)
-           parent = parent.substring(i+1);
-         count ++;
-         i = parent.indexOf(subString);
-       }
-       return count;
-     }
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/1bcdb173/region/core/src/main/java/org/apache/karaf/region/persist/internal/util/VersionRange.java
----------------------------------------------------------------------
diff --git a/region/core/src/main/java/org/apache/karaf/region/persist/internal/util/VersionRange.java b/region/core/src/main/java/org/apache/karaf/region/persist/internal/util/VersionRange.java
deleted file mode 100644
index 19bbc77..0000000
--- a/region/core/src/main/java/org/apache/karaf/region/persist/internal/util/VersionRange.java
+++ /dev/null
@@ -1,456 +0,0 @@
-/*
- * 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.karaf.region.persist.internal.util;
-
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import org.osgi.framework.Version;
-
-public final class VersionRange {
-
-    /** A string representation of the version. */
-    private String version;
-
-    /** The minimum desired version for the bundle */
-    private Version minimumVersion;
-
-    /** The maximum desired version for the bundle */
-    private Version maximumVersion;
-
-    /** True if the match is exclusive of the minimum version */
-    private boolean minimumExclusive;
-
-    /** True if the match is exclusive of the maximum version */
-    private boolean maximumExclusive;
-
-    /** A regexp to select the version */
-    private static final Pattern versionCapture = Pattern.compile("\"?(.*?)\"?$");
-
-    /**
-     *
-     * @param version
-     *            version for the verioninfo
-     */
-    public VersionRange(String version) {
-        this.version = version;
-        processVersionAttribute(version);
-    }
-
-    /**
-     * This method should be used to create a version range from a single
-     * version string.
-     * @param version
-     *            version for the versioninfo
-     * @param exactVersion
-     *            whether this is an exact version {@code true} or goes to infinity
-     *            {@code false}
-     */
-    public VersionRange(String version, boolean exactVersion) {
-
-        if (exactVersion) {
-            // Do not store this string as it might be just a version, or a range!
-            processExactVersionAttribute(version);
-        } else {
-            this.version = version;
-            processVersionAttribute(this.version);
-        }
-
-        assertInvariants();
-    }
-
-    /**
-     * Constructor designed for internal use only.
-     *
-     * @param maximumVersion
-     * @param maximumExclusive
-     * @param minimumVersion
-     * @param minimumExclusive
-     * @throws IllegalArgumentException
-     *             if parameters are not valid.
-     */
-    private VersionRange(Version maximumVersion,
-                         boolean maximumExclusive,
-                         Version minimumVersion,
-                         boolean minimumExclusive) {
-        this.maximumVersion = maximumVersion;
-        this.maximumExclusive = maximumExclusive;
-        this.minimumVersion = minimumVersion;
-        this.minimumExclusive = minimumExclusive;
-
-        assertInvariants();
-    }
-
-    /*
-     * (non-Javadoc)
-     *
-     * @see org.apache.aries.application.impl.VersionRange#toString()
-     */
-    @Override
-    public String toString() {
-        // Some constructors don't take in a string that we can return directly,
-        // so construct one if needed
-        if (version == null) {
-            if (maximumVersion == null) {
-                version = minimumVersion.toString();
-            } else {
-                version = (minimumExclusive ? "(" : "[") + minimumVersion + "," + maximumVersion
-                          + (maximumExclusive ? ")" : "]");
-            }
-        }
-        return this.version;
-    }
-
-    @Override
-    public int hashCode() {
-        int result = 17;
-        result = 31 * result + minimumVersion.hashCode();
-        result = 31 * result + (minimumExclusive ? 1 : 0);
-        result = 31 * result + (maximumVersion != null ? maximumVersion.hashCode() : 0);
-        result = 31 * result + (maximumExclusive ? 1 : 0);
-        return result;
-    }
-
-    @Override
-    public boolean equals(Object other) {
-        boolean result = false;
-        if (this == other) {
-            result = true;
-        } else if (other instanceof VersionRange) {
-            VersionRange vr = (VersionRange) other;
-            result = minimumVersion.equals(vr.minimumVersion)
-                     && minimumExclusive == vr.minimumExclusive
-                     && (maximumVersion == null ? vr.maximumVersion == null : maximumVersion
-                             .equals(vr.maximumVersion)) && maximumExclusive == vr.maximumExclusive;
-        }
-
-        return result;
-    }
-
-    /**
-     * this method returns the exact version from the versionInfo obj.
-     * this is used for DeploymentContent only to return a valid exact version
-     * otherwise, null is returned.
-     * @return the exact version
-     */
-    public Version getExactVersion() {
-        Version v = null;
-        if (isExactVersion()) {
-            v = getMinimumVersion();
-        }
-        return v;
-    }
-
-    /**
-     * get the maximum version
-     * @return    the maximum version
-     */
-    public Version getMaximumVersion() {
-        return maximumVersion;
-    }
-
-    /**
-     * get the minimum version
-     * @return    the minimum version
-     */
-    public Version getMinimumVersion() {
-        return minimumVersion;
-    }
-
-    /**
-     * is the maximum version exclusive
-     * @return is the max version in the range.
-     */
-    public boolean isMaximumExclusive() {
-        return maximumExclusive;
-    }
-
-    /**
-     * is the maximum version unbounded
-     * @return true if no upper bound was specified.
-     */
-    public boolean isMaximumUnbounded() {
-        boolean unbounded = maximumVersion == null;
-        return unbounded;
-    }
-
-    /**
-     * is the minimum version exclusive
-     * @return true if the min version is in range.
-     */
-    public boolean isMinimumExclusive() {
-        return minimumExclusive;
-    }
-
-    /**
-     * this is designed for deployed-version as that is the exact version.
-     *
-     * @param version
-     * @return
-     * @throws IllegalArgumentException
-     */
-    private boolean processExactVersionAttribute(String version) throws IllegalArgumentException {
-        boolean success = processVersionAttribute(version);
-
-        if (maximumVersion == null) {
-            maximumVersion = minimumVersion;
-        }
-
-        if (!minimumVersion.equals(maximumVersion)) {
-            throw new IllegalArgumentException("Version is not exact: " + version);
-        }
-
-        if (!!!isExactVersion()) {
-            throw new IllegalArgumentException("Version is not exact: " + version);
-        }
-
-        return success;
-    }
-
-    /**
-     * process the version attribute,
-     *
-     * @param version
-     *            the value to be processed
-     * @return
-     * @throws IllegalArgumentException
-     */
-    private boolean processVersionAttribute(String version) throws IllegalArgumentException {
-        boolean success = false;
-
-        if (version == null) {
-            throw new IllegalArgumentException("Version is null");
-        }
-
-        Matcher matches = versionCapture.matcher(version);
-
-        if (matches.matches()) {
-            String versions = matches.group(1);
-
-            if ((versions.startsWith("[") || versions.startsWith("("))
-                && (versions.endsWith("]") || versions.endsWith(")"))) {
-                if (versions.startsWith("["))
-                    minimumExclusive = false;
-                else if (versions.startsWith("("))
-                    minimumExclusive = true;
-
-                if (versions.endsWith("]"))
-                    maximumExclusive = false;
-                else if (versions.endsWith(")"))
-                    maximumExclusive = true;
-
-                int index = versions.indexOf(',');
-                String minVersion = versions.substring(1, index);
-                String maxVersion = versions.substring(index + 1, versions.length() - 1);
-
-                try {
-                    minimumVersion = new Version(minVersion.trim());
-                    maximumVersion = new Version(maxVersion.trim());
-                    success = true;
-                } catch (NumberFormatException nfe) {
-                    throw new IllegalArgumentException("Version cannot be decoded: " + version, nfe);
-                }
-            } else {
-                try {
-                    if (versions.trim().length() == 0)
-                        minimumVersion = new Version(0, 0, 0);
-                    else
-                        minimumVersion = new Version(versions.trim());
-                    success = true;
-                } catch (NumberFormatException nfe) {
-                    throw new IllegalArgumentException("Version cannot be decoded: " + version, nfe);
-                }
-            }
-        } else {
-            throw new IllegalArgumentException("Version cannot be decoded: " + version);
-        }
-
-        return success;
-    }
-
-    /**
-     * Assert object invariants. Called by constructors to verify that arguments
-     * were valid.
-     *
-     * @throws IllegalArgumentException
-     *             if invariants are violated.
-     */
-    private void assertInvariants() {
-        if (minimumVersion == null
-            || !isRangeValid(minimumVersion, minimumExclusive, maximumVersion, maximumExclusive)) {
-            IllegalArgumentException e = new IllegalArgumentException();
-            throw e;
-        }
-    }
-
-    /**
-     * Check if the supplied parameters describe a valid version range.
-     *
-     * @param min
-     *            the minimum version.
-     * @param minExclusive
-     *            whether the minimum version is exclusive.
-     * @param max
-     *            the maximum version.
-     * @param maxExclusive
-     *            whether the maximum version is exclusive.
-     * @return true is the range is valid; otherwise false.
-     */
-    private boolean isRangeValid(Version min,
-                                 boolean minExclusive,
-                                 Version max,
-                                 boolean maxExclusive) {
-        boolean result;
-
-        // A null maximum version is unbounded so means that minimum is smaller
-        // than
-        // maximum.
-        int minMaxCompare = (max == null ? -1 : min.compareTo(max));
-        if (minMaxCompare > 0) {
-            // Minimum larger than maximum is invalid.
-            result = false;
-        } else if (minMaxCompare == 0 && (minExclusive || maxExclusive)) {
-            // If min and max are the same, and either are exclusive, no valid
-            // range
-            // exists.
-            result = false;
-        } else {
-            // Range is valid.
-            result = true;
-        }
-
-        return result;
-    }
-
-    /**
-     * This method checks that the provided version matches the desired version.
-     *
-     * @param version
-     *            the version.
-     * @return true if the version matches, false otherwise.
-     */
-    public boolean matches(Version version) {
-        boolean result;
-        if (this.getMaximumVersion() == null) {
-            result = this.getMinimumVersion().compareTo(version) <= 0;
-        } else {
-            int minN = this.isMinimumExclusive() ? 0 : 1;
-            int maxN = this.isMaximumExclusive() ? 0 : 1;
-
-            result = (this.getMinimumVersion().compareTo(version) < minN)
-                     && (version.compareTo(this.getMaximumVersion()) < maxN);
-        }
-        return result;
-    }
-
-    /**
-     * check if the versioninfo is the exact version
-     * @return true if the range will match 1 exact version.
-     */
-    public boolean isExactVersion() {
-        return minimumVersion.equals(maximumVersion) && minimumExclusive == maximumExclusive
-               && !!!minimumExclusive;
-    }
-
-    /**
-     * Create a new version range that is the intersection of {@code this} and the argument.
-     * In other words, the largest version range that lies within both {@code this} and
-     * the parameter.
-     * @param r a version range to be intersected with {@code this}.
-     * @return a new version range, or {@code null} if no intersection is possible.
-     */
-    public VersionRange intersect(VersionRange r) {
-        // Use the highest minimum version.
-        final Version newMinimumVersion;
-        final boolean newMinimumExclusive;
-        int minCompare = minimumVersion.compareTo(r.getMinimumVersion());
-        if (minCompare > 0) {
-            newMinimumVersion = minimumVersion;
-            newMinimumExclusive = minimumExclusive;
-        } else if (minCompare < 0) {
-            newMinimumVersion = r.getMinimumVersion();
-            newMinimumExclusive = r.isMinimumExclusive();
-        } else {
-            newMinimumVersion = minimumVersion;
-            newMinimumExclusive = (minimumExclusive || r.isMinimumExclusive());
-        }
-
-        // Use the lowest maximum version.
-        final Version newMaximumVersion;
-        final boolean newMaximumExclusive;
-        // null maximum version means unbounded, so the highest possible value.
-        if (maximumVersion == null) {
-            newMaximumVersion = r.getMaximumVersion();
-            newMaximumExclusive = r.isMaximumExclusive();
-        } else if (r.getMaximumVersion() == null) {
-            newMaximumVersion = maximumVersion;
-            newMaximumExclusive = maximumExclusive;
-        } else {
-            int maxCompare = maximumVersion.compareTo(r.getMaximumVersion());
-            if (maxCompare < 0) {
-                newMaximumVersion = maximumVersion;
-                newMaximumExclusive = maximumExclusive;
-            } else if (maxCompare > 0) {
-                newMaximumVersion = r.getMaximumVersion();
-                newMaximumExclusive = r.isMaximumExclusive();
-            } else {
-                newMaximumVersion = maximumVersion;
-                newMaximumExclusive = (maximumExclusive || r.isMaximumExclusive());
-            }
-        }
-
-        VersionRange result;
-        if (isRangeValid(newMinimumVersion, newMinimumExclusive, newMaximumVersion,
-                newMaximumExclusive)) {
-            result = new VersionRange(newMaximumVersion, newMaximumExclusive, newMinimumVersion,
-                    newMinimumExclusive);
-        } else {
-            result = null;
-        }
-        return result;
-    }
-
-    /**
-     * Parse a version range..
-     *
-     * @param s
-     * @return VersionRange object.
-     * @throws IllegalArgumentException
-     *             if the String could not be parsed as a VersionRange
-     */
-    public static VersionRange parseVersionRange(String s) throws IllegalArgumentException {
-        return new VersionRange(s);
-    }
-
-    /**
-     * Parse a version range and indicate if the version is an exact version
-     *
-     * @param s
-     * @param exactVersion
-     * @return VersionRange object.
-     * @throws IllegalArgumentException
-     *             if the String could not be parsed as a VersionRange
-     */
-    public static VersionRange parseVersionRange(String s, boolean exactVersion)
-            throws IllegalArgumentException {
-        return new VersionRange(s, exactVersion);
-    }
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/1bcdb173/region/core/src/main/resources/org/apache/karaf/region/persist/region.xsd
----------------------------------------------------------------------
diff --git a/region/core/src/main/resources/org/apache/karaf/region/persist/region.xsd b/region/core/src/main/resources/org/apache/karaf/region/persist/region.xsd
deleted file mode 100644
index 8ca26e7..0000000
--- a/region/core/src/main/resources/org/apache/karaf/region/persist/region.xsd
+++ /dev/null
@@ -1,109 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-    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.
--->
-
-<!-- $Rev$ $Date$ -->
-
-<xsd:schema xmlns="http://karaf.apache.org/xmlns/region/v1.0.0"
-        xmlns:xsd="http://www.w3.org/2001/XMLSchema"
-        targetNamespace="http://karaf.apache.org/xmlns/region/v1.0.0"
-        elementFormDefault="qualified"
-        attributeFormDefault="unqualified">
-
-
-    <xsd:annotation>
-        <xsd:documentation>
-            Defines the configuration elements for Apache Karaf region xml configuration.
-        </xsd:documentation>
-    </xsd:annotation>
-
-    <xsd:element name="regions" type="regionsType"/>
-
-
-    <xsd:complexType name="regionsType">
-        <xsd:annotation>
-            <xsd:documentation>
-                Regions element
-            </xsd:documentation>
-        </xsd:annotation>
-        <xsd:sequence>
-            <xsd:element name="region" type="regionType" minOccurs="0" maxOccurs="unbounded"/>
-            <xsd:element name="filter" type="filterType" minOccurs="0" maxOccurs="unbounded"/>
-        </xsd:sequence>
-    </xsd:complexType>
-
-    <xsd:complexType name="regionType">
-        <xsd:annotation>
-            <xsd:documentation>
-                Region element
-            </xsd:documentation>
-        </xsd:annotation>
-        <xsd:sequence>
-            <xsd:element name="bundle" type="regionBundleType" minOccurs="0" maxOccurs="unbounded"/>
-        </xsd:sequence>
-        <xsd:attribute name="name" type="xsd:string" use="required"/>
-    </xsd:complexType>
-
-
-    <xsd:complexType name="regionBundleType">
-        <xsd:sequence/>
-        <xsd:attribute name="id" type="xsd:long"/>
-        <xsd:attribute name="location" type="xsd:string"/>
-    </xsd:complexType>
-
-    <xsd:complexType name="filterBundleType">
-        <xsd:sequence>
-            <xsd:element name="attribute" type="filterAttributeType" minOccurs="0" maxOccurs="unbounded"/>
-        </xsd:sequence>
-        <xsd:attribute name="id" type="xsd:long"/>
-        <xsd:attribute name="symbolic-name" type="xsd:string"/>
-        <xsd:attribute name="version" type="xsd:string"/>
-    </xsd:complexType>
-
-    <xsd:complexType name="filterType">
-        <xsd:sequence>
-            <xsd:element name="bundle" type="filterBundleType" minOccurs="0" maxOccurs="unbounded"/>
-            <xsd:element name="package" type="filterPackageType" minOccurs="0" maxOccurs="unbounded"/>
-            <xsd:element name="namespace" type="filterNamespaceType" minOccurs="0" maxOccurs="unbounded"/>
-        </xsd:sequence>
-        <xsd:attribute name="from" type="xsd:string" use="required"/>
-        <xsd:attribute name="to" type="xsd:string" use="required"/>
-    </xsd:complexType>
-
-    <xsd:complexType name="filterPackageType">
-        <xsd:sequence>
-            <xsd:element name="attribute" type="filterAttributeType" minOccurs="0" maxOccurs="unbounded"/>
-        </xsd:sequence>
-        <xsd:attribute name="name" type="xsd:string" use="required"/>
-        <xsd:attribute name="version" type="xsd:string"/>
-    </xsd:complexType>
-
-    <xsd:complexType name="filterAttributeType">
-        <xsd:sequence/>
-        <xsd:attribute name="name" type="xsd:string" use="required"/>
-        <xsd:attribute name="value" type="xsd:string" use="required"/>
-    </xsd:complexType>
-
-    <xsd:complexType name="filterNamespaceType">
-        <xsd:sequence>
-            <xsd:element name="attribute" type="filterAttributeType" minOccurs="0" maxOccurs="unbounded"/>
-        </xsd:sequence>
-        <xsd:attribute name="name" type="xsd:string" use="required"/>
-    </xsd:complexType>
-</xsd:schema>

http://git-wip-us.apache.org/repos/asf/karaf/blob/1bcdb173/region/pom.xml
----------------------------------------------------------------------
diff --git a/region/pom.xml b/region/pom.xml
index 293c908..2375fcc 100644
--- a/region/pom.xml
+++ b/region/pom.xml
@@ -28,91 +28,109 @@
     </parent>
 
     <groupId>org.apache.karaf.region</groupId>
-    <artifactId>region</artifactId>
-    <packaging>pom</packaging>
-    <name>Apache Karaf :: Region</name>
-
-    <modules>
-        <module>core</module>
-        <module>command</module>
-    </modules>
-
-    <profiles>
-
-        <profile>
-            <id>fetch-external</id>
-            <pluginRepositories>
-                <pluginRepository>
-                    <id>ossrh</id>
-                    <name>Sonatype OSS Repository</name>
-                    <url>http://oss.sonatype.org/content/groups/public</url>
-                    <layout>default</layout>
-                </pluginRepository>
-            </pluginRepositories>
-
-
-            <build>
-                <plugins>
-
-                    <!-- EXTERNAL DEPENDENCY RESOLVER -->
-
-                    <plugin>
-                        <groupId>com.savage7.maven.plugins</groupId>
-                        <artifactId>maven-external-dependency-plugin</artifactId>
-                        <version>0.5</version>
-                        <inherited>false</inherited>
-                        <configuration>
-                            <createChecksum>true</createChecksum>
-                            <skipChecksumVerification>false</skipChecksumVerification>
-                            <force>false</force>
-                            <artifactItems>
-<!--     used in aries subsystem but not here
-                                <artifactItem>
-                                    <groupId>org.eclipse</groupId>
-                                    <artifactId>osgi</artifactId>
-                                    <version>3.8.0-SNAPSHOT</version>
-                                    <packaging>jar</packaging>
-                                    <downloadUrl>http://www.eclipse.org/downloads/download.php?file=/equinox/drops/I20111018-0850/org.eclipse.osgi_3.8.0.v20111017-1643.jar&amp;url=http://download.eclipse.org/equinox/drops/I20111018-0850/org.eclipse.osgi_3.8.0.v20111017-1643.jar&amp;mirror_id=1</downloadUrl>
-                                </artifactItem>
-                                <artifactItem>
-                                    <groupId>org.eclipse.equinox</groupId>
-                                    <artifactId>coordinator</artifactId>
-                                    <version>1.0.0.v20110314</version>
-                                    <packaging>jar</packaging>
-                                    <downloadUrl>http://ftp.osuosl.org/pub/eclipse/equinox/drops/R-3.7.1-201109091335/org.eclipse.equinox.coordinator_1.0.0.v20110502.jar</downloadUrl>
-                                </artifactItem>
--->
-                                <artifactItem>
-                                    <groupId>org.eclipse.equinox</groupId>
-                                    <artifactId>region</artifactId>
-                                    <version>1.0.0.v20110506</version>
-                                    <packaging>jar</packaging>
-                                    <downloadUrl>http://ftp.osuosl.org/pub/eclipse/equinox/drops/R-3.7.1-201109091335/org.eclipse.equinox.region_1.0.0.v20110524.jar</downloadUrl>
-                                </artifactItem>
-                            </artifactItems>
-                        </configuration>
-                        <executions>
-                            <execution>
-                                <id>clean-external-dependencies</id>
-                                <phase>clean</phase>
-                                <goals>
-                                    <goal>clean-external</goal>
-                                </goals>
-                            </execution>
-                            <execution>
-                                <id>resolve-install-external-dependencies</id>
-                                <phase>process-resources</phase>
-                                <goals>
-                                    <goal>resolve-external</goal>
-                                    <goal>install-external</goal>
-                                </goals>
-                            </execution>
-                        </executions>
-                    </plugin>
-                </plugins>
-           </build>
-        </profile>
-    </profiles>
+    <artifactId>org.apache.karaf.region.core</artifactId>
+    <packaging>bundle</packaging>
+    <name>Apache Karaf :: Region :: Persistence</name>
+    <description>This bundle provides an xml regions model and install/dump actions.</description>
+
+    <properties>
+        <appendedResourcesDirectory>${basedir}/../../etc/appended-resources</appendedResourcesDirectory>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>org.osgi.core</artifactId>
+            <scope>provided</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.karaf</groupId>
+            <artifactId>org.apache.karaf.util</artifactId>
+            <scope>provided</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>org.osgi.compendium</artifactId>
+            <scope>provided</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-api</artifactId>
+            <scope>provided</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.karaf.features</groupId>
+            <artifactId>org.apache.karaf.features.core</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.eclipse.equinox</groupId>
+            <artifactId>region</artifactId>
+            <version>1.0.0.v20110506</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.karaf.shell</groupId>
+            <artifactId>org.apache.karaf.shell.core</artifactId>
+            <optional>true</optional>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.aries</groupId>
+            <artifactId>org.apache.aries.util</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.easymock</groupId>
+            <artifactId>easymock</artifactId>
+            <scope>test</scope>
+        </dependency>
+		<dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-jdk14</artifactId>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <resources>
+            <resource>
+                <directory>${project.basedir}/src/main/resources</directory>
+                <includes>
+                    <include>**/*</include>
+                </includes>
+            </resource>
+            <resource>
+                <directory>${project.basedir}/src/main/resources</directory>
+                <filtering>true</filtering>
+                <includes>
+                    <include>**/*.info</include>
+                </includes>
+            </resource>
+        </resources>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+                <configuration>
+                    <instructions>
+                        <Bundle-Activator>
+                            org.apache.karaf.region.persist.internal.Activator
+                        </Bundle-Activator>
+                        <Private-Package>
+                            org.apache.karaf.region.commands,
+                            org.apache.karaf.region.commands.util,
+                            org.apache.karaf.region.persist.internal.*,
+                            org.apache.karaf.util.tracker
+                        </Private-Package>
+                        <Karaf-Commands>*</Karaf-Commands>
+                    </instructions>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
 
 </project>
-

http://git-wip-us.apache.org/repos/asf/karaf/blob/1bcdb173/region/src/main/java/org/apache/karaf/region/commands/AddBundleCommand.java
----------------------------------------------------------------------
diff --git a/region/src/main/java/org/apache/karaf/region/commands/AddBundleCommand.java b/region/src/main/java/org/apache/karaf/region/commands/AddBundleCommand.java
new file mode 100644
index 0000000..30af1e0
--- /dev/null
+++ b/region/src/main/java/org/apache/karaf/region/commands/AddBundleCommand.java
@@ -0,0 +1,52 @@
+/*
+ * 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.karaf.region.commands;
+
+import java.util.List;
+
+import org.apache.karaf.shell.api.action.Argument;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.eclipse.equinox.region.Region;
+import org.eclipse.equinox.region.RegionDigraph;
+import org.osgi.framework.Bundle;
+
+@Command(scope = "region", name = "bundle-add", description = "Adds a list of known bundles by id to a specified region.")
+@Service
+public class AddBundleCommand extends RegionCommandSupport {
+
+    @Argument(index = 0, name = "region", description = "Region to add the bundles to", required = true, multiValued = false)
+    String region;
+
+    @Argument(index = 1, name = "bundles", description = "Bundles by id to add to the region", required = true, multiValued = true)
+    List<Long> ids;
+
+    protected void doExecute(RegionDigraph regionDigraph) throws Exception {
+        Region r = getRegion(regionDigraph, region);
+        for (Long id : ids) {
+            for (Region existing: regionDigraph.getRegions()) {
+                if (existing.contains(id)) {
+                    Bundle b = bundleContext.getBundle(id);
+                    System.out.println("Removing bundle " + id + " from region " + existing.getName());
+                    existing.removeBundle(b);
+                    break;
+                }
+            }
+            r.addBundle(id);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/1bcdb173/region/src/main/java/org/apache/karaf/region/commands/AddFilterCommand.java
----------------------------------------------------------------------
diff --git a/region/src/main/java/org/apache/karaf/region/commands/AddFilterCommand.java b/region/src/main/java/org/apache/karaf/region/commands/AddFilterCommand.java
new file mode 100644
index 0000000..ec3766d
--- /dev/null
+++ b/region/src/main/java/org/apache/karaf/region/commands/AddFilterCommand.java
@@ -0,0 +1,169 @@
+/*
+ * 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.karaf.region.commands;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.aries.util.VersionRange;
+import org.apache.aries.util.manifest.ManifestHeaderProcessor;
+import org.apache.karaf.shell.api.action.Argument;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.eclipse.equinox.region.Region;
+import org.eclipse.equinox.region.RegionDigraph;
+import org.eclipse.equinox.region.RegionFilter;
+import org.eclipse.equinox.region.RegionFilterBuilder;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+
+@Command(scope = "region", name = "filter-add", description = "Adds a filter between two regions.")
+@Service
+public class AddFilterCommand extends RegionCommandSupport {
+
+    @Argument(index = 0, name = "from", description = "The from region.", required = true, multiValued = false)
+    String fromRegion;
+
+    @Argument(index = 1, name = "to", description = "The to region.", required = true, multiValued = false)
+    String toRegion;
+
+    @Argument(index = 2, name = "items", description = "The bundles by id and packages with version to allow.", required = false, multiValued = true)
+    List<String> items;
+
+    protected void doExecute(RegionDigraph regionDigraph) throws Exception {
+        Region rFrom = getRegion(regionDigraph, fromRegion);
+        Region rTo = getRegion(regionDigraph, toRegion);
+        RegionFilterBuilder builder = regionDigraph.createRegionFilterBuilder();
+        BundleContext framework = bundleContext.getBundle(0).getBundleContext();
+        if (items != null) {
+            for (String item : items) {
+                try {
+                    long id = Long.parseLong(item);
+                    Bundle b = framework.getBundle(id);
+                    builder.allow("osgi.wiring.bundle", "(osgi.wiring.bundle=" + b.getSymbolicName() + ")");
+                } catch (NumberFormatException e) {
+                    for (Map.Entry<String, Map<String, String>> parsed: ManifestHeaderProcessor.parseImportString(item).entrySet()) {
+                        String packageName = parsed.getKey();
+                        Map<String, String> attributes = new HashMap<String, String>(parsed.getValue());
+                        attributes.put("osgi.wiring.package", packageName);
+                        String filter = generateFilter(attributes);
+                        System.out.println("adding filter " + filter);
+                        builder.allow("osgi.wiring.package", filter);
+                    }
+                }
+
+            }
+        }
+        RegionFilter f = builder.build();
+        regionDigraph.connect(rFrom, f, rTo);
+    }
+
+    //from aries util, with obr specific weirdness removed
+    public static String generateFilter(Map<String, String> attribs) {
+        StringBuilder filter = new StringBuilder("(&");
+        boolean realAttrib = false;
+        StringBuffer realAttribs = new StringBuffer();
+
+        if (attribs == null) {
+            attribs = new HashMap<String, String>();
+        }
+
+        for (Map.Entry<String, String> attrib : attribs.entrySet()) {
+            String attribName = attrib.getKey();
+
+            if (attribName.endsWith(":")) {
+                // skip all directives. It is used to affect the attribs on the
+                // filter xml.
+            } else if ((Constants.VERSION_ATTRIBUTE.equals(attribName))
+                    || (Constants.BUNDLE_VERSION_ATTRIBUTE.equals(attribName))) {
+                // version and bundle-version attrib requires special
+                // conversion.
+                realAttrib = true;
+
+                VersionRange vr = ManifestHeaderProcessor
+                        .parseVersionRange(attrib.getValue());
+
+                filter.append("(" + attribName + ">=" + vr.getMinimumVersion());
+
+                if (vr.getMaximumVersion() != null) {
+                    filter.append(")(" + attribName + "<=");
+                    filter.append(vr.getMaximumVersion());
+                }
+
+                if (vr.getMaximumVersion() != null && vr.isMinimumExclusive()) {
+                    filter.append(")(!(" + attribName + "=");
+                    filter.append(vr.getMinimumVersion());
+                    filter.append(")");
+                }
+
+                if (vr.getMaximumVersion() != null && vr.isMaximumExclusive()) {
+                    filter.append(")(!(" + attribName + "=");
+                    filter.append(vr.getMaximumVersion());
+                    filter.append(")");
+                }
+                filter.append(")");
+
+            } else if (Constants.OBJECTCLASS.equals(attribName)) {
+                realAttrib = true;
+                // objectClass has a "," separated list of interfaces
+                String[] values = attrib.getValue().split(",");
+                for (String s : values)
+                    filter.append("(" + Constants.OBJECTCLASS + "=" + s + ")");
+
+            } else {
+                // attribName was not version..
+                realAttrib = true;
+
+                filter.append("(" + attribName + "=" + attrib.getValue() + ")");
+                // store all attributes in order to build up the mandatory
+                // filter and separate them with ", "
+                // skip bundle-symbolic-name in the mandatory directive query
+                if (!!!Constants.BUNDLE_SYMBOLICNAME_ATTRIBUTE
+                        .equals(attribName)) {
+                    realAttribs.append(attribName);
+                    realAttribs.append(", ");
+                }
+            }
+        }
+
+        // Prune (& off the front and ) off end
+        String filterString = filter.toString();
+        int openBraces = 0;
+        for (int i = 0; openBraces < 3; i++) {
+            i = filterString.indexOf('(', i);
+            if (i == -1) {
+                break;
+            } else {
+                openBraces++;
+            }
+        }
+        if (openBraces < 3 && filterString.length() > 2) {
+            filter.delete(0, 2);
+        } else {
+            filter.append(")");
+        }
+
+        String result = "";
+        if (realAttrib != false) {
+            result = filter.toString();
+        }
+        return result;
+    }
+
+}


[52/59] [abbrv] git commit: [KARAF-2852] Merge web/core and web/command

Posted by gn...@apache.org.
[KARAF-2852] Merge web/core and web/command


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

Branch: refs/heads/master
Commit: 2b7e96df01ae4a1dc56b8e47d0bb915b38aa741b
Parents: 04afd90
Author: Guillaume Nodet <gn...@gmail.com>
Authored: Thu Apr 10 09:59:42 2014 +0200
Committer: Guillaume Nodet <gn...@gmail.com>
Committed: Thu Apr 10 16:02:58 2014 +0200

----------------------------------------------------------------------
 .../standard/src/main/feature/feature.xml       |   1 -
 web/NOTICE                                      |  71 +++++++
 web/command/NOTICE                              |  71 -------
 web/command/pom.xml                             | 105 ----------
 .../org/apache/karaf/web/commands/List.java     |  70 -------
 .../org/apache/karaf/web/commands/Start.java    |  46 -----
 .../org/apache/karaf/web/commands/Stop.java     |  46 -----
 .../src/main/resources/OSGI-INF/bundle.info     |  21 --
 web/core/NOTICE                                 |  71 -------
 web/core/pom.xml                                | 106 ----------
 .../java/org/apache/karaf/web/WebBundle.java    |  79 -------
 .../apache/karaf/web/WebContainerService.java   |  59 ------
 .../web/internal/WebContainerServiceImpl.java   | 205 -------------------
 .../karaf/web/internal/WebEventHandler.java     |  40 ----
 .../karaf/web/internal/osgi/Activator.java      |  55 -----
 .../apache/karaf/web/management/WebMBean.java   |  70 -------
 .../web/management/internal/WebMBeanImpl.java   | 116 -----------
 .../src/main/resources/OSGI-INF/bundle.info     |  16 --
 web/pom.xml                                     |  89 +++++++-
 .../java/org/apache/karaf/web/WebBundle.java    |  79 +++++++
 .../apache/karaf/web/WebContainerService.java   |  59 ++++++
 .../org/apache/karaf/web/commands/List.java     |  70 +++++++
 .../org/apache/karaf/web/commands/Start.java    |  46 +++++
 .../org/apache/karaf/web/commands/Stop.java     |  46 +++++
 .../web/internal/WebContainerServiceImpl.java   | 205 +++++++++++++++++++
 .../karaf/web/internal/WebEventHandler.java     |  40 ++++
 .../karaf/web/internal/osgi/Activator.java      |  55 +++++
 .../apache/karaf/web/management/WebMBean.java   |  70 +++++++
 .../web/management/internal/WebMBeanImpl.java   | 116 +++++++++++
 web/src/main/resources/OSGI-INF/bundle.info     |  16 ++
 30 files changed, 954 insertions(+), 1185 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/karaf/blob/2b7e96df/assemblies/features/standard/src/main/feature/feature.xml
----------------------------------------------------------------------
diff --git a/assemblies/features/standard/src/main/feature/feature.xml b/assemblies/features/standard/src/main/feature/feature.xml
index b6f8dea..fb3dd93 100644
--- a/assemblies/features/standard/src/main/feature/feature.xml
+++ b/assemblies/features/standard/src/main/feature/feature.xml
@@ -177,7 +177,6 @@
         <feature>http</feature>
         <feature>pax-war</feature>
         <bundle start-level="30">mvn:org.apache.karaf.web/org.apache.karaf.web.core/${project.version}</bundle>
-        <bundle start-level="30">mvn:org.apache.karaf.web/org.apache.karaf.web.command/${project.version}</bundle>
     </feature>
     
     <feature name="jetty" version="8.1.9.v20130131" resolver="(obr)">

http://git-wip-us.apache.org/repos/asf/karaf/blob/2b7e96df/web/NOTICE
----------------------------------------------------------------------
diff --git a/web/NOTICE b/web/NOTICE
new file mode 100644
index 0000000..b70f1f9
--- /dev/null
+++ b/web/NOTICE
@@ -0,0 +1,71 @@
+Apache Karaf
+Copyright 2010-2014 The Apache Software Foundation
+
+
+I. Included Software
+
+This product includes software developed at
+The Apache Software Foundation (http://www.apache.org/).
+Licensed under the Apache License 2.0.
+
+This product uses software developed at
+The OSGi Alliance (http://www.osgi.org/).
+Copyright (c) OSGi Alliance (2000, 2010).
+Licensed under the Apache License 2.0.
+
+This product includes software developed at
+OW2 (http://www.ow2.org/).
+Licensed under the BSD License.
+
+This product includes software developed at
+OPS4J (http://www.ops4j.org/).
+Licensed under the Apache License 2.0.
+
+This product includes software developed at
+Eclipse Foundation (http://www.eclipse.org/).
+Licensed under the EPL.
+
+This product includes software written by
+Antony Lesuisse.
+Licensed under Public Domain.
+
+
+II. Used Software
+
+This product uses software developed at
+FUSE Source (http://www.fusesource.org/).
+Licensed under the Apache License 2.0.
+
+This product uses software developed at
+AOP Alliance (http://aopalliance.sourceforge.net/).
+Licensed under the Public Domain.
+
+This product uses software developed at
+Tanuki Software (http://www.tanukisoftware.com/).
+Licensed under the Apache License 2.0.
+
+This product uses software developed at
+Jasypt (http://jasypt.sourceforge.net/).
+Licensed under the Apache License 2.0.
+
+This product uses software developed at
+JLine (http://jline.sourceforge.net).
+Licensed under the BSD License.
+
+This product uses software developed at
+SLF4J (http://www.slf4j.org/).
+Licensed under the MIT License.
+
+This product uses software developed at
+SpringSource (http://www.springsource.org/).
+Licensed under the Apache License 2.0.
+
+This product includes software from http://www.json.org.
+Copyright (c) 2002 JSON.org
+
+
+III. License Summary
+- Apache License 2.0
+- BSD License
+- EPL License
+- MIT License

http://git-wip-us.apache.org/repos/asf/karaf/blob/2b7e96df/web/command/NOTICE
----------------------------------------------------------------------
diff --git a/web/command/NOTICE b/web/command/NOTICE
deleted file mode 100644
index b70f1f9..0000000
--- a/web/command/NOTICE
+++ /dev/null
@@ -1,71 +0,0 @@
-Apache Karaf
-Copyright 2010-2014 The Apache Software Foundation
-
-
-I. Included Software
-
-This product includes software developed at
-The Apache Software Foundation (http://www.apache.org/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-The OSGi Alliance (http://www.osgi.org/).
-Copyright (c) OSGi Alliance (2000, 2010).
-Licensed under the Apache License 2.0.
-
-This product includes software developed at
-OW2 (http://www.ow2.org/).
-Licensed under the BSD License.
-
-This product includes software developed at
-OPS4J (http://www.ops4j.org/).
-Licensed under the Apache License 2.0.
-
-This product includes software developed at
-Eclipse Foundation (http://www.eclipse.org/).
-Licensed under the EPL.
-
-This product includes software written by
-Antony Lesuisse.
-Licensed under Public Domain.
-
-
-II. Used Software
-
-This product uses software developed at
-FUSE Source (http://www.fusesource.org/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-AOP Alliance (http://aopalliance.sourceforge.net/).
-Licensed under the Public Domain.
-
-This product uses software developed at
-Tanuki Software (http://www.tanukisoftware.com/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-Jasypt (http://jasypt.sourceforge.net/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-JLine (http://jline.sourceforge.net).
-Licensed under the BSD License.
-
-This product uses software developed at
-SLF4J (http://www.slf4j.org/).
-Licensed under the MIT License.
-
-This product uses software developed at
-SpringSource (http://www.springsource.org/).
-Licensed under the Apache License 2.0.
-
-This product includes software from http://www.json.org.
-Copyright (c) 2002 JSON.org
-
-
-III. License Summary
-- Apache License 2.0
-- BSD License
-- EPL License
-- MIT License

http://git-wip-us.apache.org/repos/asf/karaf/blob/2b7e96df/web/command/pom.xml
----------------------------------------------------------------------
diff --git a/web/command/pom.xml b/web/command/pom.xml
deleted file mode 100644
index f053ab7..0000000
--- a/web/command/pom.xml
+++ /dev/null
@@ -1,105 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-
-    <!--
-
-        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.
-    -->
-
-    <modelVersion>4.0.0</modelVersion>
-
-    <parent>
-        <groupId>org.apache.karaf.web</groupId>
-        <artifactId>web</artifactId>
-        <version>4.0.0-SNAPSHOT</version>
-        <relativePath>../pom.xml</relativePath>
-    </parent>
-
-    <artifactId>org.apache.karaf.web.command</artifactId>
-    <packaging>bundle</packaging>
-    <name>Apache Karaf :: Web :: Commands</name>
-    <description>
-        This bundle provides Karaf shell commands to manipulate the WebContainer service.
-    </description>
-
-    <properties>
-        <appendedResourcesDirectory>${basedir}/../../etc/appended-resources</appendedResourcesDirectory>
-    </properties>
-
-    <dependencies>
-        <dependency>
-            <groupId>org.apache.karaf.web</groupId>
-            <artifactId>org.apache.karaf.web.core</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.karaf.shell</groupId>
-            <artifactId>org.apache.karaf.shell.core</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.osgi</groupId>
-            <artifactId>org.osgi.core</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.osgi</groupId>
-            <artifactId>org.osgi.compendium</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.karaf</groupId>
-            <artifactId>org.apache.karaf.util</artifactId>
-            <scope>provided</scope>
-        </dependency>
-    </dependencies>
-
-    <build>
-        <resources>
-            <resource>
-                <directory>${project.basedir}/src/main/resources</directory>
-                <includes>
-                    <include>**/*</include>
-                </includes>
-            </resource>
-            <resource>
-                <directory>${project.basedir}/src/main/resources</directory>
-                <filtering>true</filtering>
-                <includes>
-                    <include>**/*.info</include>
-                </includes>
-            </resource>
-        </resources>
-        <plugins>
-            <plugin>
-                <groupId>org.apache.felix</groupId>
-                <artifactId>maven-bundle-plugin</artifactId>
-                <configuration>
-                    <instructions>
-                        <Export-Package>
-                            !org.apache.karaf.web.commands
-                        </Export-Package>
-                        <Private-Package>
-                            org.apache.karaf.web.commands
-                        </Private-Package>
-                        <Karaf-Commands>*</Karaf-Commands>
-                    </instructions>
-                </configuration>
-            </plugin>
-        </plugins>
-    </build>
-
-</project>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/karaf/blob/2b7e96df/web/command/src/main/java/org/apache/karaf/web/commands/List.java
----------------------------------------------------------------------
diff --git a/web/command/src/main/java/org/apache/karaf/web/commands/List.java b/web/command/src/main/java/org/apache/karaf/web/commands/List.java
deleted file mode 100644
index a862a45..0000000
--- a/web/command/src/main/java/org/apache/karaf/web/commands/List.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * 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.karaf.web.commands;
-
-import org.apache.karaf.shell.api.action.Action;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Option;
-import org.apache.karaf.shell.api.action.lifecycle.Reference;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.apache.karaf.shell.support.table.Col;
-import org.apache.karaf.shell.support.table.ShellTable;
-import org.apache.karaf.web.WebBundle;
-import org.apache.karaf.web.WebContainerService;
-
-@Command(scope = "web", name = "list", description = "Lists details for war bundles.")
-@Service
-public class List implements Action {
-
-    @Option(name = "--no-format", description = "Disable table rendered output", required = false, multiValued = false)
-    boolean noFormat;
-
-    @Reference
-    private WebContainerService webContainerService;
-    
-    public void setWebContainerService(WebContainerService webContainerService) {
-        this.webContainerService = webContainerService;
-    }
-
-    @Override
-    public Object execute() throws Exception {
-    	ShellTable table = new ShellTable();
-        table.column(new Col("ID"));
-        table.column(new Col("State"));
-        table.column(new Col("Web-State"));
-        table.column(new Col("Level"));
-        table.column(new Col("Web-ContextPath"));
-        table.column(new Col("Name"));
-        
-        java.util.List<WebBundle> webBundles = webContainerService.list();
-        if (webBundles != null && !webBundles.isEmpty()) {
-            for (WebBundle webBundle : webBundles) {
-            	table.addRow().addContent(
-                        webBundle.getBundleId(),
-                        webBundle.getState(),
-                        webBundle.getWebState(),
-                        webBundle.getLevel(),
-                        webBundle.getContextPath(),
-                        webBundle.getName());
-            }
-            
-        }
-        table.print(System.out, !noFormat);
-        return null;
-    }
-    
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/2b7e96df/web/command/src/main/java/org/apache/karaf/web/commands/Start.java
----------------------------------------------------------------------
diff --git a/web/command/src/main/java/org/apache/karaf/web/commands/Start.java b/web/command/src/main/java/org/apache/karaf/web/commands/Start.java
deleted file mode 100644
index 41d6634..0000000
--- a/web/command/src/main/java/org/apache/karaf/web/commands/Start.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * 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.karaf.web.commands;
-
-import org.apache.karaf.shell.api.action.Action;
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.lifecycle.Reference;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.apache.karaf.web.WebContainerService;
-
-@Command(scope = "web", name = "start", description = "Start the web context of given bundles.")
-@Service
-public class Start implements Action {
-
-    @Argument(index = 0, name = "ids", description = "The list of bundle IDs separated by whitespaces", required = true, multiValued = true)
-    java.util.List<Long> ids;
-
-    @Reference
-    private WebContainerService webContainerService;
-
-    public void setWebContainerService(WebContainerService webContainerService) {
-        this.webContainerService = webContainerService;
-    }
-
-    @Override
-    public Object execute() throws Exception {
-        webContainerService.start(ids);
-        return null;
-    }
-    
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/2b7e96df/web/command/src/main/java/org/apache/karaf/web/commands/Stop.java
----------------------------------------------------------------------
diff --git a/web/command/src/main/java/org/apache/karaf/web/commands/Stop.java b/web/command/src/main/java/org/apache/karaf/web/commands/Stop.java
deleted file mode 100644
index 76fd141..0000000
--- a/web/command/src/main/java/org/apache/karaf/web/commands/Stop.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * 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.karaf.web.commands;
-
-import org.apache.karaf.shell.api.action.Action;
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.lifecycle.Reference;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.apache.karaf.web.WebContainerService;
-
-@Command(scope = "web", name = "stop", description = "Stop the web context of given bundles.")
-@Service
-public class Stop implements Action {
-
-    @Argument(index = 0, name = "ids", description = "The list of bundle IDs separated by whitespaces", required = true, multiValued = true)
-    java.util.List<Long> ids;
-
-    @Reference
-    private WebContainerService webContainerService;
-    
-    public void setWebContainerService(WebContainerService webContainerService) {
-        this.webContainerService = webContainerService;
-    }
-
-    @Override
-    public Object execute() throws Exception {
-        webContainerService.stop(ids);
-        return null;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/2b7e96df/web/command/src/main/resources/OSGI-INF/bundle.info
----------------------------------------------------------------------
diff --git a/web/command/src/main/resources/OSGI-INF/bundle.info b/web/command/src/main/resources/OSGI-INF/bundle.info
deleted file mode 100644
index 6acb144..0000000
--- a/web/command/src/main/resources/OSGI-INF/bundle.info
+++ /dev/null
@@ -1,21 +0,0 @@
-h1. Synopsis
-
-${project.name}
-
-${project.description}
-
-Maven URL:
-[mvn:${project.groupId}/${project.artifactId}/${project.version}]
-
-h1. Description
-
-This bundle contains all Karaf shell commands related to the web container.
-
-The following commands are available:
-* web:list - List detail information about web bundles.
-* web:start - Start the web context for the given web bundles.
-* web:stop - Stop the web context for the given web bundles.
-
-h1. See also
-
-Web Container - section of the Karaf User Guide.
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/karaf/blob/2b7e96df/web/core/NOTICE
----------------------------------------------------------------------
diff --git a/web/core/NOTICE b/web/core/NOTICE
deleted file mode 100644
index b70f1f9..0000000
--- a/web/core/NOTICE
+++ /dev/null
@@ -1,71 +0,0 @@
-Apache Karaf
-Copyright 2010-2014 The Apache Software Foundation
-
-
-I. Included Software
-
-This product includes software developed at
-The Apache Software Foundation (http://www.apache.org/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-The OSGi Alliance (http://www.osgi.org/).
-Copyright (c) OSGi Alliance (2000, 2010).
-Licensed under the Apache License 2.0.
-
-This product includes software developed at
-OW2 (http://www.ow2.org/).
-Licensed under the BSD License.
-
-This product includes software developed at
-OPS4J (http://www.ops4j.org/).
-Licensed under the Apache License 2.0.
-
-This product includes software developed at
-Eclipse Foundation (http://www.eclipse.org/).
-Licensed under the EPL.
-
-This product includes software written by
-Antony Lesuisse.
-Licensed under Public Domain.
-
-
-II. Used Software
-
-This product uses software developed at
-FUSE Source (http://www.fusesource.org/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-AOP Alliance (http://aopalliance.sourceforge.net/).
-Licensed under the Public Domain.
-
-This product uses software developed at
-Tanuki Software (http://www.tanukisoftware.com/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-Jasypt (http://jasypt.sourceforge.net/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-JLine (http://jline.sourceforge.net).
-Licensed under the BSD License.
-
-This product uses software developed at
-SLF4J (http://www.slf4j.org/).
-Licensed under the MIT License.
-
-This product uses software developed at
-SpringSource (http://www.springsource.org/).
-Licensed under the Apache License 2.0.
-
-This product includes software from http://www.json.org.
-Copyright (c) 2002 JSON.org
-
-
-III. License Summary
-- Apache License 2.0
-- BSD License
-- EPL License
-- MIT License

http://git-wip-us.apache.org/repos/asf/karaf/blob/2b7e96df/web/core/pom.xml
----------------------------------------------------------------------
diff --git a/web/core/pom.xml b/web/core/pom.xml
deleted file mode 100644
index a6ec17e..0000000
--- a/web/core/pom.xml
+++ /dev/null
@@ -1,106 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-
-    <!--
-
-        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.
-    -->
-
-    <modelVersion>4.0.0</modelVersion>
-
-    <parent>
-        <groupId>org.apache.karaf.web</groupId>
-        <artifactId>web</artifactId>
-        <version>4.0.0-SNAPSHOT</version>
-        <relativePath>../pom.xml</relativePath>
-    </parent>
-
-    <artifactId>org.apache.karaf.web.core</artifactId>
-    <packaging>bundle</packaging>
-    <name>Apache Karaf :: Web :: Core</name>
-    <description>
-        This bundle provide the core service to manipulate the web container/bundles.
-    </description>
-
-    <properties>
-        <appendedResourcesDirectory>${basedir}/../../etc/appended-resources</appendedResourcesDirectory>
-    </properties>
-
-    <dependencies>
-        <dependency>
-            <groupId>org.osgi</groupId>
-            <artifactId>org.osgi.core</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.ops4j.pax.web</groupId>
-            <artifactId>pax-web-spi</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.slf4j</groupId>
-            <artifactId>slf4j-api</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.karaf</groupId>
-            <artifactId>org.apache.karaf.util</artifactId>
-            <scope>provided</scope>
-        </dependency>
-    </dependencies>
-
-    <build>
-        <resources>
-            <resource>
-                <directory>${project.basedir}/src/main/resources</directory>
-                <includes>
-                    <include>**/*</include>
-                </includes>
-            </resource>
-            <resource>
-                <directory>${project.basedir}/src/main/resources</directory>
-                <filtering>true</filtering>
-                <includes>
-                    <include>**/*.info</include>
-                </includes>
-            </resource>
-        </resources>
-        <plugins>
-            <plugin>
-                <groupId>org.apache.felix</groupId>
-                <artifactId>maven-bundle-plugin</artifactId>
-                <configuration>
-                    <instructions>
-                        <Export-Package>
-                            org.apache.karaf.web,
-                            org.apache.karaf.web.management
-                        </Export-Package>
-                        <Private-Package>
-                            org.apache.karaf.web.internal,
-                            org.apache.karaf.web.internal.osgi,
-                            org.apache.karaf.web.management.internal,
-                            org.apache.karaf.util.tracker
-                        </Private-Package>
-                        <Bundle-Activator>
-                            org.apache.karaf.web.internal.osgi.Activator
-                        </Bundle-Activator>
-                    </instructions>
-                </configuration>
-            </plugin>
-        </plugins>
-    </build>
-
-</project>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/karaf/blob/2b7e96df/web/core/src/main/java/org/apache/karaf/web/WebBundle.java
----------------------------------------------------------------------
diff --git a/web/core/src/main/java/org/apache/karaf/web/WebBundle.java b/web/core/src/main/java/org/apache/karaf/web/WebBundle.java
deleted file mode 100644
index 484495d..0000000
--- a/web/core/src/main/java/org/apache/karaf/web/WebBundle.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * 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.karaf.web;
-
-/**
- * Container for WebBundle information.
- */
-public class WebBundle {
-
-    private long bundleId;
-    private String name;
-    private int level;
-    private String state;
-    private String webState;
-    private String contextPath;
-
-    public long getBundleId() {
-        return bundleId;
-    }
-
-    public void setBundleId(long bundleId) {
-        this.bundleId = bundleId;
-    }
-
-    public String getName() {
-        return name;
-    }
-
-    public void setName(String name) {
-        this.name = name;
-    }
-
-    public int getLevel() {
-        return level;
-    }
-
-    public void setLevel(int level) {
-        this.level = level;
-    }
-
-    public String getState() {
-        return state;
-    }
-
-    public void setState(String state) {
-        this.state = state;
-    }
-
-    public String getWebState() {
-        return webState;
-    }
-
-    public void setWebState(String webState) {
-        this.webState = webState;
-    }
-
-    public String getContextPath() {
-        return contextPath;
-    }
-
-    public void setContextPath(String contextPath) {
-        this.contextPath = contextPath;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/2b7e96df/web/core/src/main/java/org/apache/karaf/web/WebContainerService.java
----------------------------------------------------------------------
diff --git a/web/core/src/main/java/org/apache/karaf/web/WebContainerService.java b/web/core/src/main/java/org/apache/karaf/web/WebContainerService.java
deleted file mode 100644
index 989817b..0000000
--- a/web/core/src/main/java/org/apache/karaf/web/WebContainerService.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * 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.karaf.web;
-
-import java.util.List;
-
-/**
- * Describe the WebContainer service.
- */
-public interface WebContainerService {
-
-    /**
-     * List of web bundles deployed in the web container.
-     *
-     * @return the list of web bundles.
-     * @throws Exception in case of listing failure.
-     */
-    List<WebBundle> list() throws Exception;
-
-    /**
-     * Get a string representation of the web state of a bundle (identified by id).
-     *
-     * @param bundleId the bundle ID.
-     * @return the string representation of the bundle web state.
-     * @throws Exception in case of "mapping" failure.
-     */
-    String state(long bundleId) throws Exception;
-
-    /**
-     * Start the web context of given bundles (identified by an ID).
-     *
-     * @param bundleIds the list of bundle IDs (TODO use a BundleSelector service).
-     * @throws Exception in case of deploy failure.
-     */
-    void start(List<Long> bundleIds) throws Exception;
-
-    /**
-     * Stop the web context of given bundles (identified by an ID).
-     *
-     * @param bundleIds the list of bundle IDs (TODO use a BundleSelector service).
-     * @throws Exception in case of undeploy failure.
-     */
-    void stop(List<Long> bundleIds) throws Exception;
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/2b7e96df/web/core/src/main/java/org/apache/karaf/web/internal/WebContainerServiceImpl.java
----------------------------------------------------------------------
diff --git a/web/core/src/main/java/org/apache/karaf/web/internal/WebContainerServiceImpl.java b/web/core/src/main/java/org/apache/karaf/web/internal/WebContainerServiceImpl.java
deleted file mode 100644
index 4affc8f..0000000
--- a/web/core/src/main/java/org/apache/karaf/web/internal/WebContainerServiceImpl.java
+++ /dev/null
@@ -1,205 +0,0 @@
-/*
- * 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.karaf.web.internal;
-
-import org.apache.karaf.web.WebBundle;
-import org.apache.karaf.web.WebContainerService;
-import org.ops4j.pax.web.service.spi.WarManager;
-import org.ops4j.pax.web.service.spi.WebEvent;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.Constants;
-import org.osgi.framework.startlevel.BundleStartLevel;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-
-/**
- * Implementation of the WebContainer service.
- */
-public class WebContainerServiceImpl implements WebContainerService {
-    
-    private BundleContext bundleContext;
-    private WebEventHandler webEventHandler;
-    private WarManager warManager;
-    
-    private static final Logger LOGGER = LoggerFactory.getLogger(WebContainerServiceImpl.class);
-    
-    public void setBundleContext(BundleContext bundleContext) {
-        this.bundleContext = bundleContext;
-    }
-    
-    public void setWebEventHandler(WebEventHandler webEventHandler) {
-        this.webEventHandler = webEventHandler;
-    }
-
-    public void setWarManager(WarManager warManager) {
-        this.warManager = warManager;
-    }
-    
-    public List<WebBundle> list() throws Exception {
-        Bundle[] bundles = bundleContext.getBundles();
-        Map<Long, WebEvent> bundleEvents = webEventHandler.getBundleEvents();
-        List<WebBundle> webBundles = new ArrayList<WebBundle>();
-        if (bundles != null) {
-            for (Bundle bundle : bundles) {
-                // first check if the bundle is a web bundle
-                String contextPath = (String) bundle.getHeaders().get("Web-ContextPath");
-                if (contextPath == null) {
-                    contextPath = (String) bundle.getHeaders().get("Webapp-Context"); // this one used by pax-web but is deprecated
-                }
-                if (contextPath == null) {
-                    // the bundle is not a web bundle
-                    continue;
-                }
-                
-                WebBundle webBundle = new WebBundle();
-                contextPath.trim();
-                
-                // get the bundle name
-                String name = (String) bundle.getHeaders().get(Constants.BUNDLE_NAME);
-                // if there is no name, then default to symbolic name
-                name = (name == null) ? bundle.getSymbolicName() : name;
-                // if there is no symbolic name, resort to location
-                name = (name == null) ? bundle.getLocation() : name;
-                // get the bundle version
-                String version = (String) bundle.getHeaders().get(Constants.BUNDLE_VERSION);
-                name = ((version != null)) ? name + " (" + version + ")" : name;
-                long bundleId = bundle.getBundleId();
-                int level = bundle.adapt(BundleStartLevel.class).getStartLevel();
-                if (!contextPath.startsWith("/")) {
-                    contextPath = "/" + contextPath;
-                }
-                
-                webBundle.setBundleId(bundleId);
-                webBundle.setName(name);
-                webBundle.setContextPath(contextPath);
-                webBundle.setLevel(level);
-                webBundle.setState(getStateString(bundle));
-                webBundle.setWebState(state(bundle.getBundleId()));
-                
-                webBundles.add(webBundle);
-            }
-        }
-        
-        return webBundles;
-    }
-    
-    public void start(List<Long> bundleIds) throws Exception {
-        if (bundleIds != null && !bundleIds.isEmpty()) {
-            for (long bundleId : bundleIds) {
-                if (webEventHandler.getBundleEvents().containsKey(bundleId)) {
-                    WebEvent webEvent = webEventHandler.getBundleEvents().get(bundleId);
-                    Bundle bundle = webEvent.getBundle();
-                    if (bundle != null) {
-                        // deploy
-                        warManager.start(bundleId, null);
-                    } else {
-                        System.out.println("Bundle ID " + bundleId + " is invalid");
-                        LOGGER.warn("Bundle ID {} is invalid", bundleId);
-                    }
-                }
-            }
-        }
-    }
-
-    public void stop(List<Long> bundleIds) throws Exception {
-        if (bundleIds != null && !bundleIds.isEmpty()) {
-            for (long bundleId : bundleIds) {
-                if (webEventHandler.getBundleEvents().containsKey(bundleId)) {
-                    WebEvent webEvent = webEventHandler.getBundleEvents().get(bundleId);
-                    Bundle bundle = webEvent.getBundle();
-                    if (bundle != null) {
-                        // deploy
-                        warManager.stop(bundleId);
-                    } else {
-                        System.out.println("Bundle ID " + bundleId + " is invalid");
-                        LOGGER.warn("Bundle ID {} is invalid", bundleId);
-                    }
-                }
-            }
-        }
-    }
-
-    public String state(long bundleId) {
-
-        Map<Long, WebEvent> bundleEvents = webEventHandler.getBundleEvents();
-        String topic = "Unknown    ";
-
-        if (bundleEvents.containsKey(bundleId)) {
-            WebEvent webEvent = bundleEvents.get(bundleId);
-
-            switch(webEvent.getType()) {
-                case WebEvent.DEPLOYING:
-                    topic = "Deploying  ";
-                    break;
-                case WebEvent.DEPLOYED:
-                    topic = "Deployed   ";
-                    break;
-                case WebEvent.UNDEPLOYING:
-                    topic = "Undeploying";
-                    break;
-                case WebEvent.UNDEPLOYED:
-                    topic = "Undeployed ";
-                    break;
-                case WebEvent.FAILED:
-                    topic = "Failed     ";
-                    break;
-                case WebEvent.WAITING:
-                    topic = "Waiting    ";
-                    break;
-                default:
-                    topic = "Failed     ";
-            }
-        }
-
-        while (topic.length() < 11) {
-            topic += " ";
-        }
-
-        return topic;
-    }
-
-    /**
-     * Return a string representation of the bundle state.
-     * 
-     * TODO use an util method provided by bundle core
-     * 
-     * @param bundle the target bundle.
-     * @return the string representation of the state
-     */
-    private String getStateString(Bundle bundle) {
-        int state = bundle.getState();
-        if (state == Bundle.ACTIVE) {
-            return "Active     ";
-        } else if (state == Bundle.INSTALLED) {
-            return "Installed  ";
-        } else if (state == Bundle.RESOLVED) {
-            return "Resolved   ";
-        } else if (state == Bundle.STARTING) {
-            return "Starting   ";
-        } else if (state == Bundle.STOPPING) {
-            return "Stopping   ";
-        } else {
-            return "Unknown    ";
-        }
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/2b7e96df/web/core/src/main/java/org/apache/karaf/web/internal/WebEventHandler.java
----------------------------------------------------------------------
diff --git a/web/core/src/main/java/org/apache/karaf/web/internal/WebEventHandler.java b/web/core/src/main/java/org/apache/karaf/web/internal/WebEventHandler.java
deleted file mode 100644
index 01ef52e..0000000
--- a/web/core/src/main/java/org/apache/karaf/web/internal/WebEventHandler.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * 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.karaf.web.internal;
-
-import org.ops4j.pax.web.service.spi.WebEvent;
-import org.ops4j.pax.web.service.spi.WebListener;
-
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * Class implementing {@link WebListener} service to retrieve {@link WebEvent}.
- */
-public class WebEventHandler implements WebListener {
-
-    private final Map<Long, WebEvent> bundleEvents = new HashMap<Long, WebEvent>();
-
-    public Map<Long, WebEvent> getBundleEvents() {
-        return bundleEvents;
-    }
-
-    public void webEvent(WebEvent event) {
-        getBundleEvents().put(event.getBundle().getBundleId(), event);
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/2b7e96df/web/core/src/main/java/org/apache/karaf/web/internal/osgi/Activator.java
----------------------------------------------------------------------
diff --git a/web/core/src/main/java/org/apache/karaf/web/internal/osgi/Activator.java b/web/core/src/main/java/org/apache/karaf/web/internal/osgi/Activator.java
deleted file mode 100644
index e5bcfe1..0000000
--- a/web/core/src/main/java/org/apache/karaf/web/internal/osgi/Activator.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * 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.karaf.web.internal.osgi;
-
-import org.apache.karaf.util.tracker.BaseActivator;
-import org.apache.karaf.web.WebContainerService;
-import org.apache.karaf.web.internal.WebContainerServiceImpl;
-import org.apache.karaf.web.internal.WebEventHandler;
-import org.apache.karaf.web.management.internal.WebMBeanImpl;
-import org.ops4j.pax.web.service.spi.WarManager;
-import org.ops4j.pax.web.service.spi.WebListener;
-
-public class Activator extends BaseActivator {
-
-    @Override
-    protected void doOpen() throws Exception {
-        trackService(WarManager.class);
-    }
-
-    @Override
-    protected void doStart() throws Exception {
-        WarManager warManager = getTrackedService(WarManager.class);
-        if (warManager == null) {
-            return;
-        }
-
-        WebEventHandler webEventHandler = new WebEventHandler();
-        register(WebListener.class, webEventHandler);
-
-        WebContainerServiceImpl webContainerService = new WebContainerServiceImpl();
-        webContainerService.setBundleContext(bundleContext);
-        webContainerService.setWarManager(warManager);
-        webContainerService.setWebEventHandler(webEventHandler);
-        register(WebContainerService.class, webContainerService);
-
-        WebMBeanImpl webMBean = new WebMBeanImpl();
-        webMBean.setWebContainerService(webContainerService);
-        registerMBean(webMBean, "type=web");
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/2b7e96df/web/core/src/main/java/org/apache/karaf/web/management/WebMBean.java
----------------------------------------------------------------------
diff --git a/web/core/src/main/java/org/apache/karaf/web/management/WebMBean.java b/web/core/src/main/java/org/apache/karaf/web/management/WebMBean.java
deleted file mode 100644
index 5c6df22..0000000
--- a/web/core/src/main/java/org/apache/karaf/web/management/WebMBean.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * 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.karaf.web.management;
-
-import javax.management.MBeanException;
-import javax.management.openmbean.TabularData;
-import java.util.List;
-
-/**
- * Describe the Web MBean.
- */
-public interface WebMBean {
-
-    /**
-     * Return the list of web bundles.
-     * 
-     * @return a tabular data of web bundles.
-     * @throws Exception in case of lookup failure.
-     */
-    TabularData getWebBundles() throws MBeanException;
-
-    /**
-     * Start web context of the given web bundle (identified by ID).
-     *
-     * @param bundleId the bundle ID.
-     * @throws MBeanException
-     */
-    void start(Long bundleId) throws MBeanException;
-
-    /**
-     * Start web context of the given web bundles (identified by ID).
-     * 
-     * @param bundleIds the list of bundle IDs.
-     *                  TODO use a BundleSelector service
-     * @throws Exception in case of start failure.
-     */
-    void start(List<Long> bundleIds) throws MBeanException;
-
-    /**
-     * Stop web context of the given web bundle (identified by ID).
-     *
-     * @param bundleId the bundle ID.
-     * @throws MBeanException
-     */
-    void stop(Long bundleId) throws MBeanException;
-
-    /**
-     * Stop web context of the given web bundles (identified by ID).
-     *
-     * @param bundleIds the list of bundle IDs.
-     *                  TODO use a BundleSelector service
-     * @throws Exception in case of stop failure
-     */
-    void stop(List<Long> bundleIds) throws MBeanException;
-    
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/2b7e96df/web/core/src/main/java/org/apache/karaf/web/management/internal/WebMBeanImpl.java
----------------------------------------------------------------------
diff --git a/web/core/src/main/java/org/apache/karaf/web/management/internal/WebMBeanImpl.java b/web/core/src/main/java/org/apache/karaf/web/management/internal/WebMBeanImpl.java
deleted file mode 100644
index f1a81bb..0000000
--- a/web/core/src/main/java/org/apache/karaf/web/management/internal/WebMBeanImpl.java
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * 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.karaf.web.management.internal;
-
-import org.apache.karaf.web.WebBundle;
-import org.apache.karaf.web.WebContainerService;
-import org.apache.karaf.web.management.WebMBean;
-
-import javax.management.MBeanException;
-import javax.management.NotCompliantMBeanException;
-import javax.management.StandardMBean;
-import javax.management.openmbean.*;
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Implementation of the Web MBean.
- */
-public class WebMBeanImpl extends StandardMBean implements WebMBean {
-
-    private WebContainerService webContainerService;
-
-    public WebMBeanImpl() throws NotCompliantMBeanException {
-        super(WebMBean.class);
-    }
-
-    public void setWebContainerService(WebContainerService webContainerService) {
-        this.webContainerService = webContainerService;
-    }
-
-    public TabularData getWebBundles() throws MBeanException {
-        try {
-            CompositeType webType = new CompositeType("Web Bundle", "An OSGi Web bundle",
-                    new String[]{"ID", "State", "Web-State", "Level", "Web-ContextPath", "Name"},
-                    new String[]{"ID of the bundle",
-                            "OSGi state of the bundle",
-                            "Web state of the bundle",
-                            "Start level of the bundle",
-                            "Web context path",
-                            "Name of the bundle"},
-                    new OpenType[]{SimpleType.LONG, SimpleType.STRING, SimpleType.STRING, SimpleType.INTEGER, SimpleType.STRING, SimpleType.STRING});
-            TabularType tableType = new TabularType("Web Bundles", "Table of web bundles", webType,
-                    new String[]{"ID"});
-            TabularData table = new TabularDataSupport(tableType);
-            for (WebBundle webBundle : webContainerService.list()) {
-                try {
-                    CompositeData data = new CompositeDataSupport(webType,
-                            new String[]{"ID", "State", "Web-State", "Level", "Web-ContextPath", "Name"},
-                            new Object[]{webBundle.getBundleId(),
-                                    webBundle.getState(),
-                                    webBundle.getWebState(),
-                                    webBundle.getLevel(),
-                                    webBundle.getContextPath(),
-                                    webBundle.getName()});
-                    table.put(data);
-                } catch (Exception e) {
-                    e.printStackTrace();
-                }
-            }
-            return table;
-        } catch (Exception e) {
-            throw new MBeanException(null, e.getMessage());
-        }
-    }
-
-    public void start(Long bundleId) throws MBeanException {
-        try {
-            List<Long> list = new ArrayList<Long>();
-            list.add(bundleId);
-            webContainerService.start(list);
-        } catch (Exception e) {
-            throw new MBeanException(null, e.getMessage());
-        }
-    }
-
-    public void start(List<Long> bundleIds) throws MBeanException {
-        try {
-            webContainerService.start(bundleIds);
-        } catch (Exception e) {
-            throw new MBeanException(null, e.getMessage());
-        }
-    }
-
-    public void stop(Long bundleId) throws MBeanException {
-        try {
-            List<Long> list = new ArrayList<Long>();
-            list.add(bundleId);
-            webContainerService.stop(list);
-        } catch (Exception e) {
-            throw new MBeanException(null, e.getMessage());
-        }
-    }
-
-    public void stop(List<Long> bundleIds) throws MBeanException {
-        try {
-            webContainerService.stop(bundleIds);
-        } catch (Exception e) {
-            throw new MBeanException(null, e.getMessage());
-        }
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/2b7e96df/web/core/src/main/resources/OSGI-INF/bundle.info
----------------------------------------------------------------------
diff --git a/web/core/src/main/resources/OSGI-INF/bundle.info b/web/core/src/main/resources/OSGI-INF/bundle.info
deleted file mode 100644
index 650fee9..0000000
--- a/web/core/src/main/resources/OSGI-INF/bundle.info
+++ /dev/null
@@ -1,16 +0,0 @@
-h1. Synopsis
-
-${project.name}
-
-${project.description}
-
-Maven URL:
-[mvn:${project.groupId}/${project.artifactId}/${project.version}]
-
-h1. Description
-
-This bundle provides support of the WebContainer service, which allows to manipulate the Karaf embedded web container.
-
-h1. See also
-
-Web Container - section of the Karaf User Guide

http://git-wip-us.apache.org/repos/asf/karaf/blob/2b7e96df/web/pom.xml
----------------------------------------------------------------------
diff --git a/web/pom.xml b/web/pom.xml
index 6284a5c..037ee5f 100644
--- a/web/pom.xml
+++ b/web/pom.xml
@@ -29,13 +29,86 @@
     </parent>
 
     <groupId>org.apache.karaf.web</groupId>
-    <artifactId>web</artifactId>
-    <packaging>pom</packaging>
-    <name>Apache Karaf :: Web</name>
-
-    <modules>
-        <module>core</module>
-        <module>command</module>
-    </modules>
+    <artifactId>org.apache.karaf.web.core</artifactId>
+    <packaging>bundle</packaging>
+    <name>Apache Karaf :: Web :: Core</name>
+    <description>
+        This bundle provide the core service to manipulate the web container/bundles.
+    </description>
+
+    <properties>
+        <appendedResourcesDirectory>${basedir}/../../etc/appended-resources</appendedResourcesDirectory>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>org.osgi.core</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.ops4j.pax.web</groupId>
+            <artifactId>pax-web-spi</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-api</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.karaf</groupId>
+            <artifactId>org.apache.karaf.util</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.karaf.shell</groupId>
+            <artifactId>org.apache.karaf.shell.core</artifactId>
+            <optional>true</optional>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <resources>
+            <resource>
+                <directory>${project.basedir}/src/main/resources</directory>
+                <includes>
+                    <include>**/*</include>
+                </includes>
+            </resource>
+            <resource>
+                <directory>${project.basedir}/src/main/resources</directory>
+                <filtering>true</filtering>
+                <includes>
+                    <include>**/*.info</include>
+                </includes>
+            </resource>
+        </resources>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+                <configuration>
+                    <instructions>
+                        <Export-Package>
+                            org.apache.karaf.web,
+                            org.apache.karaf.web.management
+                        </Export-Package>
+                        <Private-Package>
+                            org.apache.karaf.web.commands,
+                            org.apache.karaf.web.internal,
+                            org.apache.karaf.web.internal.osgi,
+                            org.apache.karaf.web.management.internal,
+                            org.apache.karaf.util.tracker
+                        </Private-Package>
+                        <Bundle-Activator>
+                            org.apache.karaf.web.internal.osgi.Activator
+                        </Bundle-Activator>
+                        <Karaf-Commands>*</Karaf-Commands>
+                    </instructions>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
 
 </project>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/karaf/blob/2b7e96df/web/src/main/java/org/apache/karaf/web/WebBundle.java
----------------------------------------------------------------------
diff --git a/web/src/main/java/org/apache/karaf/web/WebBundle.java b/web/src/main/java/org/apache/karaf/web/WebBundle.java
new file mode 100644
index 0000000..484495d
--- /dev/null
+++ b/web/src/main/java/org/apache/karaf/web/WebBundle.java
@@ -0,0 +1,79 @@
+/*
+ * 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.karaf.web;
+
+/**
+ * Container for WebBundle information.
+ */
+public class WebBundle {
+
+    private long bundleId;
+    private String name;
+    private int level;
+    private String state;
+    private String webState;
+    private String contextPath;
+
+    public long getBundleId() {
+        return bundleId;
+    }
+
+    public void setBundleId(long bundleId) {
+        this.bundleId = bundleId;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public int getLevel() {
+        return level;
+    }
+
+    public void setLevel(int level) {
+        this.level = level;
+    }
+
+    public String getState() {
+        return state;
+    }
+
+    public void setState(String state) {
+        this.state = state;
+    }
+
+    public String getWebState() {
+        return webState;
+    }
+
+    public void setWebState(String webState) {
+        this.webState = webState;
+    }
+
+    public String getContextPath() {
+        return contextPath;
+    }
+
+    public void setContextPath(String contextPath) {
+        this.contextPath = contextPath;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/2b7e96df/web/src/main/java/org/apache/karaf/web/WebContainerService.java
----------------------------------------------------------------------
diff --git a/web/src/main/java/org/apache/karaf/web/WebContainerService.java b/web/src/main/java/org/apache/karaf/web/WebContainerService.java
new file mode 100644
index 0000000..989817b
--- /dev/null
+++ b/web/src/main/java/org/apache/karaf/web/WebContainerService.java
@@ -0,0 +1,59 @@
+/*
+ * 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.karaf.web;
+
+import java.util.List;
+
+/**
+ * Describe the WebContainer service.
+ */
+public interface WebContainerService {
+
+    /**
+     * List of web bundles deployed in the web container.
+     *
+     * @return the list of web bundles.
+     * @throws Exception in case of listing failure.
+     */
+    List<WebBundle> list() throws Exception;
+
+    /**
+     * Get a string representation of the web state of a bundle (identified by id).
+     *
+     * @param bundleId the bundle ID.
+     * @return the string representation of the bundle web state.
+     * @throws Exception in case of "mapping" failure.
+     */
+    String state(long bundleId) throws Exception;
+
+    /**
+     * Start the web context of given bundles (identified by an ID).
+     *
+     * @param bundleIds the list of bundle IDs (TODO use a BundleSelector service).
+     * @throws Exception in case of deploy failure.
+     */
+    void start(List<Long> bundleIds) throws Exception;
+
+    /**
+     * Stop the web context of given bundles (identified by an ID).
+     *
+     * @param bundleIds the list of bundle IDs (TODO use a BundleSelector service).
+     * @throws Exception in case of undeploy failure.
+     */
+    void stop(List<Long> bundleIds) throws Exception;
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/2b7e96df/web/src/main/java/org/apache/karaf/web/commands/List.java
----------------------------------------------------------------------
diff --git a/web/src/main/java/org/apache/karaf/web/commands/List.java b/web/src/main/java/org/apache/karaf/web/commands/List.java
new file mode 100644
index 0000000..a862a45
--- /dev/null
+++ b/web/src/main/java/org/apache/karaf/web/commands/List.java
@@ -0,0 +1,70 @@
+/*
+ * 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.karaf.web.commands;
+
+import org.apache.karaf.shell.api.action.Action;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.Option;
+import org.apache.karaf.shell.api.action.lifecycle.Reference;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.apache.karaf.shell.support.table.Col;
+import org.apache.karaf.shell.support.table.ShellTable;
+import org.apache.karaf.web.WebBundle;
+import org.apache.karaf.web.WebContainerService;
+
+@Command(scope = "web", name = "list", description = "Lists details for war bundles.")
+@Service
+public class List implements Action {
+
+    @Option(name = "--no-format", description = "Disable table rendered output", required = false, multiValued = false)
+    boolean noFormat;
+
+    @Reference
+    private WebContainerService webContainerService;
+    
+    public void setWebContainerService(WebContainerService webContainerService) {
+        this.webContainerService = webContainerService;
+    }
+
+    @Override
+    public Object execute() throws Exception {
+    	ShellTable table = new ShellTable();
+        table.column(new Col("ID"));
+        table.column(new Col("State"));
+        table.column(new Col("Web-State"));
+        table.column(new Col("Level"));
+        table.column(new Col("Web-ContextPath"));
+        table.column(new Col("Name"));
+        
+        java.util.List<WebBundle> webBundles = webContainerService.list();
+        if (webBundles != null && !webBundles.isEmpty()) {
+            for (WebBundle webBundle : webBundles) {
+            	table.addRow().addContent(
+                        webBundle.getBundleId(),
+                        webBundle.getState(),
+                        webBundle.getWebState(),
+                        webBundle.getLevel(),
+                        webBundle.getContextPath(),
+                        webBundle.getName());
+            }
+            
+        }
+        table.print(System.out, !noFormat);
+        return null;
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/2b7e96df/web/src/main/java/org/apache/karaf/web/commands/Start.java
----------------------------------------------------------------------
diff --git a/web/src/main/java/org/apache/karaf/web/commands/Start.java b/web/src/main/java/org/apache/karaf/web/commands/Start.java
new file mode 100644
index 0000000..41d6634
--- /dev/null
+++ b/web/src/main/java/org/apache/karaf/web/commands/Start.java
@@ -0,0 +1,46 @@
+/*
+ * 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.karaf.web.commands;
+
+import org.apache.karaf.shell.api.action.Action;
+import org.apache.karaf.shell.api.action.Argument;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.lifecycle.Reference;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.apache.karaf.web.WebContainerService;
+
+@Command(scope = "web", name = "start", description = "Start the web context of given bundles.")
+@Service
+public class Start implements Action {
+
+    @Argument(index = 0, name = "ids", description = "The list of bundle IDs separated by whitespaces", required = true, multiValued = true)
+    java.util.List<Long> ids;
+
+    @Reference
+    private WebContainerService webContainerService;
+
+    public void setWebContainerService(WebContainerService webContainerService) {
+        this.webContainerService = webContainerService;
+    }
+
+    @Override
+    public Object execute() throws Exception {
+        webContainerService.start(ids);
+        return null;
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/2b7e96df/web/src/main/java/org/apache/karaf/web/commands/Stop.java
----------------------------------------------------------------------
diff --git a/web/src/main/java/org/apache/karaf/web/commands/Stop.java b/web/src/main/java/org/apache/karaf/web/commands/Stop.java
new file mode 100644
index 0000000..76fd141
--- /dev/null
+++ b/web/src/main/java/org/apache/karaf/web/commands/Stop.java
@@ -0,0 +1,46 @@
+/*
+ * 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.karaf.web.commands;
+
+import org.apache.karaf.shell.api.action.Action;
+import org.apache.karaf.shell.api.action.Argument;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.lifecycle.Reference;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.apache.karaf.web.WebContainerService;
+
+@Command(scope = "web", name = "stop", description = "Stop the web context of given bundles.")
+@Service
+public class Stop implements Action {
+
+    @Argument(index = 0, name = "ids", description = "The list of bundle IDs separated by whitespaces", required = true, multiValued = true)
+    java.util.List<Long> ids;
+
+    @Reference
+    private WebContainerService webContainerService;
+    
+    public void setWebContainerService(WebContainerService webContainerService) {
+        this.webContainerService = webContainerService;
+    }
+
+    @Override
+    public Object execute() throws Exception {
+        webContainerService.stop(ids);
+        return null;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/2b7e96df/web/src/main/java/org/apache/karaf/web/internal/WebContainerServiceImpl.java
----------------------------------------------------------------------
diff --git a/web/src/main/java/org/apache/karaf/web/internal/WebContainerServiceImpl.java b/web/src/main/java/org/apache/karaf/web/internal/WebContainerServiceImpl.java
new file mode 100644
index 0000000..4affc8f
--- /dev/null
+++ b/web/src/main/java/org/apache/karaf/web/internal/WebContainerServiceImpl.java
@@ -0,0 +1,205 @@
+/*
+ * 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.karaf.web.internal;
+
+import org.apache.karaf.web.WebBundle;
+import org.apache.karaf.web.WebContainerService;
+import org.ops4j.pax.web.service.spi.WarManager;
+import org.ops4j.pax.web.service.spi.WebEvent;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.osgi.framework.startlevel.BundleStartLevel;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Implementation of the WebContainer service.
+ */
+public class WebContainerServiceImpl implements WebContainerService {
+    
+    private BundleContext bundleContext;
+    private WebEventHandler webEventHandler;
+    private WarManager warManager;
+    
+    private static final Logger LOGGER = LoggerFactory.getLogger(WebContainerServiceImpl.class);
+    
+    public void setBundleContext(BundleContext bundleContext) {
+        this.bundleContext = bundleContext;
+    }
+    
+    public void setWebEventHandler(WebEventHandler webEventHandler) {
+        this.webEventHandler = webEventHandler;
+    }
+
+    public void setWarManager(WarManager warManager) {
+        this.warManager = warManager;
+    }
+    
+    public List<WebBundle> list() throws Exception {
+        Bundle[] bundles = bundleContext.getBundles();
+        Map<Long, WebEvent> bundleEvents = webEventHandler.getBundleEvents();
+        List<WebBundle> webBundles = new ArrayList<WebBundle>();
+        if (bundles != null) {
+            for (Bundle bundle : bundles) {
+                // first check if the bundle is a web bundle
+                String contextPath = (String) bundle.getHeaders().get("Web-ContextPath");
+                if (contextPath == null) {
+                    contextPath = (String) bundle.getHeaders().get("Webapp-Context"); // this one used by pax-web but is deprecated
+                }
+                if (contextPath == null) {
+                    // the bundle is not a web bundle
+                    continue;
+                }
+                
+                WebBundle webBundle = new WebBundle();
+                contextPath.trim();
+                
+                // get the bundle name
+                String name = (String) bundle.getHeaders().get(Constants.BUNDLE_NAME);
+                // if there is no name, then default to symbolic name
+                name = (name == null) ? bundle.getSymbolicName() : name;
+                // if there is no symbolic name, resort to location
+                name = (name == null) ? bundle.getLocation() : name;
+                // get the bundle version
+                String version = (String) bundle.getHeaders().get(Constants.BUNDLE_VERSION);
+                name = ((version != null)) ? name + " (" + version + ")" : name;
+                long bundleId = bundle.getBundleId();
+                int level = bundle.adapt(BundleStartLevel.class).getStartLevel();
+                if (!contextPath.startsWith("/")) {
+                    contextPath = "/" + contextPath;
+                }
+                
+                webBundle.setBundleId(bundleId);
+                webBundle.setName(name);
+                webBundle.setContextPath(contextPath);
+                webBundle.setLevel(level);
+                webBundle.setState(getStateString(bundle));
+                webBundle.setWebState(state(bundle.getBundleId()));
+                
+                webBundles.add(webBundle);
+            }
+        }
+        
+        return webBundles;
+    }
+    
+    public void start(List<Long> bundleIds) throws Exception {
+        if (bundleIds != null && !bundleIds.isEmpty()) {
+            for (long bundleId : bundleIds) {
+                if (webEventHandler.getBundleEvents().containsKey(bundleId)) {
+                    WebEvent webEvent = webEventHandler.getBundleEvents().get(bundleId);
+                    Bundle bundle = webEvent.getBundle();
+                    if (bundle != null) {
+                        // deploy
+                        warManager.start(bundleId, null);
+                    } else {
+                        System.out.println("Bundle ID " + bundleId + " is invalid");
+                        LOGGER.warn("Bundle ID {} is invalid", bundleId);
+                    }
+                }
+            }
+        }
+    }
+
+    public void stop(List<Long> bundleIds) throws Exception {
+        if (bundleIds != null && !bundleIds.isEmpty()) {
+            for (long bundleId : bundleIds) {
+                if (webEventHandler.getBundleEvents().containsKey(bundleId)) {
+                    WebEvent webEvent = webEventHandler.getBundleEvents().get(bundleId);
+                    Bundle bundle = webEvent.getBundle();
+                    if (bundle != null) {
+                        // deploy
+                        warManager.stop(bundleId);
+                    } else {
+                        System.out.println("Bundle ID " + bundleId + " is invalid");
+                        LOGGER.warn("Bundle ID {} is invalid", bundleId);
+                    }
+                }
+            }
+        }
+    }
+
+    public String state(long bundleId) {
+
+        Map<Long, WebEvent> bundleEvents = webEventHandler.getBundleEvents();
+        String topic = "Unknown    ";
+
+        if (bundleEvents.containsKey(bundleId)) {
+            WebEvent webEvent = bundleEvents.get(bundleId);
+
+            switch(webEvent.getType()) {
+                case WebEvent.DEPLOYING:
+                    topic = "Deploying  ";
+                    break;
+                case WebEvent.DEPLOYED:
+                    topic = "Deployed   ";
+                    break;
+                case WebEvent.UNDEPLOYING:
+                    topic = "Undeploying";
+                    break;
+                case WebEvent.UNDEPLOYED:
+                    topic = "Undeployed ";
+                    break;
+                case WebEvent.FAILED:
+                    topic = "Failed     ";
+                    break;
+                case WebEvent.WAITING:
+                    topic = "Waiting    ";
+                    break;
+                default:
+                    topic = "Failed     ";
+            }
+        }
+
+        while (topic.length() < 11) {
+            topic += " ";
+        }
+
+        return topic;
+    }
+
+    /**
+     * Return a string representation of the bundle state.
+     * 
+     * TODO use an util method provided by bundle core
+     * 
+     * @param bundle the target bundle.
+     * @return the string representation of the state
+     */
+    private String getStateString(Bundle bundle) {
+        int state = bundle.getState();
+        if (state == Bundle.ACTIVE) {
+            return "Active     ";
+        } else if (state == Bundle.INSTALLED) {
+            return "Installed  ";
+        } else if (state == Bundle.RESOLVED) {
+            return "Resolved   ";
+        } else if (state == Bundle.STARTING) {
+            return "Starting   ";
+        } else if (state == Bundle.STOPPING) {
+            return "Stopping   ";
+        } else {
+            return "Unknown    ";
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/2b7e96df/web/src/main/java/org/apache/karaf/web/internal/WebEventHandler.java
----------------------------------------------------------------------
diff --git a/web/src/main/java/org/apache/karaf/web/internal/WebEventHandler.java b/web/src/main/java/org/apache/karaf/web/internal/WebEventHandler.java
new file mode 100644
index 0000000..01ef52e
--- /dev/null
+++ b/web/src/main/java/org/apache/karaf/web/internal/WebEventHandler.java
@@ -0,0 +1,40 @@
+/*
+ * 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.karaf.web.internal;
+
+import org.ops4j.pax.web.service.spi.WebEvent;
+import org.ops4j.pax.web.service.spi.WebListener;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Class implementing {@link WebListener} service to retrieve {@link WebEvent}.
+ */
+public class WebEventHandler implements WebListener {
+
+    private final Map<Long, WebEvent> bundleEvents = new HashMap<Long, WebEvent>();
+
+    public Map<Long, WebEvent> getBundleEvents() {
+        return bundleEvents;
+    }
+
+    public void webEvent(WebEvent event) {
+        getBundleEvents().put(event.getBundle().getBundleId(), event);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/2b7e96df/web/src/main/java/org/apache/karaf/web/internal/osgi/Activator.java
----------------------------------------------------------------------
diff --git a/web/src/main/java/org/apache/karaf/web/internal/osgi/Activator.java b/web/src/main/java/org/apache/karaf/web/internal/osgi/Activator.java
new file mode 100644
index 0000000..e5bcfe1
--- /dev/null
+++ b/web/src/main/java/org/apache/karaf/web/internal/osgi/Activator.java
@@ -0,0 +1,55 @@
+/*
+ * 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.karaf.web.internal.osgi;
+
+import org.apache.karaf.util.tracker.BaseActivator;
+import org.apache.karaf.web.WebContainerService;
+import org.apache.karaf.web.internal.WebContainerServiceImpl;
+import org.apache.karaf.web.internal.WebEventHandler;
+import org.apache.karaf.web.management.internal.WebMBeanImpl;
+import org.ops4j.pax.web.service.spi.WarManager;
+import org.ops4j.pax.web.service.spi.WebListener;
+
+public class Activator extends BaseActivator {
+
+    @Override
+    protected void doOpen() throws Exception {
+        trackService(WarManager.class);
+    }
+
+    @Override
+    protected void doStart() throws Exception {
+        WarManager warManager = getTrackedService(WarManager.class);
+        if (warManager == null) {
+            return;
+        }
+
+        WebEventHandler webEventHandler = new WebEventHandler();
+        register(WebListener.class, webEventHandler);
+
+        WebContainerServiceImpl webContainerService = new WebContainerServiceImpl();
+        webContainerService.setBundleContext(bundleContext);
+        webContainerService.setWarManager(warManager);
+        webContainerService.setWebEventHandler(webEventHandler);
+        register(WebContainerService.class, webContainerService);
+
+        WebMBeanImpl webMBean = new WebMBeanImpl();
+        webMBean.setWebContainerService(webContainerService);
+        registerMBean(webMBean, "type=web");
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/2b7e96df/web/src/main/java/org/apache/karaf/web/management/WebMBean.java
----------------------------------------------------------------------
diff --git a/web/src/main/java/org/apache/karaf/web/management/WebMBean.java b/web/src/main/java/org/apache/karaf/web/management/WebMBean.java
new file mode 100644
index 0000000..5c6df22
--- /dev/null
+++ b/web/src/main/java/org/apache/karaf/web/management/WebMBean.java
@@ -0,0 +1,70 @@
+/*
+ * 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.karaf.web.management;
+
+import javax.management.MBeanException;
+import javax.management.openmbean.TabularData;
+import java.util.List;
+
+/**
+ * Describe the Web MBean.
+ */
+public interface WebMBean {
+
+    /**
+     * Return the list of web bundles.
+     * 
+     * @return a tabular data of web bundles.
+     * @throws Exception in case of lookup failure.
+     */
+    TabularData getWebBundles() throws MBeanException;
+
+    /**
+     * Start web context of the given web bundle (identified by ID).
+     *
+     * @param bundleId the bundle ID.
+     * @throws MBeanException
+     */
+    void start(Long bundleId) throws MBeanException;
+
+    /**
+     * Start web context of the given web bundles (identified by ID).
+     * 
+     * @param bundleIds the list of bundle IDs.
+     *                  TODO use a BundleSelector service
+     * @throws Exception in case of start failure.
+     */
+    void start(List<Long> bundleIds) throws MBeanException;
+
+    /**
+     * Stop web context of the given web bundle (identified by ID).
+     *
+     * @param bundleId the bundle ID.
+     * @throws MBeanException
+     */
+    void stop(Long bundleId) throws MBeanException;
+
+    /**
+     * Stop web context of the given web bundles (identified by ID).
+     *
+     * @param bundleIds the list of bundle IDs.
+     *                  TODO use a BundleSelector service
+     * @throws Exception in case of stop failure
+     */
+    void stop(List<Long> bundleIds) throws MBeanException;
+    
+}


[12/59] [abbrv] [KARAF-2852] Merge features/core and features/command

Posted by gn...@apache.org.
http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/core/src/main/java/org/apache/karaf/features/internal/service/BootFeaturesInstaller.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/service/BootFeaturesInstaller.java b/features/core/src/main/java/org/apache/karaf/features/internal/service/BootFeaturesInstaller.java
deleted file mode 100644
index 380848a..0000000
--- a/features/core/src/main/java/org/apache/karaf/features/internal/service/BootFeaturesInstaller.java
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * 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.karaf.features.internal.service;
-
-import java.net.URI;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.EnumSet;
-import java.util.HashSet;
-import java.util.Hashtable;
-import java.util.List;
-import java.util.Set;
-import java.util.TreeSet;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import org.apache.karaf.features.BootFinished;
-import org.apache.karaf.features.Feature;
-import org.apache.karaf.features.FeaturesService;
-import org.osgi.framework.BundleContext;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class BootFeaturesInstaller {
-
-    private static final Logger LOGGER = LoggerFactory.getLogger(BootFeaturesInstaller.class);
-
-    public static String VERSION_PREFIX = "version=";
-
-    private final FeaturesServiceImpl featuresService;
-    private final BundleContext bundleContext;
-    private final String repositories;
-    private final String features;
-    private final boolean asynchronous;
-
-    /**
-     *
-     * @param features list of boot features separated by comma. Optionally contains ;version=x.x.x to specify a specific feature version
-     */
-    public BootFeaturesInstaller(BundleContext bundleContext,
-                                 FeaturesServiceImpl featuresService,
-                                 String repositories,
-                                 String features,
-                                 boolean asynchronous) {
-        this.bundleContext = bundleContext;
-        this.featuresService = featuresService;
-        this.repositories = repositories;
-        this.features = features;
-        this.asynchronous = asynchronous;
-    }
-
-    /**
-     * Install boot features
-     */
-    public void start() {
-        if (featuresService.isBootDone()) {
-            publishBootFinished();
-            return;
-        }
-        if (asynchronous) {
-            new Thread("Initial Features Provisioning") {
-                public void run() {
-                    installBootFeatures();
-                }
-            }.start();
-        } else {
-            installBootFeatures();
-        }
-    }
-
-    protected void installBootFeatures() {
-        try {
-            for (String repo : repositories.split(",")) {
-                repo = repo.trim();
-                if (!repo.isEmpty()) {
-                    try {
-                        featuresService.addRepository(URI.create(repo));
-                    } catch (Exception e) {
-                        LOGGER.error("Error installing boot feature repository " + repo);
-                    }
-                }
-            }
-
-            List<Set<String>> stagedFeatures = parseBootFeatures(features);
-            for (Set<String> features : stagedFeatures) {
-                featuresService.installFeatures(features, EnumSet.of(FeaturesService.Option.NoFailOnFeatureNotFound));
-            }
-            featuresService.bootDone();
-            publishBootFinished();
-        } catch (Exception e) {
-            // Special handling in case the bundle has been refreshed.
-            // In such a case, simply exits without logging any exception
-            // as the restart should cause the feature service to finish
-            // the work.
-            if (e instanceof IllegalStateException) {
-                try {
-                    bundleContext.getBundle();
-                } catch (IllegalStateException ies) {
-                    return;
-                }
-            }
-            LOGGER.error("Error installing boot features", e);
-        }
-    }
-
-    /**
-     *
-     * @param featureSt either feature name or <featurename>;version=<version>
-     * @return feature matching the feature string
-     * @throws Exception
-     */
-    private Feature getFeature(String featureSt) throws Exception {
-        String[] parts = featureSt.trim().split(";");
-        String featureName = parts[0];
-        String featureVersion = null;
-        for (String part : parts) {
-            // if the part starts with "version=" it contains the version info
-            if (part.startsWith(VERSION_PREFIX)) {
-                featureVersion = part.substring(VERSION_PREFIX.length());
-            }
-        }
-        if (featureVersion == null) {
-            // no version specified - use default version
-            featureVersion = org.apache.karaf.features.internal.model.Feature.DEFAULT_VERSION;
-        }
-        return featuresService.getFeature(featureName, featureVersion);
-    }
-
-    protected List<Set<String>> parseBootFeatures(String bootFeatures) {
-        Pattern pattern = Pattern.compile("(\\((.+))\\),|.+");
-        Matcher matcher = pattern.matcher(bootFeatures);
-        List<Set<String>> result = new ArrayList<Set<String>>();
-        while (matcher.find()) {
-            String group = matcher.group(2) != null ? matcher.group(2) : matcher.group();
-            result.add(parseFeatureList(group));
-        }
-        return result;
-    }
-
-    protected Set<String> parseFeatureList(String group) {
-        HashSet<String> features = new HashSet<String>();
-        for (String feature : Arrays.asList(group.trim().split("\\s*,\\s*"))) {
-            if (feature.length() > 0) {
-                features.add(feature);
-            }
-        }
-        return features;
-    }
-
-    private void publishBootFinished() {
-        if (bundleContext != null) {
-            BootFinished bootFinished = new BootFinished() {};
-            bundleContext.registerService(BootFinished.class, bootFinished, new Hashtable<String, String>());
-        }
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/core/src/main/java/org/apache/karaf/features/internal/service/EventAdminListener.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/service/EventAdminListener.java b/features/core/src/main/java/org/apache/karaf/features/internal/service/EventAdminListener.java
deleted file mode 100644
index b6eaae5..0000000
--- a/features/core/src/main/java/org/apache/karaf/features/internal/service/EventAdminListener.java
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * 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.karaf.features.internal.service;
-
-import java.util.Dictionary;
-import java.util.Hashtable;
-
-import org.apache.karaf.features.EventConstants;
-import org.apache.karaf.features.FeatureEvent;
-import org.apache.karaf.features.FeaturesListener;
-import org.apache.karaf.features.RepositoryEvent;
-import org.osgi.framework.BundleContext;
-import org.osgi.service.event.Event;
-import org.osgi.service.event.EventAdmin;
-import org.osgi.util.tracker.ServiceTracker;
-
-/**
- * A listener to publish events to EventAdmin
- */
-public class EventAdminListener implements FeaturesListener {
-
-    private final ServiceTracker<EventAdmin, EventAdmin> tracker;
-
-    public EventAdminListener(BundleContext context) {
-        tracker = new ServiceTracker<EventAdmin, EventAdmin>(context, EventAdmin.class.getName(), null);
-        tracker.open();
-    }
-
-    public void featureEvent(FeatureEvent event) {
-        EventAdmin eventAdmin = tracker.getService();
-        if (eventAdmin == null) {
-            return;
-        }
-        Dictionary<String, Object> props = new Hashtable<String, Object>();
-        props.put(EventConstants.TYPE, event.getType());
-        props.put(EventConstants.EVENT, event);
-        props.put(EventConstants.TIMESTAMP, System.currentTimeMillis());
-        props.put(EventConstants.FEATURE_NAME, event.getFeature().getName());
-        props.put(EventConstants.FEATURE_VERSION, event.getFeature().getVersion());
-        String topic;
-        switch (event.getType()) {
-            case FeatureInstalled:
-                topic = EventConstants.TOPIC_FEATURES_INSTALLED;
-                break;
-            case FeatureUninstalled:
-                topic = EventConstants.TOPIC_FEATURES_UNINSTALLED;
-                break;
-            default:
-                throw new IllegalStateException("Unknown features event type: " + event.getType());
-        }
-        eventAdmin.postEvent(new Event(topic, props));
-    }
-
-    public void repositoryEvent(RepositoryEvent event) {
-        EventAdmin eventAdmin = tracker.getService();
-        if (eventAdmin == null) {
-            return;
-        }
-        Dictionary<String, Object> props = new Hashtable<String, Object>();
-        props.put(EventConstants.TYPE, event.getType());
-        props.put(EventConstants.EVENT, event);
-        props.put(EventConstants.TIMESTAMP, System.currentTimeMillis());
-        props.put(EventConstants.REPOSITORY_URI, event.getRepository().getURI().toString());
-        String topic;
-        switch (event.getType()) {
-            case RepositoryAdded:
-                topic = EventConstants.TOPIC_REPOSITORY_ADDED;
-                break;
-            case RepositoryRemoved:
-                topic = EventConstants.TOPIC_REPOSITORY_REMOVED;
-                break;
-            default:
-                throw new IllegalStateException("Unknown repository event type: " + event.getType());
-        }
-        eventAdmin.postEvent(new Event(topic, props));
-    }
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/core/src/main/java/org/apache/karaf/features/internal/service/FeatureConfigInstaller.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/service/FeatureConfigInstaller.java b/features/core/src/main/java/org/apache/karaf/features/internal/service/FeatureConfigInstaller.java
deleted file mode 100644
index 0e9038d..0000000
--- a/features/core/src/main/java/org/apache/karaf/features/internal/service/FeatureConfigInstaller.java
+++ /dev/null
@@ -1,167 +0,0 @@
-/*
- * 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.karaf.features.internal.service;
-
-import java.io.BufferedInputStream;
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.util.Dictionary;
-import java.util.Hashtable;
-
-import org.apache.karaf.features.ConfigFileInfo;
-import org.apache.karaf.features.Feature;
-import org.osgi.framework.Constants;
-import org.osgi.framework.InvalidSyntaxException;
-import org.osgi.service.cm.Configuration;
-import org.osgi.service.cm.ConfigurationAdmin;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class FeatureConfigInstaller {
-	private static final Logger LOGGER = LoggerFactory.getLogger(FeaturesServiceImpl.class);
-    private static final String CONFIG_KEY = "org.apache.karaf.features.configKey";
-
-    private final ConfigurationAdmin configAdmin;
-    
-    public FeatureConfigInstaller(ConfigurationAdmin configAdmin) {
-		this.configAdmin = configAdmin;
-	}
-
-    private String[] parsePid(String pid) {
-        int n = pid.indexOf('-');
-        if (n > 0) {
-            String factoryPid = pid.substring(n + 1);
-            pid = pid.substring(0, n);
-            return new String[]{pid, factoryPid};
-        } else {
-            return new String[]{pid, null};
-        }
-    }
-
-    private Configuration createConfiguration(ConfigurationAdmin configurationAdmin,
-                                                String pid, String factoryPid) throws IOException, InvalidSyntaxException {
-        if (factoryPid != null) {
-            return configurationAdmin.createFactoryConfiguration(factoryPid, null);
-        } else {
-            return configurationAdmin.getConfiguration(pid, null);
-        }
-    }
-
-    private Configuration findExistingConfiguration(ConfigurationAdmin configurationAdmin,
-                                                      String pid, String factoryPid) throws IOException, InvalidSyntaxException {
-        String filter;
-        if (factoryPid == null) {
-            filter = "(" + Constants.SERVICE_PID + "=" + pid + ")";
-        } else {
-            String key = createConfigurationKey(pid, factoryPid);
-            filter = "(" + CONFIG_KEY + "=" + key + ")";
-        }
-        Configuration[] configurations = configurationAdmin.listConfigurations(filter);
-        if (configurations != null && configurations.length > 0) {
-            return configurations[0];
-        }
-        return null;
-    }
-
-    void installFeatureConfigs(Feature feature) throws IOException, InvalidSyntaxException {
-        for (String config : feature.getConfigurations().keySet()) {
-            Dictionary<String,String> props = new Hashtable<String, String>(feature.getConfigurations().get(config));
-            String[] pid = parsePid(config);
-            Configuration cfg = findExistingConfiguration(configAdmin, pid[0], pid[1]);
-            if (cfg == null) {
-                cfg = createConfiguration(configAdmin, pid[0], pid[1]);
-                String key = createConfigurationKey(pid[0], pid[1]);
-                props.put(CONFIG_KEY, key);
-                if (cfg.getBundleLocation() != null) {
-                    cfg.setBundleLocation(null);
-                }
-                cfg.update(props);
-            }
-        }
-        for (ConfigFileInfo configFile : feature.getConfigurationFiles()) {
-            installConfigurationFile(configFile.getLocation(), configFile.getFinalname(), configFile.isOverride());
-        }
-    }
-
-    private String createConfigurationKey(String pid, String factoryPid) {
-        return factoryPid == null ? pid : pid + "-" + factoryPid;
-    }
-
-    private void installConfigurationFile(String fileLocation, String finalname, boolean override) throws IOException {
-    	String basePath = System.getProperty("karaf.base");
-    	
-    	if (finalname.contains("${")) {
-    		//remove any placeholder or variable part, this is not valid.
-    		int marker = finalname.indexOf("}");
-    		finalname = finalname.substring(marker+1);
-    	}
-    	
-    	finalname = basePath + File.separator + finalname;
-    	
-    	File file = new File(finalname); 
-    	if (file.exists()) {
-            if (!override) {
-                LOGGER.debug("Configuration file {} already exist, don't override it", finalname);
-                return;
-            } else {
-                LOGGER.info("Configuration file {} already exist, overriding it", finalname);
-            }
-    	} else {
-            LOGGER.info("Creating configuration file {}", finalname);
-        }
-
-        InputStream is = null;
-        FileOutputStream fop = null;
-        try {
-            is = new BufferedInputStream(new URL(fileLocation).openStream());
-
-            if (!file.exists()) {
-                File parentFile = file.getParentFile();
-                if (parentFile != null)
-                    parentFile.mkdirs();
-                file.createNewFile();
-            }
-
-            fop = new FileOutputStream(file);
-        
-            int bytesRead;
-            byte[] buffer = new byte[1024];
-            
-            while ((bytesRead = is.read(buffer)) != -1) {
-                fop.write(buffer, 0, bytesRead);
-            }
-        } catch (RuntimeException e) {
-            LOGGER.error(e.getMessage());
-            throw e;
-        } catch (MalformedURLException e) {
-        	LOGGER.error(e.getMessage());
-            throw e;
-		} finally {
-			if (is != null)
-				is.close();
-            if (fop != null) {
-			    fop.flush();
-			    fop.close();
-            }
-		}
-            
-    }
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/core/src/main/java/org/apache/karaf/features/internal/service/FeatureFinder.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/service/FeatureFinder.java b/features/core/src/main/java/org/apache/karaf/features/internal/service/FeatureFinder.java
deleted file mode 100644
index d6defe0..0000000
--- a/features/core/src/main/java/org/apache/karaf/features/internal/service/FeatureFinder.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * 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.karaf.features.internal.service;
-
-import java.net.URI;
-import java.util.Dictionary;
-import java.util.Enumeration;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Set;
-
-import org.osgi.service.cm.ConfigurationException;
-import org.osgi.service.cm.ManagedService;
-
-public class FeatureFinder implements ManagedService {
-
-    final Map<String, String> nameToArtifactMap = new HashMap<String, String>();
-
-    public String[] getNames() {
-        synchronized (nameToArtifactMap) {
-            Set<String> strings = nameToArtifactMap.keySet();
-            return strings.toArray(new String[strings.size()]);
-        }
-    }
-
-    public URI getUriFor(String name, String version) {
-        String coords;
-        synchronized (nameToArtifactMap) {
-            coords = nameToArtifactMap.get(name);
-        }
-        if (coords == null) {
-            return null;
-        }
-        Artifact artifact = new Artifact(coords);
-        return artifact.getMavenUrl(version);
-    }
-
-    @SuppressWarnings("rawtypes")
-    public void updated(Dictionary properties) throws ConfigurationException {
-        synchronized (nameToArtifactMap) {
-            if (properties != null) {
-                nameToArtifactMap.clear();
-                Enumeration keys = properties.keys();
-                while (keys.hasMoreElements()) {
-                    String key = (String) keys.nextElement();
-                    if (!"felix.fileinstall.filename".equals(key) && !"service.pid".equals(key)) {
-                        nameToArtifactMap.put(key, (String) properties.get(key));
-                    }
-                }
-            }
-        }
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/core/src/main/java/org/apache/karaf/features/internal/service/FeatureValidationUtil.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/service/FeatureValidationUtil.java b/features/core/src/main/java/org/apache/karaf/features/internal/service/FeatureValidationUtil.java
deleted file mode 100644
index 8fb161e..0000000
--- a/features/core/src/main/java/org/apache/karaf/features/internal/service/FeatureValidationUtil.java
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * 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.karaf.features.internal.service;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URI;
-import java.net.URLConnection;
-
-import javax.xml.XMLConstants;
-import javax.xml.namespace.QName;
-import javax.xml.parsers.DocumentBuilderFactory;
-import javax.xml.parsers.ParserConfigurationException;
-import javax.xml.transform.dom.DOMSource;
-import javax.xml.transform.stream.StreamSource;
-import javax.xml.validation.Schema;
-import javax.xml.validation.SchemaFactory;
-import javax.xml.validation.Validator;
-
-import org.apache.karaf.features.FeaturesNamespaces;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.w3c.dom.Document;
-import org.xml.sax.SAXException;
-
-/**
- * Utility class which fires XML Schema validation.
- */
-public class FeatureValidationUtil {
-
-    public static final QName FEATURES_0_0 = new QName("features");
-    public static final QName FEATURES_1_0 = new QName("http://karaf.apache.org/xmlns/features/v1.0.0", "features");
-    public static final QName FEATURES_1_1 = new QName("http://karaf.apache.org/xmlns/features/v1.1.0", "features");
-    public static final QName FEATURES_1_2 = new QName("http://karaf.apache.org/xmlns/features/v1.2.0", "features");
-    private static final Logger LOGGER = LoggerFactory.getLogger(FeatureValidationUtil.class);
-
-    /**
-     * Runs schema validation.
-     * 
-     * @param uri Uri to validate.
-     * @throws Exception When validation fails.
-     */
-    public static void validate(URI uri) throws Exception {
-        Document doc = load(uri);
-
-        QName name = new QName(doc.getDocumentElement().getNamespaceURI(), doc.getDocumentElement().getLocalName());
-
-        if (FeaturesNamespaces.FEATURES_0_0_0.equals(name)) {
-            LOGGER.warn("Old style feature file without namespace found (URI: {}). This format is deprecated and support for it will soon be removed", uri);
-            return;
-        } else if (FeaturesNamespaces.FEATURES_1_0_0.equals(name)) {
-            validate(doc, "/org/apache/karaf/features/karaf-features-1.0.0.xsd");
-        } else if (FeaturesNamespaces.FEATURES_1_1_0.equals(name)) {
-            validate(doc, "/org/apache/karaf/features/karaf-features-1.1.0.xsd");
-        } else if (FeaturesNamespaces.FEATURES_1_2_0.equals(name)) {
-            validate(doc, "/org/apache/karaf/features/karaf-features-1.2.0.xsd");
-        } else if (FeaturesNamespaces.FEATURES_1_3_0.equals(name)) {
-            validate(doc, "/org/apache/karaf/features/karaf-features-1.3.0.xsd");
-        }
-        else {
-            throw new IllegalArgumentException("Unrecognized root element: " + name);
-        }
-    }
-
-    private static Document load(URI uri) throws IOException, SAXException, ParserConfigurationException {
-        InputStream stream = null;
-        try {
-            URLConnection conn;
-            try {
-                conn = uri.toURL().openConnection();
-            } catch (IllegalArgumentException e) {
-                throw new IllegalArgumentException("invalid URI: " + uri, e);
-            }
-            conn.setDefaultUseCaches(false);
-            stream = conn.getInputStream();
-            // load document and check the root element for namespace declaration
-            DocumentBuilderFactory dFactory = DocumentBuilderFactory.newInstance();
-            dFactory.setNamespaceAware(true);
-            return dFactory.newDocumentBuilder().parse(stream);
-        } finally {
-            if (stream != null) {
-                stream.close();
-            }
-        }
-    }
-
-    private static void validate(Document doc, String schemaLocation) throws SAXException {
-        SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
-        // root element has namespace - we can use schema validation
-        Schema schema = factory.newSchema(new StreamSource(FeatureValidationUtil.class.getResourceAsStream(schemaLocation)));
-        // create schema by reading it from an XSD file:
-        Validator validator = schema.newValidator();
-        try {
-            validator.validate(new DOMSource(doc));
-        } catch (Exception e) {
-            throw new IllegalArgumentException("Unable to validate " + doc.getDocumentURI(), e);
-        }
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/core/src/main/java/org/apache/karaf/features/internal/service/FeaturesServiceImpl.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/service/FeaturesServiceImpl.java b/features/core/src/main/java/org/apache/karaf/features/internal/service/FeaturesServiceImpl.java
deleted file mode 100644
index 495f3f8..0000000
--- a/features/core/src/main/java/org/apache/karaf/features/internal/service/FeaturesServiceImpl.java
+++ /dev/null
@@ -1,1454 +0,0 @@
-/*
- * 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.karaf.features.internal.service;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URI;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.EnumSet;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.LinkedHashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.TreeMap;
-import java.util.TreeSet;
-import java.util.concurrent.Callable;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-
-import org.apache.felix.utils.version.VersionRange;
-import org.apache.felix.utils.version.VersionTable;
-import org.apache.karaf.features.BundleInfo;
-import org.apache.karaf.features.Feature;
-import org.apache.karaf.features.FeatureEvent;
-import org.apache.karaf.features.FeaturesListener;
-import org.apache.karaf.features.FeaturesService;
-import org.apache.karaf.features.Repository;
-import org.apache.karaf.features.RepositoryEvent;
-import org.apache.karaf.features.internal.deployment.DeploymentBuilder;
-import org.apache.karaf.features.internal.deployment.StreamProvider;
-import org.apache.karaf.features.internal.resolver.FeatureNamespace;
-import org.apache.karaf.features.internal.resolver.UriNamespace;
-import org.apache.karaf.features.internal.util.ChecksumUtils;
-import org.apache.karaf.features.internal.util.Macro;
-import org.apache.karaf.features.internal.util.MultiException;
-import org.apache.karaf.util.collections.CopyOnWriteArrayIdentityList;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.BundleException;
-import org.osgi.framework.Constants;
-import org.osgi.framework.FrameworkEvent;
-import org.osgi.framework.FrameworkListener;
-import org.osgi.framework.ServiceReference;
-import org.osgi.framework.Version;
-import org.osgi.framework.namespace.PackageNamespace;
-import org.osgi.framework.startlevel.BundleStartLevel;
-import org.osgi.framework.wiring.BundleCapability;
-import org.osgi.framework.wiring.BundleRequirement;
-import org.osgi.framework.wiring.BundleRevision;
-import org.osgi.framework.wiring.FrameworkWiring;
-import org.osgi.resource.Resource;
-import org.osgi.resource.Wire;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import static org.apache.felix.resolver.Util.getSymbolicName;
-import static org.apache.felix.resolver.Util.getVersion;
-
-/**
- *
- */
-public class FeaturesServiceImpl implements FeaturesService {
-
-    public static final String UPDATE_SNAPSHOTS_NONE = "none";
-    public static final String UPDATE_SNAPSHOTS_CRC = "crc";
-    public static final String UPDATE_SNAPSHOTS_ALWAYS = "always";
-    public static final String DEFAULT_UPDATE_SNAPSHOTS = UPDATE_SNAPSHOTS_CRC;
-
-    public static final String DEFAULT_FEATURE_RESOLUTION_RANGE = "${range;[====,====]}";
-    public static final String DEFAULT_BUNDLE_UPDATE_RANGE = "${range;[==,=+)}";
-
-    private static final Logger LOGGER = LoggerFactory.getLogger(FeaturesServiceImpl.class);
-    private static final String SNAPSHOT = "SNAPSHOT";
-    private static final String MAVEN = "mvn:";
-
-    /**
-     * Our bundle.
-     * We use it to check bundle operations affecting our own bundle.
-     */
-    private final Bundle bundle;
-
-    /**
-     * The system bundle context.
-     * For all bundles related operations, we use the system bundle context
-     * to allow this bundle to be stopped and still allow the deployment to
-     * take place.
-     */
-    private final BundleContext systemBundleContext;
-    /**
-     * Used to load and save the {@link State} of this service.
-     */
-    private final StateStorage storage;
-    private final FeatureFinder featureFinder;
-    private final EventAdminListener eventAdminListener;
-    private final FeatureConfigInstaller configInstaller;
-    private final String overrides;
-    /**
-     * Range to use when a version is specified on a feature dependency.
-     * The default is {@link FeaturesServiceImpl#DEFAULT_FEATURE_RESOLUTION_RANGE}
-     */
-    private final String featureResolutionRange;
-    /**
-     * Range to use when verifying if a bundle should be updated or
-     * new bundle installed.
-     * The default is {@link FeaturesServiceImpl#DEFAULT_BUNDLE_UPDATE_RANGE}
-     */
-    private final String bundleUpdateRange;
-    /**
-     * Use CRC to check snapshot bundles and update them if changed.
-     * Either:
-     *   - none : never update snapshots
-     *   - always : always update snapshots
-     *   - crc : use CRC to detect changes
-     */
-    private final String updateSnaphots;
-
-    private final List<FeaturesListener> listeners = new CopyOnWriteArrayIdentityList<FeaturesListener>();
-
-    // Synchronized on lock
-    private final Object lock = new Object();
-    private final State state = new State();
-    private final Map<String, Repository> repositoryCache = new HashMap<String, Repository>();
-    private Map<String, Map<String, Feature>> featureCache;
-
-
-    public FeaturesServiceImpl(Bundle bundle,
-                               BundleContext systemBundleContext,
-                               StateStorage storage,
-                               FeatureFinder featureFinder,
-                               EventAdminListener eventAdminListener,
-                               FeatureConfigInstaller configInstaller,
-                               String overrides,
-                               String featureResolutionRange,
-                               String bundleUpdateRange,
-                               String updateSnaphots) {
-        this.bundle = bundle;
-        this.systemBundleContext = systemBundleContext;
-        this.storage = storage;
-        this.featureFinder = featureFinder;
-        this.eventAdminListener = eventAdminListener;
-        this.configInstaller = configInstaller;
-        this.overrides = overrides;
-        this.featureResolutionRange = featureResolutionRange;
-        this.bundleUpdateRange = bundleUpdateRange;
-        this.updateSnaphots = updateSnaphots;
-        loadState();
-    }
-
-    //
-    // State support
-    //
-
-    protected void loadState() {
-        try {
-            synchronized (lock) {
-                storage.load(state);
-            }
-        } catch (IOException e) {
-            LOGGER.warn("Error loading FeaturesService state", e);
-        }
-    }
-
-    protected void saveState() {
-        try {
-            synchronized (lock) {
-                // Make sure we don't store bundle checksums if
-                // it has been disabled through configadmin
-                // so that we don't keep out-of-date checksums.
-                if (!UPDATE_SNAPSHOTS_CRC.equalsIgnoreCase(updateSnaphots)) {
-                    state.bundleChecksums.clear();
-                }
-                storage.save(state);
-            }
-        } catch (IOException e) {
-            LOGGER.warn("Error saving FeaturesService state", e);
-        }
-    }
-
-    boolean isBootDone() {
-        synchronized (lock) {
-            return state.bootDone.get();
-        }
-    }
-
-    void bootDone() {
-        synchronized (lock) {
-            state.bootDone.set(true);
-            saveState();
-        }
-    }
-
-    //
-    // Listeners support
-    //
-
-    public void registerListener(FeaturesListener listener) {
-        listeners.add(listener);
-        try {
-            Set<String> repositories = new TreeSet<String>();
-            Set<String> installedFeatures = new TreeSet<String>();
-            synchronized (lock) {
-                repositories.addAll(state.repositories);
-                installedFeatures.addAll(state.installedFeatures);
-            }
-            for (String uri : repositories) {
-                Repository repository = new RepositoryImpl(URI.create(uri));
-                listener.repositoryEvent(new RepositoryEvent(repository, RepositoryEvent.EventType.RepositoryAdded, true));
-            }
-            for (String id : installedFeatures) {
-                Feature feature = org.apache.karaf.features.internal.model.Feature.valueOf(id);
-                listener.featureEvent(new FeatureEvent(feature, FeatureEvent.EventType.FeatureInstalled, true));
-            }
-        } catch (Exception e) {
-            LOGGER.error("Error notifying listener about the current state", e);
-        }
-    }
-
-    public void unregisterListener(FeaturesListener listener) {
-        listeners.remove(listener);
-    }
-
-    protected void callListeners(FeatureEvent event) {
-        if (eventAdminListener != null) {
-            eventAdminListener.featureEvent(event);
-        }
-        for (FeaturesListener listener : listeners) {
-            listener.featureEvent(event);
-        }
-    }
-
-    protected void callListeners(RepositoryEvent event) {
-        if (eventAdminListener != null) {
-            eventAdminListener.repositoryEvent(event);
-        }
-        for (FeaturesListener listener : listeners) {
-            listener.repositoryEvent(event);
-        }
-    }
-
-    //
-    // Feature Finder support
-    //
-
-    @Override
-    public URI getRepositoryUriFor(String name, String version) {
-        return featureFinder.getUriFor(name, version);
-    }
-
-    @Override
-    public String[] getRepositoryNames() {
-        return featureFinder.getNames();
-    }
-
-
-    //
-    // Repositories support
-    //
-
-    public Repository loadRepository(URI uri) throws Exception {
-        // TODO: merge validation and loading by loading the DOM, validating, unmarshalling
-        FeatureValidationUtil.validate(uri);
-        RepositoryImpl repo = new RepositoryImpl(uri);
-        repo.load();
-        return repo;
-    }
-
-    @Override
-    public void validateRepository(URI uri) throws Exception {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public void addRepository(URI uri) throws Exception {
-        addRepository(uri, false);
-    }
-
-    @Override
-    public void addRepository(URI uri, boolean install) throws Exception {
-        if (install) {
-            // TODO: implement
-            throw new UnsupportedOperationException();
-        }
-        Repository repository = loadRepository(uri);
-        synchronized (lock) {
-            // Clean cache
-            repositoryCache.put(uri.toString(), repository);
-            featureCache = null;
-            // Add repo
-            if (!state.repositories.add(uri.toString())) {
-                return;
-            }
-            saveState();
-        }
-        callListeners(new RepositoryEvent(repository, RepositoryEvent.EventType.RepositoryAdded, false));
-    }
-
-    @Override
-    public void removeRepository(URI uri) throws Exception {
-        removeRepository(uri, true);
-    }
-
-    @Override
-    public void removeRepository(URI uri, boolean uninstall) throws Exception {
-        // TODO: check we don't have any feature installed from this repository
-        Repository repo;
-        synchronized (lock) {
-            // Remove repo
-            if (!state.repositories.remove(uri.toString())) {
-                return;
-            }
-            // Clean cache
-            featureCache = null;
-            repo = repositoryCache.get(uri.toString());
-            List<String> toRemove = new ArrayList<String>();
-            toRemove.add(uri.toString());
-            while (!toRemove.isEmpty()) {
-                Repository rep = repositoryCache.remove(toRemove.remove(0));
-                if (rep != null) {
-                    for (URI u : rep.getRepositories()) {
-                        toRemove.add(u.toString());
-                    }
-                }
-            }
-            saveState();
-        }
-        if (repo == null) {
-            repo = new RepositoryImpl(uri);
-        }
-        callListeners(new RepositoryEvent(repo, RepositoryEvent.EventType.RepositoryRemoved, false));
-    }
-
-    @Override
-    public void restoreRepository(URI uri) throws Exception {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public void refreshRepository(URI uri) throws Exception {
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public Repository[] listRepositories() throws Exception {
-        // Make sure the cache is loaded
-        getFeatures();
-        synchronized (lock) {
-            return repositoryCache.values().toArray(new Repository[repositoryCache.size()]);
-        }
-    }
-
-    @Override
-    public Repository[] listRequiredRepositories() throws Exception {
-        // Make sure the cache is loaded
-        getFeatures();
-        synchronized (lock) {
-            List<Repository> repos = new ArrayList<Repository>();
-            for (Map.Entry<String, Repository> entry : repositoryCache.entrySet()) {
-                if (state.repositories.contains(entry.getKey())) {
-                    repos.add(entry.getValue());
-                }
-            }
-            return repos.toArray(new Repository[repos.size()]);
-        }
-    }
-
-    @Override
-    public Repository getRepository(String name) throws Exception {
-        // Make sure the cache is loaded
-        getFeatures();
-        synchronized (lock) {
-            for (Repository repo : this.repositoryCache.values()) {
-                if (name.equals(repo.getName())) {
-                    return repo;
-                }
-            }
-            return null;
-        }
-    }
-
-    //
-    // Features support
-    //
-
-    public Feature getFeature(String name) throws Exception {
-        return getFeature(name, null);
-    }
-
-    public Feature getFeature(String name, String version) throws Exception {
-        Map<String, Feature> versions = getFeatures().get(name);
-        return getFeatureMatching(versions, version);
-    }
-
-    protected Feature getFeatureMatching(Map<String, Feature> versions, String version) {
-        if (version != null) {
-            version = version.trim();
-            if (version.equals(org.apache.karaf.features.internal.model.Feature.DEFAULT_VERSION)) {
-                version = "";
-            }
-        } else {
-            version = "";
-        }
-        if (versions == null || versions.isEmpty()) {
-            return null;
-        } else {
-            Feature feature = version.isEmpty() ? null : versions.get(version);
-            if (feature == null) {
-                // Compute version range. If an version has been given, assume exact range
-                VersionRange versionRange = version.isEmpty() ?
-                        new VersionRange(Version.emptyVersion) :
-                        new VersionRange(version, true, true);
-                Version latest = Version.emptyVersion;
-                for (String available : versions.keySet()) {
-                    Version availableVersion = VersionTable.getVersion(available);
-                    if (availableVersion.compareTo(latest) >= 0 && versionRange.contains(availableVersion)) {
-                        feature = versions.get(available);
-                        latest = availableVersion;
-                    }
-                }
-            }
-            return feature;
-        }
-    }
-
-    public Feature[] listFeatures() throws Exception {
-        Set<Feature> features = new HashSet<Feature>();
-        for (Map<String, Feature> featureWithDifferentVersion : getFeatures().values()) {
-            for (Feature f : featureWithDifferentVersion.values()) {
-                features.add(f);
-            }
-        }
-        return features.toArray(new Feature[features.size()]);
-    }
-
-    protected Map<String, Map<String, Feature>> getFeatures() throws Exception {
-        List<String> uris;
-        synchronized (lock) {
-            if (featureCache != null) {
-                return featureCache;
-            }
-            uris = new ArrayList<String>(state.repositories);
-        }
-        //the outer map's key is feature name, the inner map's key is feature version
-        Map<String, Map<String, Feature>> map = new HashMap<String, Map<String, Feature>>();
-        // Two phase load:
-        // * first load dependent repositories
-        List<String> toLoad = new ArrayList<String>(uris);
-        while (!toLoad.isEmpty()) {
-            String uri = toLoad.remove(0);
-            Repository repo;
-            synchronized (lock) {
-                repo = repositoryCache.get(uri);
-            }
-            if (repo == null) {
-                RepositoryImpl rep = new RepositoryImpl(URI.create(uri));
-                rep.load();
-                repo = rep;
-                synchronized (lock) {
-                    repositoryCache.put(uri, repo);
-                }
-            }
-            for (URI u : repo.getRepositories()) {
-                toLoad.add(u.toString());
-            }
-        }
-        List<Repository> repos;
-        synchronized (lock) {
-            repos = new ArrayList<Repository>(repositoryCache.values());
-        }
-        // * then load all features
-        for (Repository repo : repos) {
-            for (Feature f : repo.getFeatures()) {
-                if (map.get(f.getName()) == null) {
-                    Map<String, Feature> versionMap = new HashMap<String, Feature>();
-                    versionMap.put(f.getVersion(), f);
-                    map.put(f.getName(), versionMap);
-                } else {
-                    map.get(f.getName()).put(f.getVersion(), f);
-                }
-            }
-        }
-        synchronized (lock) {
-            if (uris.size() == state.repositories.size() &&
-                    state.repositories.containsAll(uris)) {
-                featureCache = map;
-            }
-        }
-        return map;
-    }
-
-    //
-    // Installed features
-    //
-
-    @Override
-    public Feature[] listInstalledFeatures() throws Exception {
-        Set<Feature> features = new HashSet<Feature>();
-        Map<String, Map<String, Feature>> allFeatures = getFeatures();
-        synchronized (lock) {
-            for (Map<String, Feature> featureWithDifferentVersion : allFeatures.values()) {
-                for (Feature f : featureWithDifferentVersion.values()) {
-                    if (isInstalled(f)) {
-                        features.add(f);
-                    }
-                }
-            }
-        }
-        return features.toArray(new Feature[features.size()]);
-    }
-
-    @Override
-    public Feature[] listRequiredFeatures() throws Exception {
-        Set<Feature> features = new HashSet<Feature>();
-        Map<String, Map<String, Feature>> allFeatures = getFeatures();
-        synchronized (lock) {
-            for (Map<String, Feature> featureWithDifferentVersion : allFeatures.values()) {
-                for (Feature f : featureWithDifferentVersion.values()) {
-                    if (isRequired(f)) {
-                        features.add(f);
-                    }
-                }
-            }
-        }
-        return features.toArray(new Feature[features.size()]);
-    }
-
-
-    @Override
-    public boolean isInstalled(Feature f) {
-        String id = normalize(f.getId());
-        synchronized (lock) {
-            return state.installedFeatures.contains(id);
-        }
-    }
-
-    @Override
-    public boolean isRequired(Feature f) {
-        String id = normalize(f.getId());
-        synchronized (lock) {
-            return state.features.contains(id);
-        }
-    }
-
-    //
-    // Installation and uninstallation of features
-    //
-
-    public void installFeature(String name) throws Exception {
-        installFeature(name, EnumSet.noneOf(Option.class));
-    }
-
-    public void installFeature(String name, String version) throws Exception {
-        installFeature(version != null ? name + "/" + version : name, EnumSet.noneOf(Option.class));
-    }
-
-    public void installFeature(String name, EnumSet<Option> options) throws Exception {
-        installFeatures(Collections.singleton(name), options);
-    }
-
-    public void installFeature(String name, String version, EnumSet<Option> options) throws Exception {
-        installFeature(version != null ? name + "/" + version : name, options);
-    }
-
-    public void installFeature(Feature feature, EnumSet<Option> options) throws Exception {
-        installFeature(feature.getId());
-    }
-
-    @Override
-    public void uninstallFeature(String name, String version) throws Exception {
-        uninstallFeature(version != null ? name + "/" + version : name);
-    }
-
-    @Override
-    public void uninstallFeature(String name, String version, EnumSet<Option> options) throws Exception {
-        uninstallFeature(version != null ? name + "/" + version : name, options);
-    }
-
-    @Override
-    public void uninstallFeature(String name) throws Exception {
-        uninstallFeature(name, EnumSet.noneOf(Option.class));
-    }
-
-    @Override
-    public void uninstallFeature(String name, EnumSet<Option> options) throws Exception {
-        uninstallFeatures(Collections.singleton(name), options);
-    }
-
-
-    //
-    //
-    //
-    //   RESOLUTION
-    //
-    //
-    //
-
-
-
-
-
-
-    public void installFeatures(Set<String> features, EnumSet<Option> options) throws Exception {
-        Set<String> required;
-        Set<String> installed;
-        Set<Long> managed;
-        synchronized (lock) {
-            required = new HashSet<String>(state.features);
-            installed = new HashSet<String>(state.installedFeatures);
-            managed = new HashSet<Long>(state.managedBundles);
-        }
-        List<String> featuresToAdd = new ArrayList<String>();
-        Map<String, Map<String, Feature>> featuresMap = getFeatures();
-        for (String feature : features) {
-            feature = normalize(feature);
-            String name = feature.substring(0, feature.indexOf("/"));
-            String version = feature.substring(feature.indexOf("/") + 1);
-            Feature f = getFeatureMatching(featuresMap.get(name), version);
-            if (f == null) {
-                if (!options.contains(Option.NoFailOnFeatureNotFound)) {
-                    throw new IllegalArgumentException("No matching features for " + feature);
-                }
-            } else {
-                featuresToAdd.add(normalize(f.getId()));
-            }
-        }
-        featuresToAdd = new ArrayList<String>(new LinkedHashSet<String>(featuresToAdd));
-        StringBuilder sb = new StringBuilder();
-        sb.append("Adding features: ");
-        for (int i = 0; i < featuresToAdd.size(); i++) {
-            if (i > 0) {
-                sb.append(", ");
-            }
-            sb.append(featuresToAdd.get(i));
-        }
-        print(sb.toString(), options.contains(Option.Verbose));
-        required.addAll(featuresToAdd);
-        doInstallFeaturesInThread(required, installed, managed, options);
-    }
-
-    public void uninstallFeatures(Set<String> features, EnumSet<Option> options) throws Exception {
-        Set<String> required;
-        Set<String> installed;
-        Set<Long> managed;
-        synchronized (lock) {
-            required = new HashSet<String>(state.features);
-            installed = new HashSet<String>(state.installedFeatures);
-            managed = new HashSet<Long>(state.managedBundles);
-        }
-        List<String> featuresToRemove = new ArrayList<String>();
-        for (String feature : new HashSet<String>(features)) {
-            List<String> toRemove = new ArrayList<String>();
-            feature = normalize(feature);
-            if (feature.endsWith("/0.0.0")) {
-                String nameSep = feature.substring(0, feature.indexOf("/") + 1);
-                for (String f : required) {
-                    if (normalize(f).startsWith(nameSep)) {
-                        toRemove.add(f);
-                    }
-                }
-            } else {
-                toRemove.add(feature);
-            }
-            toRemove.retainAll(required);
-            if (toRemove.isEmpty()) {
-                throw new IllegalArgumentException("Feature named '" + feature + "' is not installed");
-            } else if (toRemove.size() > 1) {
-                String name = feature.substring(0, feature.indexOf("/"));
-                StringBuilder sb = new StringBuilder();
-                sb.append("Feature named '").append(name).append("' has multiple versions installed (");
-                for (int i = 0; i < toRemove.size(); i++) {
-                    if (i > 0) {
-                        sb.append(", ");
-                    }
-                    sb.append(toRemove.get(i));
-                }
-                sb.append("). Please specify the version to uninstall.");
-                throw new IllegalArgumentException(sb.toString());
-            }
-            featuresToRemove.addAll(toRemove);
-        }
-        featuresToRemove = new ArrayList<String>(new LinkedHashSet<String>(featuresToRemove));
-        StringBuilder sb = new StringBuilder();
-        sb.append("Removing features: ");
-        for (int i = 0; i < featuresToRemove.size(); i++) {
-            if (i > 0) {
-                sb.append(", ");
-            }
-            sb.append(featuresToRemove.get(i));
-        }
-        print(sb.toString(), options.contains(Option.Verbose));
-        required.removeAll(featuresToRemove);
-        doInstallFeaturesInThread(required, installed, managed, options);
-    }
-
-    protected String normalize(String feature) {
-        if (!feature.contains("/")) {
-            feature += "/0.0.0";
-        }
-        int idx = feature.indexOf("/");
-        String name = feature.substring(0, idx);
-        String version = feature.substring(idx + 1);
-        return name + "/" + VersionTable.getVersion(version).toString();
-    }
-
-    /**
-     * Actual deployment needs to be done in a separate thread.
-     * The reason is that if the console is refreshed, the current thread which is running
-     * the command may be interrupted while waiting for the refresh to be done, leading
-     * to bundles not being started after the refresh.
-     */
-    public void doInstallFeaturesInThread(final Set<String> features,
-                                          final Set<String> installed,
-                                          final Set<Long> managed,
-                                          final EnumSet<Option> options) throws Exception {
-        ExecutorService executor = Executors.newCachedThreadPool();
-        try {
-            executor.submit(new Callable<Object>() {
-                @Override
-                public Object call() throws Exception {
-                    doInstallFeatures(features, installed, managed, options);
-                    return null;
-                }
-            }).get();
-        } catch (ExecutionException e) {
-            Throwable t = e.getCause();
-            if (t instanceof RuntimeException) {
-                throw ((RuntimeException) t);
-            } else if (t instanceof Error) {
-                throw ((Error) t);
-            } else if (t instanceof Exception) {
-                throw (Exception) t;
-            } else {
-                throw e;
-            }
-        } finally {
-            executor.shutdown();
-        }
-    }
-
-    public void doInstallFeatures(Set<String> features,    // all request features
-                                  Set<String> installed,   // installed features
-                                  Set<Long> managed,       // currently managed bundles
-                                  EnumSet<Option> options  // installation options
-                    ) throws Exception {
-
-        boolean noRefreshUnmanaged = options.contains(Option.NoAutoRefreshUnmanagedBundles);
-        boolean noRefreshManaged = options.contains(Option.NoAutoRefreshManagedBundles);
-        boolean noRefresh = options.contains(Option.NoAutoRefreshBundles);
-        boolean noStart = options.contains(Option.NoAutoStartBundles);
-        boolean verbose = options.contains(Option.Verbose);
-        boolean simulate = options.contains(Option.Simulate);
-
-        // Get a list of resolved and unmanaged bundles to use as capabilities during resolution
-        List<Resource> systemBundles = new ArrayList<Resource>();
-        Bundle[] bundles = systemBundleContext.getBundles();
-        for (Bundle bundle : bundles) {
-            if (bundle.getState() >= Bundle.RESOLVED && !managed.contains(bundle.getBundleId())) {
-                Resource res = bundle.adapt(BundleRevision.class);
-                systemBundles.add(res);
-            }
-        }
-        // Resolve
-        // TODO: requirements
-        // TODO: bundles
-        // TODO: regions: on isolated regions, we may need different resolution for each region
-        Set<String>  overrides    = Overrides.loadOverrides(this.overrides);
-        Repository[] repositories = listRepositories();
-        DeploymentBuilder builder = createDeploymentBuilder(repositories);
-        builder.setFeatureRange(featureResolutionRange);
-        builder.download(features,
-                         Collections.<String>emptySet(),
-                         Collections.<String>emptySet(),
-                         overrides,
-                         Collections.<String>emptySet());
-        Map<Resource, List<Wire>> resolution = builder.resolve(systemBundles, false);
-        Collection<Resource> allResources = resolution.keySet();
-        Map<String, StreamProvider> providers = builder.getProviders();
-
-        // Install conditionals
-        List<String> installedFeatureIds = getFeatureIds(allResources);
-        List<Feature> installedFeatures = getFeatures(repositories, installedFeatureIds);
-
-        //
-        // Compute list of installable resources (those with uris)
-        //
-        List<Resource> resources = getBundles(allResources);
-
-        // Compute information for each bundle
-        Map<String, BundleInfo> bundleInfos = new HashMap<String, BundleInfo>();
-        for (Feature feature : getFeatures(repositories, getFeatureIds(allResources))) {
-            for (BundleInfo bi : feature.getBundles()) {
-                BundleInfo oldBi = bundleInfos.get(bi.getLocation());
-                if (oldBi != null) {
-                    bi = mergeBundleInfo(bi, oldBi);
-                }
-                bundleInfos.put(bi.getLocation(), bi);
-            }
-        }
-
-        // TODO: handle bundleInfo.isStart()
-
-        // Get all resources that will be used to satisfy the old features set
-        Set<Resource> resourceLinkedToOldFeatures = new HashSet<Resource>();
-        if (noStart) {
-            for (Resource resource : resolution.keySet()) {
-                String name = FeatureNamespace.getName(resource);
-                if (name != null) {
-                    Version version = FeatureNamespace.getVersion(resource);
-                    String id = version != null ? name + "/" + version : name;
-                    if (installed.contains(id)) {
-                        addTransitive(resource, resourceLinkedToOldFeatures, resolution);
-                    }
-                }
-            }
-        }
-
-        //
-        // Compute deployment
-        //
-        Map<String, Long> bundleChecksums = new HashMap<String, Long>();
-        synchronized (lock) {
-            bundleChecksums.putAll(state.bundleChecksums);
-        }
-        Deployment deployment = computeDeployment(managed, bundles, providers, resources, bundleChecksums);
-
-        if (deployment.toDelete.isEmpty() &&
-                deployment.toUpdate.isEmpty() &&
-                deployment.toInstall.isEmpty()) {
-            print("No deployment change.", verbose);
-            return;
-        }
-        //
-        // Log deployment
-        //
-        logDeployment(deployment, verbose);
-
-        if (simulate) {
-            // TODO: it would be nice to print bundles that will be refreshed
-            // TODO: it could be done by checking the differences between
-            // TODO: the resolution result and the actual wiring state
-            return;
-        }
-
-        Set<Bundle> toRefresh = new HashSet<Bundle>();
-        Set<Bundle> toStart = new HashSet<Bundle>();
-
-        //
-        // Execute deployment
-        //
-
-        // TODO: handle update on the features service itself
-        if (deployment.toUpdate.containsKey(bundle) ||
-                deployment.toDelete.contains(bundle)) {
-
-            LOGGER.warn("Updating or uninstalling of the FeaturesService is not supported");
-            deployment.toUpdate.remove(bundle);
-            deployment.toDelete.remove(bundle);
-
-        }
-
-        //
-        // Perform bundle operations
-        //
-
-        // Stop bundles by chunks
-        Set<Bundle> toStop = new HashSet<Bundle>();
-        toStop.addAll(deployment.toUpdate.keySet());
-        toStop.addAll(deployment.toDelete);
-        removeFragmentsAndBundlesInState(toStop, Bundle.UNINSTALLED | Bundle.RESOLVED | Bundle.STOPPING);
-        if (!toStop.isEmpty()) {
-            print("Stopping bundles:", verbose);
-            while (!toStop.isEmpty()) {
-                List<Bundle> bs = getBundlesToStop(toStop);
-                for (Bundle bundle : bs) {
-                    print("  " + bundle.getSymbolicName() + " / " + bundle.getVersion(), verbose);
-                    bundle.stop(Bundle.STOP_TRANSIENT);
-                    toStop.remove(bundle);
-                }
-            }
-        }
-        if (!deployment.toDelete.isEmpty()) {
-            print("Uninstalling bundles:", verbose);
-            for (Bundle bundle : deployment.toDelete) {
-                print("  " + bundle.getSymbolicName() + " / " + bundle.getVersion(), verbose);
-                bundle.uninstall();
-                managed.remove(bundle.getBundleId());
-                toRefresh.add(bundle);
-            }
-        }
-        if (!deployment.toUpdate.isEmpty()) {
-            print("Updating bundles:", verbose);
-            for (Map.Entry<Bundle, Resource> entry : deployment.toUpdate.entrySet()) {
-                Bundle bundle = entry.getKey();
-                Resource resource = entry.getValue();
-                String uri = UriNamespace.getUri(resource);
-                print("  " + uri, verbose);
-                InputStream is = getBundleInputStream(resource, providers);
-                bundle.update(is);
-                toRefresh.add(bundle);
-                toStart.add(bundle);
-                BundleInfo bi = bundleInfos.get(uri);
-                if (bi != null && bi.getStartLevel() > 0) {
-                    bundle.adapt(BundleStartLevel.class).setStartLevel(bi.getStartLevel());
-                }
-                // TODO: handle region
-            }
-        }
-        if (!deployment.toInstall.isEmpty()) {
-            print("Installing bundles:", verbose);
-            for (Resource resource : deployment.toInstall) {
-                String uri = UriNamespace.getUri(resource);
-                print("  " + uri, verbose);
-                InputStream is = getBundleInputStream(resource, providers);
-                Bundle bundle = systemBundleContext.installBundle(uri, is);
-                managed.add(bundle.getBundleId());
-                if (!noStart || resourceLinkedToOldFeatures.contains(resource)) {
-                    toStart.add(bundle);
-                }
-                deployment.resToBnd.put(resource, bundle);
-                // save a checksum of installed snapshot bundle
-                if (UPDATE_SNAPSHOTS_CRC.equals(updateSnaphots)
-                        && isUpdateable(resource) && !deployment.newCheckums.containsKey(bundle.getLocation())) {
-                    deployment.newCheckums.put(bundle.getLocation(), ChecksumUtils.checksum(getBundleInputStream(resource, providers)));
-                }
-                BundleInfo bi = bundleInfos.get(uri);
-                if (bi != null && bi.getStartLevel() > 0) {
-                    bundle.adapt(BundleStartLevel.class).setStartLevel(bi.getStartLevel());
-                }
-                // TODO: handle region
-            }
-        }
-
-        //
-        // Update and save state
-        //
-        List<String> newFeatures = new ArrayList<String>();
-        synchronized (lock) {
-            List<String> allFeatures = new ArrayList<String>();
-            for (Resource resource : allResources) {
-                String name = FeatureNamespace.getName(resource);
-                if (name != null) {
-                    Version version = FeatureNamespace.getVersion(resource);
-                    String id = version != null ? name + "/" + version : name;
-                    allFeatures.add(id);
-                    if (!state.installedFeatures.contains(id)) {
-                        newFeatures.add(id);
-                    }
-                }
-            }
-            state.bundleChecksums.putAll(deployment.newCheckums);
-            state.features.clear();
-            state.features.addAll(features);
-            state.installedFeatures.clear();
-            state.installedFeatures.addAll(allFeatures);
-            state.managedBundles.clear();
-            state.managedBundles.addAll(managed);
-            saveState();
-        }
-
-        //
-        // Install configurations
-        //
-        if (configInstaller != null && !newFeatures.isEmpty()) {
-            for (Repository repository : repositories) {
-                for (Feature feature : repository.getFeatures()) {
-                    if (newFeatures.contains(feature.getId())) {
-                        configInstaller.installFeatureConfigs(feature);
-                    }
-                }
-            }
-        }
-
-        if (!noRefreshManaged) {
-            findBundlesWithOptionalPackagesToRefresh(toRefresh);
-            findBundlesWithFragmentsToRefresh(toRefresh);
-        }
-
-        if (noRefreshUnmanaged) {
-            Set<Bundle> newSet = new HashSet<Bundle>();
-            for (Bundle bundle : toRefresh) {
-                if (managed.contains(bundle.getBundleId())) {
-                    newSet.add(bundle);
-                }
-            }
-            toRefresh = newSet;
-        }
-
-        // TODO: remove this hack, but it avoids loading the class after the bundle is refreshed
-        RequirementSort sort = new RequirementSort();
-
-        if (!noRefresh) {
-            toStop = new HashSet<Bundle>();
-            toStop.addAll(toRefresh);
-            removeFragmentsAndBundlesInState(toStop, Bundle.UNINSTALLED | Bundle.RESOLVED | Bundle.STOPPING);
-            if (!toStop.isEmpty()) {
-                print("Stopping bundles:", verbose);
-                while (!toStop.isEmpty()) {
-                    List<Bundle> bs = getBundlesToStop(toStop);
-                    for (Bundle bundle : bs) {
-                        print("  " + bundle.getSymbolicName() + " / " + bundle.getVersion(), verbose);
-                        bundle.stop(Bundle.STOP_TRANSIENT);
-                        toStop.remove(bundle);
-                        toStart.add(bundle);
-                    }
-                }
-            }
-
-            if (!toRefresh.isEmpty()) {
-                print("Refreshing bundles:", verbose);
-                for (Bundle bundle : toRefresh) {
-                    print("  " + bundle.getSymbolicName() + " / " + bundle.getVersion(), verbose);
-                }
-                if (!toRefresh.isEmpty()) {
-                    refreshPackages(toRefresh);
-                }
-            }
-        }
-
-        // Compute bundles to start
-        removeFragmentsAndBundlesInState(toStart, Bundle.UNINSTALLED | Bundle.ACTIVE | Bundle.STARTING);
-        if (!toStart.isEmpty()) {
-            // Compute correct start order
-            List<Exception> exceptions = new ArrayList<Exception>();
-            print("Starting bundles:", verbose);
-            while (!toStart.isEmpty()) {
-                List<Bundle> bs = getBundlesToStart(toStart);
-                for (Bundle bundle : bs) {
-                    LOGGER.info("  " + bundle.getSymbolicName() + " / " + bundle.getVersion());
-                    try {
-                        bundle.start();
-                    } catch (BundleException e) {
-                        exceptions.add(e);
-                    }
-                    toStart.remove(bundle);
-                }
-            }
-            if (!exceptions.isEmpty()) {
-                throw new MultiException("Error restarting bundles", exceptions);
-            }
-        }
-
-        // TODO: call listeners for features added and removed
-
-        print("Done.", verbose);
-    }
-
-    private void addTransitive(Resource resource, Set<Resource> resources, Map<Resource, List<Wire>> resolution) {
-        if (resources.add(resource)) {
-            for (Wire wire : resolution.get(resource)) {
-                addTransitive(wire.getProvider(), resources, resolution);
-            }
-        }
-    }
-
-    protected BundleInfo mergeBundleInfo(BundleInfo bi, BundleInfo oldBi) {
-        // TODO: we need a proper merge strategy when a bundle
-        // TODO: comes from different features
-        return bi;
-    }
-
-    private void print(String message, boolean verbose) {
-        LOGGER.info(message);
-        if (verbose) {
-            System.out.println(message);
-        }
-    }
-
-    private void removeFragmentsAndBundlesInState(Collection<Bundle> bundles, int state) {
-        for (Bundle bundle : new ArrayList<Bundle>(bundles)) {
-            if ((bundle.getState() & state) != 0
-                     || bundle.getHeaders().get(Constants.FRAGMENT_HOST) != null) {
-                bundles.remove(bundle);
-            }
-        }
-    }
-
-    protected void logDeployment(Deployment deployment, boolean verbose) {
-        print("Changes to perform:", verbose);
-        if (!deployment.toDelete.isEmpty()) {
-            print("  Bundles to uninstall:", verbose);
-            for (Bundle bundle : deployment.toDelete) {
-                print("    " + bundle.getSymbolicName() + " / " + bundle.getVersion(), verbose);
-            }
-        }
-        if (!deployment.toUpdate.isEmpty()) {
-            print("  Bundles to update:", verbose);
-            for (Map.Entry<Bundle, Resource> entry : deployment.toUpdate.entrySet()) {
-                print("    " + entry.getKey().getSymbolicName() + " / " + entry.getKey().getVersion() + " with " + UriNamespace.getUri(entry.getValue()), verbose);
-            }
-        }
-        if (!deployment.toInstall.isEmpty()) {
-            print("  Bundles to install:", verbose);
-            for (Resource resource : deployment.toInstall) {
-                print("    " + UriNamespace.getUri(resource), verbose);
-            }
-        }
-    }
-
-    protected Deployment computeDeployment(
-                                Set<Long> managed,
-                                Bundle[] bundles,
-                                Map<String, StreamProvider> providers,
-                                List<Resource> resources,
-                                Map<String, Long> bundleChecksums) throws IOException {
-        Deployment deployment = new Deployment();
-
-        // TODO: regions
-        List<Resource> toDeploy = new ArrayList<Resource>(resources);
-
-        // First pass: go through all installed bundles and mark them
-        // as either to ignore or delete
-        for (Bundle bundle : bundles) {
-            if (bundle.getSymbolicName() != null && bundle.getBundleId() != 0) {
-                Resource resource = null;
-                for (Resource res : toDeploy) {
-                    if (bundle.getSymbolicName().equals(getSymbolicName(res))) {
-                        if (bundle.getVersion().equals(getVersion(res))) {
-                            resource = res;
-                            break;
-                        }
-                    }
-                }
-                // We found a matching bundle
-                if (resource != null) {
-                    // In case of snapshots, check if the snapshot is out of date
-                    // and flag it as to update
-                    if (managed.contains(bundle.getBundleId()) && isUpdateable(resource)) {
-                        // Always update snapshots
-                        if (UPDATE_SNAPSHOTS_ALWAYS.equalsIgnoreCase(updateSnaphots)) {
-                            LOGGER.debug("Update snapshot for " + bundle.getLocation());
-                            deployment.toUpdate.put(bundle, resource);
-                        }
-                        else if (UPDATE_SNAPSHOTS_CRC.equalsIgnoreCase(updateSnaphots)) {
-                            // if the checksum are different
-                            InputStream is = null;
-                            try {
-                                is = getBundleInputStream(resource, providers);
-                                long newCrc = ChecksumUtils.checksum(is);
-                                long oldCrc = bundleChecksums.containsKey(bundle.getLocation()) ? bundleChecksums.get(bundle.getLocation()) : 0l;
-                                if (newCrc != oldCrc) {
-                                    LOGGER.debug("New snapshot available for " + bundle.getLocation());
-                                    deployment.toUpdate.put(bundle, resource);
-                                    deployment.newCheckums.put(bundle.getLocation(), newCrc);
-                                }
-                            } finally {
-                                if (is != null) {
-                                    is.close();
-                                }
-                            }
-                        }
-                    }
-                    // We're done for this resource
-                    toDeploy.remove(resource);
-                    deployment.resToBnd.put(resource, bundle);
-                // There's no matching resource
-                // If the bundle is managed, we need to delete it
-                } else if (managed.contains(bundle.getBundleId())) {
-                    deployment.toDelete.add(bundle);
-                }
-            }
-        }
-
-        // Second pass on remaining resources
-        for (Resource resource : toDeploy) {
-            TreeMap<Version, Bundle> matching = new TreeMap<Version, Bundle>();
-            VersionRange range = new VersionRange(Macro.transform(bundleUpdateRange, getVersion(resource).toString()));
-            for (Bundle bundle : deployment.toDelete) {
-                if (bundle.getSymbolicName().equals(getSymbolicName(resource)) && range.contains(bundle.getVersion())) {
-                    matching.put(bundle.getVersion(), bundle);
-                }
-            }
-            if (!matching.isEmpty()) {
-                Bundle bundle = matching.lastEntry().getValue();
-                deployment.toUpdate.put(bundle, resource);
-                deployment.toDelete.remove(bundle);
-                deployment.resToBnd.put(resource, bundle);
-            } else {
-                deployment.toInstall.add(resource);
-            }
-        }
-        return deployment;
-    }
-
-    protected List<Resource> getBundles(Collection<Resource> allResources) {
-        Map<String, Resource> deploy = new TreeMap<String, Resource>();
-        for (Resource res : allResources) {
-            String uri = UriNamespace.getUri(res);
-            if (uri != null) {
-                deploy.put(uri, res);
-            }
-        }
-        return new ArrayList<Resource>(deploy.values());
-    }
-
-    protected List<Feature> getFeatures(Repository[] repositories, List<String> featureIds) throws Exception {
-        List<Feature> installedFeatures = new ArrayList<Feature>();
-        for (Repository repository : repositories) {
-            for (Feature feature : repository.getFeatures()) {
-                String id = feature.getName() + "/" + VersionTable.getVersion(feature.getVersion());
-                if (featureIds.contains(id)) {
-                    installedFeatures.add(feature);
-                }
-            }
-        }
-        return installedFeatures;
-    }
-
-    protected List<String> getFeatureIds(Collection<Resource> allResources) {
-        List<String> installedFeatureIds = new ArrayList<String>();
-        for (Resource resource : allResources) {
-            String name = FeatureNamespace.getName(resource);
-            if (name != null) {
-                Version version = FeatureNamespace.getVersion(resource);
-                String id = version != null ? name + "/" + version : name;
-                installedFeatureIds.add(id);
-            }
-        }
-        return installedFeatureIds;
-    }
-
-    protected DeploymentBuilder createDeploymentBuilder(Repository[] repositories) {
-        return new DeploymentBuilder(new SimpleDownloader(), Arrays.asList(repositories));
-    }
-
-
-    protected boolean isUpdateable(Resource resource) {
-        return (getVersion(resource).getQualifier().endsWith(SNAPSHOT) ||
-                UriNamespace.getUri(resource).contains(SNAPSHOT) ||
-                !UriNamespace.getUri(resource).contains(MAVEN));
-    }
-
-    protected List<Bundle> getBundlesToStart(Collection<Bundle> bundles) {
-        // TODO: make this pluggable ?
-        // TODO: honor respectStartLvlDuringFeatureStartup
-
-        // We hit FELIX-2949 if we don't use the correct order as Felix resolver isn't greedy.
-        // In order to minimize that, we make sure we resolve the bundles in the order they
-        // are given back by the resolution, meaning that all root bundles (i.e. those that were
-        // not flagged as dependencies in features) are started before the others.   This should
-        // make sure those important bundles are started first and minimize the problem.
-
-        // Restart the features service last, regardless of any other consideration
-        // so that we don't end up with the service trying to do stuff before we're done
-        boolean restart = bundles.remove(bundle);
-
-        List<BundleRevision> revs = new ArrayList<BundleRevision>();
-        for (Bundle bundle : bundles) {
-            revs.add(bundle.adapt(BundleRevision.class));
-        }
-        List<Bundle> sorted = new ArrayList<Bundle>();
-        for (BundleRevision rev : RequirementSort.sort(revs)) {
-            sorted.add(rev.getBundle());
-        }
-        if (restart) {
-            sorted.add(bundle);
-        }
-        return sorted;
-    }
-
-    protected List<Bundle> getBundlesToStop(Collection<Bundle> bundles) {
-        // TODO: make this pluggable ?
-        // TODO: honor respectStartLvlDuringFeatureUninstall
-
-        List<Bundle> bundlesToDestroy = new ArrayList<Bundle>();
-        for (Bundle bundle : bundles) {
-            ServiceReference[] references = bundle.getRegisteredServices();
-            int usage = 0;
-            if (references != null) {
-                for (ServiceReference reference : references) {
-                    usage += getServiceUsage(reference, bundles);
-                }
-            }
-            LOGGER.debug("Usage for bundle {} is {}", bundle, usage);
-            if (usage == 0) {
-                bundlesToDestroy.add(bundle);
-            }
-        }
-        if (!bundlesToDestroy.isEmpty()) {
-            Collections.sort(bundlesToDestroy, new Comparator<Bundle>() {
-                public int compare(Bundle b1, Bundle b2) {
-                    return (int) (b2.getLastModified() - b1.getLastModified());
-                }
-            });
-            LOGGER.debug("Selected bundles {} for destroy (no services in use)", bundlesToDestroy);
-        } else {
-            ServiceReference ref = null;
-            for (Bundle bundle : bundles) {
-                ServiceReference[] references = bundle.getRegisteredServices();
-                for (ServiceReference reference : references) {
-                    if (getServiceUsage(reference, bundles) == 0) {
-                        continue;
-                    }
-                    if (ref == null || reference.compareTo(ref) < 0) {
-                        LOGGER.debug("Currently selecting bundle {} for destroy (with reference {})", bundle, reference);
-                        ref = reference;
-                    }
-                }
-            }
-            if (ref != null) {
-                bundlesToDestroy.add(ref.getBundle());
-            }
-            LOGGER.debug("Selected bundle {} for destroy (lowest ranking service)", bundlesToDestroy);
-        }
-        return bundlesToDestroy;
-    }
-
-    private static int getServiceUsage(ServiceReference ref, Collection<Bundle> bundles) {
-        Bundle[] usingBundles = ref.getUsingBundles();
-        int nb = 0;
-        if (usingBundles != null) {
-            for (Bundle bundle : usingBundles) {
-                if (bundles.contains(bundle)) {
-                    nb++;
-                }
-            }
-        }
-        return nb;
-    }
-
-    protected InputStream getBundleInputStream(Resource resource, Map<String, StreamProvider> providers) throws IOException {
-        String uri = UriNamespace.getUri(resource);
-        if (uri == null) {
-            throw new IllegalStateException("Resource has no uri");
-        }
-        StreamProvider provider = providers.get(uri);
-        if (provider == null) {
-            throw new IllegalStateException("Resource " + uri + " has no StreamProvider");
-        }
-        return provider.open();
-    }
-
-    protected void findBundlesWithOptionalPackagesToRefresh(Set<Bundle> toRefresh) {
-        // First pass: include all bundles contained in these features
-        if (toRefresh.isEmpty()) {
-            return;
-        }
-        Set<Bundle> bundles = new HashSet<Bundle>(Arrays.asList(systemBundleContext.getBundles()));
-        bundles.removeAll(toRefresh);
-        if (bundles.isEmpty()) {
-            return;
-        }
-        // Second pass: for each bundle, check if there is any unresolved optional package that could be resolved
-        for (Bundle bundle : bundles) {
-            BundleRevision rev = bundle.adapt(BundleRevision.class);
-            boolean matches = false;
-            if (rev != null) {
-                for (BundleRequirement req : rev.getDeclaredRequirements(null)) {
-                    if (PackageNamespace.PACKAGE_NAMESPACE.equals(req.getNamespace())
-                            && PackageNamespace.RESOLUTION_OPTIONAL.equals(req.getDirectives().get(PackageNamespace.REQUIREMENT_RESOLUTION_DIRECTIVE))) {
-                        // This requirement is an optional import package
-                        for (Bundle provider : toRefresh) {
-                            BundleRevision providerRev = provider.adapt(BundleRevision.class);
-                            if (providerRev != null) {
-                                for (BundleCapability cap : providerRev.getDeclaredCapabilities(null)) {
-                                    if (req.matches(cap)) {
-                                        matches = true;
-                                        break;
-                                    }
-                                }
-                            }
-                            if (matches) {
-                                break;
-                            }
-                        }
-                    }
-                    if (matches) {
-                        break;
-                    }
-                }
-            }
-            if (matches) {
-                toRefresh.add(bundle);
-            }
-        }
-    }
-
-    protected void findBundlesWithFragmentsToRefresh(Set<Bundle> toRefresh) {
-        if (toRefresh.isEmpty()) {
-            return;
-        }
-        Set<Bundle> bundles = new HashSet<Bundle>(Arrays.asList(systemBundleContext.getBundles()));
-        bundles.removeAll(toRefresh);
-        if (bundles.isEmpty()) {
-            return;
-        }
-        for (Bundle bundle : new ArrayList<Bundle>(toRefresh)) {
-            BundleRevision rev = bundle.adapt(BundleRevision.class);
-            if (rev != null) {
-                for (BundleRequirement req : rev.getDeclaredRequirements(null)) {
-                    if (BundleRevision.HOST_NAMESPACE.equals(req.getNamespace())) {
-                        for (Bundle hostBundle : bundles) {
-                            if (!toRefresh.contains(hostBundle)) {
-                                BundleRevision hostRev = hostBundle.adapt(BundleRevision.class);
-                                if (hostRev != null) {
-                                    for (BundleCapability cap : hostRev.getDeclaredCapabilities(null)) {
-                                        if (req.matches(cap)) {
-                                            toRefresh.add(hostBundle);
-                                        }
-                                    }
-                                }
-                            }
-                        }
-                    }
-                }
-            }
-        }
-    }
-
-    protected void refreshPackages(Collection<Bundle> bundles) throws InterruptedException {
-        final CountDownLatch latch = new CountDownLatch(1);
-        FrameworkWiring fw = systemBundleContext.getBundle().adapt(FrameworkWiring.class);
-        fw.refreshBundles(bundles, new FrameworkListener() {
-            @Override
-            public void frameworkEvent(FrameworkEvent event) {
-                if (event.getType() == FrameworkEvent.ERROR) {
-                    LOGGER.error("Framework error", event.getThrowable());
-                }
-                latch.countDown();
-            }
-        });
-        latch.await();
-    }
-
-
-    static class Deployment {
-        Map<String, Long> newCheckums = new HashMap<String, Long>();
-        Map<Resource, Bundle> resToBnd = new HashMap<Resource, Bundle>();
-        List<Resource> toInstall = new ArrayList<Resource>();
-        List<Bundle> toDelete = new ArrayList<Bundle>();
-        Map<Bundle, Resource> toUpdate = new HashMap<Bundle, Resource>();
-    }
-
-}


[20/59] [abbrv] [KARAF-2852] Merge bundle/command into bundle/core

Posted by gn...@apache.org.
http://git-wip-us.apache.org/repos/asf/karaf/blob/d0180939/bundle/command/src/main/java/org/apache/karaf/bundle/command/Refresh.java
----------------------------------------------------------------------
diff --git a/bundle/command/src/main/java/org/apache/karaf/bundle/command/Refresh.java b/bundle/command/src/main/java/org/apache/karaf/bundle/command/Refresh.java
deleted file mode 100644
index 53adaeb..0000000
--- a/bundle/command/src/main/java/org/apache/karaf/bundle/command/Refresh.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * 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.karaf.bundle.command;
-
-import java.util.List;
-
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.wiring.FrameworkWiring;
-
-@Command(scope = "bundle", name = "refresh", description = "Refresh bundles.")
-@Service
-public class Refresh extends BundlesCommandWithConfirmation {
-    
-    public Refresh() {
-        this.defaultAllBundles = false;
-    }
-
-    protected void doExecute(List<Bundle> bundles) throws Exception {
-        FrameworkWiring wiring = bundleContext.getBundle(0).adapt(FrameworkWiring.class);
-        wiring.refreshBundles(bundles == null || bundles.isEmpty() ? null : bundles);
-    }
-
-    @Override
-    protected void executeOnBundle(Bundle bundle) throws Exception {
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d0180939/bundle/command/src/main/java/org/apache/karaf/bundle/command/Requirements.java
----------------------------------------------------------------------
diff --git a/bundle/command/src/main/java/org/apache/karaf/bundle/command/Requirements.java b/bundle/command/src/main/java/org/apache/karaf/bundle/command/Requirements.java
deleted file mode 100644
index c87d4d4..0000000
--- a/bundle/command/src/main/java/org/apache/karaf/bundle/command/Requirements.java
+++ /dev/null
@@ -1,177 +0,0 @@
-/*
- * 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.karaf.bundle.command;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.regex.Pattern;
-
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Option;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.apache.karaf.shell.support.ShellUtil;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.Constants;
-import org.osgi.framework.ServiceReference;
-import org.osgi.framework.wiring.BundleCapability;
-import org.osgi.framework.wiring.BundleRequirement;
-import org.osgi.framework.wiring.BundleWire;
-import org.osgi.framework.wiring.BundleWiring;
-
-@Command(scope = "bundle", name = "requirements", description = "Displays OSGi requirements of a given bundles.")
-@Service
-public class Requirements extends BundlesCommand {
-
-    public static final String NONSTANDARD_SERVICE_NAMESPACE = "service";
-
-    private static final String EMPTY_MESSAGE = "[EMPTY]";
-    private static final String UNRESOLVED_MESSAGE = "[UNRESOLVED]";
-
-    @Option(name = "--namespace")
-    String namespace = "*";
-    
-    public Requirements() {
-        super(true);
-    }
-
-    @Override
-    protected void doExecute(List<Bundle> bundles) throws Exception {
-        boolean separatorNeeded = false;
-        Pattern ns = Pattern.compile(namespace.replaceAll("\\.", "\\\\.").replaceAll("\\*", ".*"));
-        for (Bundle b : bundles) {
-            if (separatorNeeded) {
-                System.out.println("");
-            }
-
-            // Print out any matching generic requirements.
-            BundleWiring wiring = b.adapt(BundleWiring.class);
-            if (wiring != null) {
-                String title = b + " requires:";
-                System.out.println(title);
-                System.out.println(ShellUtil.getUnderlineString(title));
-                boolean matches = printMatchingRequirements(wiring, ns);
-
-                // Handle service requirements separately, since they aren't part
-                // of the generic model in OSGi.
-                if (matchNamespace(ns, NONSTANDARD_SERVICE_NAMESPACE)) {
-                    matches |= printServiceRequirements(b);
-                }
-
-                // If there were no requirements for the specified namespace,
-                // then say so.
-                if (!matches) {
-                    System.out.println(namespace + " " + EMPTY_MESSAGE);
-                }
-            } else {
-                System.out.println("Bundle " + b.getBundleId() + " is not resolved.");
-            }
-
-            separatorNeeded = true;
-        }
-    }
-
-    private static boolean printMatchingRequirements(BundleWiring wiring, Pattern namespace) {
-        List<BundleWire> wires = wiring.getRequiredWires(null);
-        Map<BundleRequirement, List<BundleWire>> aggregateReqs = aggregateRequirements(namespace, wires);
-        List<BundleRequirement> allReqs = wiring.getRequirements(null);
-        boolean matches = false;
-        for (BundleRequirement req : allReqs) {
-            if (matchNamespace(namespace, req.getNamespace())) {
-                matches = true;
-                List<BundleWire> providers = aggregateReqs.get(req);
-                if (providers != null) {
-                    System.out.println(req.getNamespace() + "; "
-                                    + req.getDirectives().get(Constants.FILTER_DIRECTIVE) + " resolved by:");
-                    for (BundleWire wire : providers) {
-                        String msg;
-                        Object keyAttr = wire.getCapability().getAttributes().get(wire.getCapability().getNamespace());
-                        if (keyAttr != null) {
-                            msg = wire.getCapability().getNamespace() + "; "
-                                    + keyAttr + " " + getVersionFromCapability(wire.getCapability());
-                        } else {
-                            msg = wire.getCapability().toString();
-                        }
-                        msg = "   " + msg + " from " + wire.getProviderWiring().getBundle();
-                        System.out.println(msg);
-                    }
-                } else {
-                    System.out.println(req.getNamespace() + "; "
-                                    + req.getDirectives().get(Constants.FILTER_DIRECTIVE) + " " + UNRESOLVED_MESSAGE);
-                }
-            }
-        }
-        return matches;
-    }
-
-    private static Map<BundleRequirement, List<BundleWire>> aggregateRequirements(
-            Pattern namespace, List<BundleWire> wires) {
-        // Aggregate matching capabilities.
-        Map<BundleRequirement, List<BundleWire>> map = new HashMap<BundleRequirement, List<BundleWire>>();
-        for (BundleWire wire : wires) {
-            if (matchNamespace(namespace, wire.getRequirement().getNamespace())) {
-                List<BundleWire> providers = map.get(wire.getRequirement());
-                if (providers == null) {
-                    providers = new ArrayList<BundleWire>();
-                    map.put(wire.getRequirement(), providers);
-                }
-                providers.add(wire);
-            }
-        }
-        return map;
-    }
-
-    static boolean printServiceRequirements(Bundle b) {
-        boolean matches = false;
-
-        try {
-            ServiceReference<?>[] refs = b.getServicesInUse();
-
-            if ((refs != null) && (refs.length > 0)) {
-                matches = true;
-                // Print properties for each service.
-                for (ServiceReference<?> ref : refs) {
-                    // Print object class with "namespace".
-                    System.out.println(
-                            NONSTANDARD_SERVICE_NAMESPACE
-                                    + "; "
-                                    + ShellUtil.getValueString(ref.getProperty("objectClass"))
-                                    + " provided by:");
-                    System.out.println("   " + ref.getBundle());
-                }
-            }
-        } catch (Exception ex) {
-            System.err.println(ex.toString());
-        }
-
-        return matches;
-    }
-
-    private static String getVersionFromCapability(BundleCapability c) {
-        Object o = c.getAttributes().get(Constants.VERSION_ATTRIBUTE);
-        if (o == null) {
-            o = c.getAttributes().get(Constants.BUNDLE_VERSION_ATTRIBUTE);
-        }
-        return (o == null) ? "" : o.toString();
-    }
-
-    private static boolean matchNamespace(Pattern namespace, String actual) {
-        return namespace.matcher(actual).matches();
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d0180939/bundle/command/src/main/java/org/apache/karaf/bundle/command/Resolve.java
----------------------------------------------------------------------
diff --git a/bundle/command/src/main/java/org/apache/karaf/bundle/command/Resolve.java b/bundle/command/src/main/java/org/apache/karaf/bundle/command/Resolve.java
deleted file mode 100644
index 720f118..0000000
--- a/bundle/command/src/main/java/org/apache/karaf/bundle/command/Resolve.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * 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.karaf.bundle.command;
-
-import java.util.List;
-
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.wiring.FrameworkWiring;
-
-@Command(scope = "bundle", name = "resolve", description = "Resolve bundles.")
-@Service
-public class Resolve extends BundlesCommand {
-
-    public Resolve() {
-        super(true);
-    }
-
-    protected void doExecute(List<Bundle> bundles) throws Exception {
-        FrameworkWiring wiring = bundleContext.getBundle(0).adapt(FrameworkWiring.class);
-        wiring.resolveBundles(bundles == null || bundles.isEmpty() ? null : bundles);
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d0180939/bundle/command/src/main/java/org/apache/karaf/bundle/command/Restart.java
----------------------------------------------------------------------
diff --git a/bundle/command/src/main/java/org/apache/karaf/bundle/command/Restart.java b/bundle/command/src/main/java/org/apache/karaf/bundle/command/Restart.java
deleted file mode 100644
index 95d5dfe..0000000
--- a/bundle/command/src/main/java/org/apache/karaf/bundle/command/Restart.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * 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.karaf.bundle.command;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.apache.karaf.shell.support.MultiException;
-import org.osgi.framework.Bundle;
-
-@Command(scope = "bundle", name = "restart", description = "Restarts bundles.")
-@Service
-public class Restart extends BundlesCommandWithConfirmation {
-    
-    public Restart() {
-        errorMessage = "Error restarting bundle";
-    }
-
-    protected void doExecute(List<Bundle> bundles) throws Exception {
-        if (bundles.isEmpty()) {
-            System.err.println("No bundles specified.");
-            return;
-        }
-        List<Exception> exceptions = new ArrayList<Exception>();
-        for (Bundle bundle : bundles) {
-            try {
-                bundle.stop();
-            } catch (Exception e) {
-                exceptions.add(new Exception("Unable to stop bundle " + bundle.getBundleId() + ": " + e.getMessage(), e));
-            }
-        }
-        for (Bundle bundle : bundles) {
-            try {
-                bundle.start();
-            } catch (Exception e) {
-                exceptions.add(new Exception("Unable to start bundle " + bundle.getBundleId() + ": " + e.getMessage(), e));
-            }
-        }
-        MultiException.throwIf("Error restarting bundles", exceptions);
-    }
-
-    @Override
-    protected void executeOnBundle(Bundle bundle) throws Exception {
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d0180939/bundle/command/src/main/java/org/apache/karaf/bundle/command/ShowBundleTree.java
----------------------------------------------------------------------
diff --git a/bundle/command/src/main/java/org/apache/karaf/bundle/command/ShowBundleTree.java b/bundle/command/src/main/java/org/apache/karaf/bundle/command/ShowBundleTree.java
deleted file mode 100644
index a83ce39..0000000
--- a/bundle/command/src/main/java/org/apache/karaf/bundle/command/ShowBundleTree.java
+++ /dev/null
@@ -1,245 +0,0 @@
-/*
- * 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.karaf.bundle.command;
-
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import org.apache.felix.utils.manifest.Clause;
-import org.apache.felix.utils.manifest.Parser;
-import org.apache.felix.utils.version.VersionRange;
-import org.apache.felix.utils.version.VersionTable;
-import org.apache.karaf.bundle.command.bundletree.Node;
-import org.apache.karaf.bundle.command.bundletree.Tree;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.Constants;
-import org.osgi.framework.wiring.BundleCapability;
-import org.osgi.framework.wiring.BundleRevision;
-import org.osgi.framework.wiring.BundleRevisions;
-import org.osgi.framework.wiring.BundleWire;
-import org.osgi.framework.wiring.BundleWiring;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import static java.lang.String.format;
-
-/**
- * Command for showing the full tree of bundles that have been used to resolve
- * a given bundle.
- */
-@Command(scope = "bundle", name = "tree-show", description = "Shows the tree of bundles based on the wiring information.")
-@Service
-public class ShowBundleTree extends BundleCommand {
-
-    private static final Logger LOGGER = LoggerFactory.getLogger(ShowBundleTree.class);
-    private Tree<Bundle> tree;
-
-    public ShowBundleTree() {
-        super(false);
-    }
-
-    @Override
-    protected void doExecute(Bundle bundle) throws Exception {
-        long start = System.currentTimeMillis();
-        // let's do the real work here
-        printHeader(bundle);
-        tree = new Tree<Bundle>(bundle);
-        createTree(bundle);
-        printTree(tree);
-        printDuplicatePackages(tree);
-        LOGGER.debug(format("Dependency tree calculated in %d ms",
-                            System.currentTimeMillis() - start));
-    }
-    
-    /**
-     * Return a String representation of a bundle state
-     */
-    private String getState(Bundle bundle) {
-        switch (bundle.getState()) {
-            case Bundle.UNINSTALLED : return "UNINSTALLED";
-            case Bundle.INSTALLED : return "INSTALLED";
-            case Bundle.RESOLVED: return "RESOLVED";
-            case Bundle.STARTING : return "STARTING";
-            case Bundle.STOPPING : return "STOPPING";
-            case Bundle.ACTIVE : return "ACTIVE";
-            default : return "UNKNOWN";
-        }
-    }
-
-    /*
-     * Print the header
-     */
-    private void printHeader(Bundle bundle) {
-        System.out.printf("Bundle %s [%s] is currently %s%n",
-                bundle.getSymbolicName(),
-                bundle.getBundleId(),
-                getState(bundle));
-    }
-
-    /*
-     * Print the dependency tree
-     */
-    private void printTree(Tree<Bundle> tree) {
-        System.out.printf("%n");
-        tree.write(System.out, new Tree.Converter<Bundle>() {
-
-            public String toString(Node<Bundle> node) {
-                return String.format("%s [%s]",
-                                     node.getValue().getSymbolicName(),
-                                     node.getValue().getBundleId());
-            }
-        });
-    }
-
-    /*
-     * Check for bundles in the tree exporting the same package
-     * as a possible cause for 'Unresolved constraint...' on a uses-conflict
-     */
-    private void printDuplicatePackages(Tree<Bundle> tree) {
-        Set<Bundle> bundles = tree.flatten();
-        Map<String, Set<Bundle>> exports = new HashMap<String, Set<Bundle>>();
-
-        for (Bundle bundle : bundles) {
-            for (BundleRevision revision : bundle.adapt(BundleRevisions.class).getRevisions()) {
-                BundleWiring wiring = revision.getWiring();
-                if (wiring != null) {
-                    List<BundleWire> wires = wiring.getProvidedWires(BundleRevision.PACKAGE_NAMESPACE);
-                    if (wires != null) {
-                        for (BundleWire wire : wires) {
-                            String name = wire.getCapability().getAttributes().get(BundleRevision.PACKAGE_NAMESPACE).toString();
-                            if (exports.get(name) == null) {
-                                exports.put(name, new HashSet<Bundle>());
-                            }
-                            exports.get(name).add(bundle);
-                        }
-                    }
-                }
-            }
-        }
-
-        for (String pkg : exports.keySet()) {
-            if (exports.get(pkg).size() > 1) {
-                System.out.printf("%n");
-                System.out.printf("WARNING: multiple bundles are exporting package %s%n", pkg);
-                for (Bundle bundle : exports.get(pkg)) {
-                    System.out.printf("- %s%n", bundle);
-                }
-            }
-        }
-    }
-
-    /*
-     * Creates the bundle tree
-     */
-    protected void createTree(Bundle bundle) {
-        if (bundle.getState() >= Bundle.RESOLVED) {
-            createNode(tree);
-        } else {
-            createNodesForImports(tree, bundle);
-            System.out.print("\nWarning: the below tree is a rough approximation of a possible resolution");
-        }
-    }
-
-    /*
-     * Creates nodes for the imports of the bundle (instead of reporting wiring information
-     */
-    private void createNodesForImports(Node<Bundle> node, Bundle bundle) {
-        Clause[] imports = Parser.parseHeader(bundle.getHeaders().get("Import-Package"));
-        Clause[] exports = Parser.parseHeader(bundle.getHeaders().get("Export-Package"));
-        for (Clause i : imports) {
-            boolean exported = false;
-            for (Clause e : exports) {
-                if (e.getName().equals(i.getName())) {
-                    exported = true;
-                    break;
-                }
-            }
-            if (!exported) {
-                createNodeForImport(node, bundle, i);
-            }
-        }
-    }
-
-    /*
-     * Create a child node for a given import (by finding a matching export in the currently installed bundles)
-     */
-    private void createNodeForImport(Node<Bundle> node, Bundle bundle, Clause i) {
-        VersionRange range = VersionRange.parseVersionRange(i.getAttribute(Constants.VERSION_ATTRIBUTE));
-        boolean foundMatch = false;
-        for (Bundle b : bundleContext.getBundles()) {
-            BundleWiring wiring = b.adapt(BundleWiring.class);
-            if (wiring != null) {
-                List<BundleCapability> caps = wiring.getCapabilities(BundleRevision.PACKAGE_NAMESPACE);
-                if (caps != null) {
-                    for (BundleCapability cap : caps) {
-                        String n = getAttribute(cap, BundleRevision.PACKAGE_NAMESPACE);
-                        String v = getAttribute(cap, Constants.VERSION_ATTRIBUTE);
-                        if (i.getName().equals(n) && range.contains(VersionTable.getVersion(v))) {
-                            boolean existing = tree.flatten().contains(b);
-                            System.out.printf("- import %s: resolved using %s%n", i, b);
-                            foundMatch = true;
-                            if (!node.hasChild(b)) {
-                                Node<Bundle> child = node.addChild(b);
-                                if (!existing) {
-                                    createNode(child);
-                                }
-                            }
-                        }
-                    }
-                }
-            }
-        }
-        if (!foundMatch) {
-            System.out.printf("- import %s: WARNING - unable to find matching export%n", i);
-        }
-    }
-
-    private String getAttribute(BundleCapability capability, String name) {
-        Object o = capability.getAttributes().get(name);
-        return o != null ? o.toString() : null;
-    }
-
-    /*
-    * Creates a node in the bundle tree
-    */
-    private void createNode(Node<Bundle> node) {
-        Bundle bundle = node.getValue();
-        Collection<Bundle> exporters = new HashSet<Bundle>();
-        exporters.addAll(bundleService.getWiredBundles(bundle).values());
-
-        for (Bundle exporter : exporters) {
-            if (node.hasAncestor(exporter)) {                
-                LOGGER.debug(format("Skipping %s (already exists in the current branch)", exporter));
-            } else {
-                boolean existing = tree.flatten().contains(exporter);
-                LOGGER.debug(format("Adding %s as a dependency for %s", exporter, bundle));
-                Node<Bundle> child = node.addChild(exporter);
-                if (existing) {
-                    LOGGER.debug(format("Skipping children of %s (already exists in another branch)", exporter));
-                } else {
-                    createNode(child);
-                }
-            }
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d0180939/bundle/command/src/main/java/org/apache/karaf/bundle/command/Start.java
----------------------------------------------------------------------
diff --git a/bundle/command/src/main/java/org/apache/karaf/bundle/command/Start.java b/bundle/command/src/main/java/org/apache/karaf/bundle/command/Start.java
deleted file mode 100644
index 48e90fa..0000000
--- a/bundle/command/src/main/java/org/apache/karaf/bundle/command/Start.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * 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.karaf.bundle.command;
-
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.osgi.framework.Bundle;
-
-@Command(scope = "bundle", name = "start", description = "Starts bundles.")
-@Service
-public class Start extends BundlesCommandWithConfirmation {
-
-    @Override
-    protected void executeOnBundle(Bundle bundle) throws Exception {
-        bundle.start();
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d0180939/bundle/command/src/main/java/org/apache/karaf/bundle/command/StartLevel.java
----------------------------------------------------------------------
diff --git a/bundle/command/src/main/java/org/apache/karaf/bundle/command/StartLevel.java b/bundle/command/src/main/java/org/apache/karaf/bundle/command/StartLevel.java
deleted file mode 100644
index 30bec0f..0000000
--- a/bundle/command/src/main/java/org/apache/karaf/bundle/command/StartLevel.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * 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.karaf.bundle.command;
-
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.console.Session;
-import org.apache.karaf.shell.api.action.lifecycle.Reference;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.startlevel.BundleStartLevel;
-
-@Command(scope = "bundle", name = "start-level", description = "Gets or sets the start level of a bundle.")
-@Service
-public class StartLevel extends BundleCommandWithConfirmation {
-
-    @Argument(index = 1, name = "startLevel", description = "The bundle's new start level", required = false, multiValued = false)
-    Integer level;
-
-    @Reference
-    Session session;
-
-    protected void doExecute(Bundle bundle) throws Exception {
-        // Get package instance service.
-        BundleStartLevel bsl = bundle.adapt(BundleStartLevel.class);
-        if (bsl == null) {
-            System.out.println("StartLevel service is unavailable.");
-            return;
-        }
-        if (level == null) {
-            System.out.println("Level " + bsl.getStartLevel());
-        }
-        else if ((level < 50) && (bsl.getStartLevel() > 50) && !force){
-            for (;;) {
-                String msg = "You are about to designate bundle as a system bundle.  Do you wish to continue (yes/no): ";
-                String str = session.readLine(msg, null);
-                if ("yes".equalsIgnoreCase(str)) {
-                    bsl.setStartLevel(level);
-                    break;
-                } else if ("no".equalsIgnoreCase(str)) {
-                    break;
-                }
-            }
-
-        } else {
-            bsl.setStartLevel(level);
-        }
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d0180939/bundle/command/src/main/java/org/apache/karaf/bundle/command/Stop.java
----------------------------------------------------------------------
diff --git a/bundle/command/src/main/java/org/apache/karaf/bundle/command/Stop.java b/bundle/command/src/main/java/org/apache/karaf/bundle/command/Stop.java
deleted file mode 100644
index 0b0fed2..0000000
--- a/bundle/command/src/main/java/org/apache/karaf/bundle/command/Stop.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * 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.karaf.bundle.command;
-
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Option;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.osgi.framework.Bundle;
-
-@Command(scope = "bundle", name = "stop", description = "Stop bundles.")
-@Service
-public class Stop extends BundlesCommandWithConfirmation {
-    
-	@Option(name = "-t", aliases={"--transient"}, description="Keep the bundle as auto-start", required = false, multiValued = false)
-	boolean transientStop;
-	
-    public Stop() {
-        this.errorMessage = "Unable to stop bundle";
-    }
-
-    @Override
-    protected void executeOnBundle(Bundle bundle) throws Exception {
-    	if (transientStop) {
-    		bundle.stop(Bundle.STOP_TRANSIENT);
-    	} else {
-    		bundle.stop();
-    	}
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d0180939/bundle/command/src/main/java/org/apache/karaf/bundle/command/Uninstall.java
----------------------------------------------------------------------
diff --git a/bundle/command/src/main/java/org/apache/karaf/bundle/command/Uninstall.java b/bundle/command/src/main/java/org/apache/karaf/bundle/command/Uninstall.java
deleted file mode 100644
index 67b5b14..0000000
--- a/bundle/command/src/main/java/org/apache/karaf/bundle/command/Uninstall.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * 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.karaf.bundle.command;
-
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.osgi.framework.Bundle;
-
-@Command(scope = "bundle", name = "uninstall", description = "Uninstall bundles.")
-@Service
-public class Uninstall extends BundlesCommandWithConfirmation {
-    
-    public Uninstall() {
-        this.errorMessage = "Unable to uninstall bundle";
-    }
-
-    @Override
-    protected void executeOnBundle(Bundle bundle) throws Exception {
-        bundle.uninstall();
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d0180939/bundle/command/src/main/java/org/apache/karaf/bundle/command/Update.java
----------------------------------------------------------------------
diff --git a/bundle/command/src/main/java/org/apache/karaf/bundle/command/Update.java b/bundle/command/src/main/java/org/apache/karaf/bundle/command/Update.java
deleted file mode 100644
index 71ae74d..0000000
--- a/bundle/command/src/main/java/org/apache/karaf/bundle/command/Update.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * 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.karaf.bundle.command;
-
-import java.io.InputStream;
-import java.net.URL;
-
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.osgi.framework.Bundle;
-
-@Command(scope = "bundle", name = "update", description = "Update bundle.")
-@Service
-public class Update extends BundleCommandWithConfirmation {
-
-    @Argument(index = 1, name = "location", description = "The bundles update location", required = false, multiValued = false)
-    String location;
-
-    protected void doExecute(Bundle bundle) throws Exception {
-        InputStream is = null;
-        if (location != null) {
-            try {
-                is = new URL(location).openStream();
-                bundle.update(is);
-            } finally {
-                is.close();
-            }
-        } else {
-            bundle.update();
-        }
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d0180939/bundle/command/src/main/java/org/apache/karaf/bundle/command/Watch.java
----------------------------------------------------------------------
diff --git a/bundle/command/src/main/java/org/apache/karaf/bundle/command/Watch.java b/bundle/command/src/main/java/org/apache/karaf/bundle/command/Watch.java
deleted file mode 100644
index 9203f59..0000000
--- a/bundle/command/src/main/java/org/apache/karaf/bundle/command/Watch.java
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * 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.karaf.bundle.command;
-
-import java.util.List;
-
-import org.apache.karaf.bundle.core.BundleWatcher;
-import org.apache.karaf.shell.api.action.Action;
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Option;
-import org.apache.karaf.shell.api.action.lifecycle.Reference;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.Constants;
-
-@Command(scope = "bundle", name = "watch", description = "Watches and updates bundles", detailedDescription = "Watches the local maven repo for changes in snapshot jars and redploys changed jars")
-@Service
-public class Watch implements Action {
-
-    @Argument(index = 0, name = "urls", description = "The bundle IDs or URLs", required = false, multiValued = true)
-    List<String> urls;
-
-    @Option(name = "-i", aliases = {}, description = "Watch interval", required = false, multiValued = false)
-    private long interval;
-
-    @Option(name = "--start", description = "Starts watching the selected bundles", required = false, multiValued = false)
-    protected boolean start;
-
-    @Option(name = "--stop", description = "Stops watching all bundles", required = false, multiValued = false)
-    protected boolean stop;
-
-    @Option(name = "--remove", description = "Removes bundles from the watch list", required = false, multiValued = false)
-    protected boolean remove;
-
-    @Option(name = "--list", description = "Displays the watch list", required = false, multiValued = false)
-    protected boolean list;
-
-    @Reference
-    private BundleWatcher bundleWatcher;
-
-    public void setBundleWatcher(BundleWatcher bundleWatcher) {
-        this.bundleWatcher = bundleWatcher;
-    }
-
-    @Override
-    public Object execute() throws Exception {
-        if (start && stop) {
-            System.err.println("Please use only one of --start and --stop options!");
-            return null;
-        }
-
-        if (interval > 0) {
-            System.out.println("Setting watch interval to " + interval + " ms");
-            bundleWatcher.setInterval(interval);
-        }
-        if (stop) {
-            System.out.println("Stopping watch");
-            bundleWatcher.stop();
-        }
-        if (urls != null) {
-            if (remove) {
-                for (String url : urls) {
-                    bundleWatcher.remove(url);
-                }
-            } else {
-                for (String url : urls) {
-                    bundleWatcher.add(url);
-                }
-            }
-        }
-        if (start) {
-            System.out.println("Starting watch");
-            bundleWatcher.start();
-        }
-
-        if (list) { //List the watched bundles.
-            String format = "%-40s %6s %-80s";
-            System.out.println(String.format(format, "URL", "ID", "Bundle Name"));
-            for (String url : bundleWatcher.getWatchURLs()) {
-
-                List<Bundle> bundleList = bundleWatcher.getBundlesByURL(url);
-                if (bundleList != null && bundleList.size() > 0) {
-                    for (Bundle bundle : bundleList) {
-                        System.out.println(String.format(format, url, bundle.getBundleId(), bundle.getHeaders().get(Constants.BUNDLE_NAME)));
-                    }
-                } else {
-                    System.out.println(String.format(format, url, "", ""));
-                }
-            }
-        } else {
-            List<String> urls = bundleWatcher.getWatchURLs();
-            if (urls != null && urls.size()>0) {
-                System.out.println("Watched URLs/IDs: ");
-                for (String url : bundleWatcher.getWatchURLs()) {
-                    System.out.println(url);
-                }
-            } else {
-                System.out.println("No watched URLs/IDs");
-            }
-        }
-
-        return null;
-    }
-
-}
-
-
-
-
-
-
-
-

http://git-wip-us.apache.org/repos/asf/karaf/blob/d0180939/bundle/command/src/main/java/org/apache/karaf/bundle/command/bundletree/Node.java
----------------------------------------------------------------------
diff --git a/bundle/command/src/main/java/org/apache/karaf/bundle/command/bundletree/Node.java b/bundle/command/src/main/java/org/apache/karaf/bundle/command/bundletree/Node.java
deleted file mode 100644
index fe4dc2a..0000000
--- a/bundle/command/src/main/java/org/apache/karaf/bundle/command/bundletree/Node.java
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
- * 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.karaf.bundle.command.bundletree;
-
-import java.io.PrintWriter;
-import java.util.HashSet;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Set;
-
-/**
- * Represents a node in a {@link Tree}
- */
-public class Node<T> {
-    
-    private final T value;
-    private Node<T> parent;
-    private List<Node<T>> children = new LinkedList<Node<T>>();
-
-    /**
-     * Creates a new node. Only meant for wrapper use,
-     * new nodes should be added using the {@link #addChild(Object)} method
-     *
-     * @param value the node value
-     */
-    protected Node(T value) {
-        super();
-        this.value = value;
-    }
-
-    /**
-     * Creates a new node. Only meant for wrapper use,
-     * new nodes should be added using the {@link #addChild(Object)} method
-     *
-     * @param value the node value
-     */
-    protected Node(T value, Node<T> parent) {
-        this(value);
-        this.parent = parent;
-    }
-
-    /**
-     * Access the node's value
-     */
-    public T getValue() {
-        return value;
-    }
-
-    /**
-     * Access the node's child nodes
-     */
-    public List<Node<T>> getChildren() {
-        return children;
-    }
-
-    /**
-     * Adds a child to this node
-     *
-     * @param value the child's value
-     * @return the child node
-     */
-    public Node<T> addChild(T value) {
-        Node<T> node = new Node<T>(value, this);
-        children.add(node);
-        return node;
-    }
-
-    /**
-     * Give a set of values in the tree.
-     *
-     * @return
-     */
-    public Set<T> flatten() {
-        Set<T> result = new HashSet<T>();
-        result.add(getValue());
-        for (Node<T> child : getChildren()) {
-            result.addAll(child.flatten());
-        }
-        return result;
-    }
-
-    /**
-     * Check if the node has an ancestor that represents the given value
-     *
-     * @param value the node value
-     * @return <code>true</code> it there's an ancestor that represents the value
-     */
-    public boolean hasAncestor(T value) {
-        if (parent == null) {
-            return false;
-        } else {
-            return value.equals(parent.value) || parent.hasAncestor(value);
-        }
-    }
-    
-    public boolean hasChild(T value) {
-        for (Node<T> child : getChildren()) {
-            if (value.equals(child.getValue())) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    /*
-     * Write this node to the PrintWriter.  It should be indented one step
-     * further for every element in the indents array.  If an element in the
-     * array is <code>true</code>, there should be a | to connect to the next
-     * sibling.
-     */
-    protected void write(PrintWriter writer, Tree.Converter<T> converter, boolean... indents) {
-        for (boolean indent : indents) {
-            writer.printf("%-3s", indent ? "|" : "");
-        }
-        writer.printf("+- %s%n", converter.toString(this));
-        for (Node<T> child : getChildren()) {
-            child.write(writer, converter, concat(indents, hasNextSibling()));
-        }
-    }
-
-    /*
-     * Is this node the last child node for its parent
-     * or is there a next sibling?
-     */
-    private boolean hasNextSibling() {
-        if (parent == null) {
-            return false;
-        } else {
-            return parent.getChildren().size() > 1
-                    && parent.getChildren().indexOf(this) < parent.getChildren().size() - 1;
-        }
-    }
-
-    /*
-     * Add an element to the end of the array
-     */
-    private boolean[] concat(boolean[] array, boolean element) {
-        boolean[] result = new boolean[array.length + 1];
-        for (int i = 0 ; i < array.length ; i++) {
-            result[i] = array[i];
-        }
-        result[array.length] = element;
-        return result;
-    }
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d0180939/bundle/command/src/main/java/org/apache/karaf/bundle/command/bundletree/Tree.java
----------------------------------------------------------------------
diff --git a/bundle/command/src/main/java/org/apache/karaf/bundle/command/bundletree/Tree.java b/bundle/command/src/main/java/org/apache/karaf/bundle/command/bundletree/Tree.java
deleted file mode 100644
index 7a7b64e..0000000
--- a/bundle/command/src/main/java/org/apache/karaf/bundle/command/bundletree/Tree.java
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * 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.karaf.bundle.command.bundletree;
-
-import java.io.PrintStream;
-import java.io.PrintWriter;
-
-/**
- * Represents a tree that can be written to the console.
- *
- * The output will look like this:
- * <pre>
- * root
- * +- child1
- * |  +- grandchild
- * +- child2
- * </pre>
- */
-public class Tree<T> extends Node<T> {
-
-    /**
-     * Creates a new tree with the given root node
-     *
-     * @param root the root node
-     */
-    public Tree(T root) {
-        super(root);
-    }
-
-    /**
-     * Write the tree to a PrintStream, using the default toString() method to output the node values
-     *
-     * @param stream
-     */
-    public void write(PrintStream stream) {
-        write(new PrintWriter(stream));
-    }
-
-    /**
-     * Write the tree to a PrintStream, using the provided converter to output the node values
-     *
-     * @param stream
-     * @param converter
-     */
-    public void write(PrintStream stream, Converter<T> converter) {
-        write(new PrintWriter(stream), converter);
-    }
-
-    /**
-     * Write the tree to a PrintWriter, using the default toString() method to output the node values
-     *
-     * @param writer
-     */
-    public void write(PrintWriter writer) {
-        write(writer, new Converter() {
-            public String toString(Node node) {
-                return node.getValue().toString();
-            }
-        });
-    }
-
-    /**
-     * Write the tree to a PrintWriter, using the provided converter to output the node values
-     *
-     * @param writer
-     * @param converter
-     */
-    public void write(PrintWriter writer, Converter<T> converter) {
-        writer.printf("%s%n", converter.toString(this));
-        for (Node<T> child : getChildren()) {
-            child.write(writer, converter);
-        }
-        writer.flush();
-    }
-
-    /**
-     * Interface to convert node values to string
-     *
-     * @param <T> the object type for the node value
-     */
-    public static interface Converter<T> {
-
-        public String toString(Node<T> node);
-
-    }
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d0180939/bundle/command/src/main/java/org/apache/karaf/bundle/command/wikidoc/AnsiPrintingWikiVisitor.java
----------------------------------------------------------------------
diff --git a/bundle/command/src/main/java/org/apache/karaf/bundle/command/wikidoc/AnsiPrintingWikiVisitor.java b/bundle/command/src/main/java/org/apache/karaf/bundle/command/wikidoc/AnsiPrintingWikiVisitor.java
deleted file mode 100644
index 077cfef..0000000
--- a/bundle/command/src/main/java/org/apache/karaf/bundle/command/wikidoc/AnsiPrintingWikiVisitor.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * 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.karaf.bundle.command.wikidoc;
-
-import java.io.PrintStream;
-
-import org.fusesource.jansi.Ansi;
-import org.fusesource.jansi.Ansi.Attribute;
-import org.fusesource.jansi.Ansi.Color;
-
-/**
- * Translates the Wiki tags to Ansi escape sequences to display them on the console
- */
-public class AnsiPrintingWikiVisitor implements WikiVisitor {
-	private PrintStream out;
-	
-	public AnsiPrintingWikiVisitor(PrintStream out) {
-		this.out = out;
-	}
-	
-	@Override
-	public void heading(int level, String header) {
-		this.out.print(Ansi.ansi().a(Attribute.INTENSITY_BOLD).a(header)
-				.a(Attribute.INTENSITY_BOLD_OFF).toString());
-	}
-	
-	@Override
-	public void link(String target, String title) {
-		this.out.print(Ansi.ansi().fg(Color.YELLOW) 
-				.a(target).fg(Color.DEFAULT));
-	}
-
-	@Override
-	public void enumeration(String text) {
-		this.out.print(Ansi.ansi().a(" * ").fg(Color.CYAN).a(text).fg(Color.DEFAULT).a(" "));
-	}
-
-	@Override
-	public void text(String text) {
-		this.out.print(text);
-	}
-
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d0180939/bundle/command/src/main/java/org/apache/karaf/bundle/command/wikidoc/WikiParser.java
----------------------------------------------------------------------
diff --git a/bundle/command/src/main/java/org/apache/karaf/bundle/command/wikidoc/WikiParser.java b/bundle/command/src/main/java/org/apache/karaf/bundle/command/wikidoc/WikiParser.java
deleted file mode 100644
index 8ec3d5b..0000000
--- a/bundle/command/src/main/java/org/apache/karaf/bundle/command/wikidoc/WikiParser.java
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * 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.karaf.bundle.command.wikidoc;
-
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.Reader;
-import java.util.StringTokenizer;
-
-/**
- * Parses wiki syntax from a reader and calls a Wikivisitor with the 
- * tokens it finds
- */
-public class WikiParser {
-	WikiVisitor visitor;
-	
-	public WikiParser(WikiVisitor visitor) {
-		this.visitor = visitor;
-	}
-
-	public void parse(String line) {
-		StringTokenizer tokenizer = new StringTokenizer(line , "[h*", true);
-		while (tokenizer.hasMoreTokens()) {
-			String token = tokenizer.nextToken();
-			if ("[".equals(token)) {
-				parseLink(tokenizer);
-			} else if ("h".equals(token)) {
-				parseHeading(tokenizer);
-			} else if ("*".equals(token)){
-				parseEnumeration(tokenizer);
-			} else {
-				visitor.text(token);
-			}
-		}
-	}
-	
-	private void parseEnumeration(StringTokenizer tokenizer) {
-		String text = tokenizer.nextToken("-\n");
-		visitor.enumeration(text.trim());
-	}
-
-	private void parseHeading(StringTokenizer tokenizer) {
-		String level = tokenizer.nextToken("123456789");
-		if (!level.matches("[123456789]")) {
-			visitor.text("h" + level);
-			return;
-		}
-		String dot = tokenizer.nextToken(".\n");
-		if (!".".equals(dot)) {
-			visitor.text("h" + level + dot);
-			return;
-		}
-		String heading = tokenizer.hasMoreTokens() ? tokenizer.nextToken("\n") : "";
-		visitor.heading(new Integer(level), heading.trim());
-	}
-
-	private void parseLink(StringTokenizer tokenizer) {
-		String token = tokenizer.nextToken("]");
-		visitor.link(token, "");
-		tokenizer.nextToken();
-	}
-
-	public void parse(Reader reader) throws IOException {
-		BufferedReader br = new BufferedReader(reader);
-		String line;
-		while ((line = br.readLine()) != null) {
-			parse(line);
-			visitor.text("\n");
-		}
-	}
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d0180939/bundle/command/src/main/java/org/apache/karaf/bundle/command/wikidoc/WikiVisitor.java
----------------------------------------------------------------------
diff --git a/bundle/command/src/main/java/org/apache/karaf/bundle/command/wikidoc/WikiVisitor.java b/bundle/command/src/main/java/org/apache/karaf/bundle/command/wikidoc/WikiVisitor.java
deleted file mode 100644
index b4a5fb3..0000000
--- a/bundle/command/src/main/java/org/apache/karaf/bundle/command/wikidoc/WikiVisitor.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * 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.karaf.bundle.command.wikidoc;
-
-/**
- * Will be used by WikiParser to call the respective handler when it recognizes the tag 
- */
-public interface WikiVisitor {
-
-	void link(String target, String title);
-	void heading(int level, String title);
-	void enumeration(String text);
-	void text(String text);
-
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/karaf/blob/d0180939/bundle/command/src/main/resources/OSGI-INF/bundle.info
----------------------------------------------------------------------
diff --git a/bundle/command/src/main/resources/OSGI-INF/bundle.info b/bundle/command/src/main/resources/OSGI-INF/bundle.info
deleted file mode 100644
index af2c24f..0000000
--- a/bundle/command/src/main/resources/OSGI-INF/bundle.info
+++ /dev/null
@@ -1,32 +0,0 @@
-h1. Synopsis
-
-${project.name}
-
-${project.description}
-
-Maven URL:
-   [mvn:${project.groupId}/${project.artifactId}/${project.version}]
-
-h1. Description
-
-This bundle provides the low level OSGi shell commands.
-
-The following commands are available:
-* bundle:classes - Displays a list of classes contained in the bundle
-* bundle:find-class - Locates a specified class in any deployed bundle
-* bundle:headers - Display OSGi headers of a given bundle.
-* bundle:info - Display detailed information of a given bundle.
-* bundle:install - Install one or more bundles.
-* bundle:list - List all installed bundles.
-* bundle:refresh - Refresh bundles.
-* bundle:resolve - Resolve bundles.
-* bundle:restart - Stop and restart bundles.
-* bundle:start - Starts bundles.
-* bundlestart-level - Get or set the start level of a bundle.
-* bundle:stop - Stop bundles.
-* bundle:uninstall - Uninstall bundles.
-* bundle:update - Update a bundle.
-
-h1. See also
-
-Commands and Using the console sections of the Karaf User Guide

http://git-wip-us.apache.org/repos/asf/karaf/blob/d0180939/bundle/command/src/test/java/org/apache/karaf/bundle/command/ListServicesTest.java
----------------------------------------------------------------------
diff --git a/bundle/command/src/test/java/org/apache/karaf/bundle/command/ListServicesTest.java b/bundle/command/src/test/java/org/apache/karaf/bundle/command/ListServicesTest.java
deleted file mode 100644
index 876f605..0000000
--- a/bundle/command/src/test/java/org/apache/karaf/bundle/command/ListServicesTest.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * 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.karaf.bundle.command;
-
-import java.util.Arrays;
-import java.util.Collections;
-
-import org.apache.karaf.bundle.core.internal.BundleServiceImpl;
-import org.junit.Test;
-import org.osgi.framework.BundleContext;
-
-public class ListServicesTest {
-
-    private ListBundleServices listServices;
-
-    @SuppressWarnings("unchecked")
-    public ListServicesTest() {
-        listServices = new ListBundleServices();
-        BundleContext bundleContext = new TestBundleFactory().createBundleContext();
-        listServices.setBundleContext(bundleContext);
-        listServices.setBundleService(new BundleServiceImpl(bundleContext));
-    }
-    
-    @Test
-    public void listAllShort() throws Exception {
-        System.out.println("listAllShort");
-        listServices.execute();
-    }
-
-    
-    @Test
-    public void listAllLong() throws Exception {
-        System.out.println("listAllLong");
-        listServices.ids = Arrays.asList(new String[]{"1", "2"});
-        listServices.execute();
-    }
-
-    @Test
-    public void listAllLongServiceUse() throws Exception {
-        System.out.println("listAllLongServicesUse");
-        listServices.ids = Arrays.asList(new String[]{"1", "2"});
-        listServices.inUse = true;
-        listServices.execute();
-    }
-
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d0180939/bundle/command/src/test/java/org/apache/karaf/bundle/command/TestBundleFactory.java
----------------------------------------------------------------------
diff --git a/bundle/command/src/test/java/org/apache/karaf/bundle/command/TestBundleFactory.java b/bundle/command/src/test/java/org/apache/karaf/bundle/command/TestBundleFactory.java
deleted file mode 100644
index 27e4a63..0000000
--- a/bundle/command/src/test/java/org/apache/karaf/bundle/command/TestBundleFactory.java
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * 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.karaf.bundle.command;
-
-import static org.easymock.EasyMock.createMock;
-import static org.easymock.EasyMock.expect;
-import static org.easymock.EasyMock.replay;
-
-import java.util.Collections;
-import java.util.Dictionary;
-import java.util.Hashtable;
-
-import org.osgi.framework.Bundle;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.Constants;
-import org.osgi.framework.ServiceReference;
-
-public class TestBundleFactory {
-    ServiceReference<?> createServiceRef(Object ... keyProp) {
-        ServiceReference<?> serviceRef = createMock(ServiceReference.class);
-        if (keyProp.length % 2 != 0) {
-            throw new IllegalArgumentException("");
-        }
-        Hashtable<String, Object> keyPropMap = new Hashtable<String, Object>();
-        int c = 0;
-        while (c < keyProp.length) {
-            String key = (String)keyProp[c++];
-            Object value = (Object)keyProp[c++];
-            keyPropMap.put(key, value);
-            expect(serviceRef.getProperty(key)).andReturn(value).anyTimes();
-        }
-        expect(serviceRef.getPropertyKeys()).andReturn(Collections.list(keyPropMap.keys()).toArray(new String[]{})).anyTimes();
-        return serviceRef;
-    }
-    
-    Bundle createBundle(long id, String name) {
-        Bundle bundle = createMock(Bundle.class);
-        expect(bundle.getBundleId()).andReturn(id).anyTimes();
-        Dictionary<String, String> headers = new Hashtable<String, String>();
-        headers.put(Constants.BUNDLE_NAME, name);
-        expect(bundle.getHeaders()).andReturn(headers).anyTimes();
-        return bundle;
-    }
-    
-    private Bundle[] createBundles() {
-        Bundle bundle1 = createBundle(1, "Bundle A");
-        Bundle bundle2 = createBundle(2, "Bundle B");
-        Bundle bundle3 = createBundle(3, "Bundle C");
-
-        ServiceReference<?> ref1 = createServiceRef(Constants.OBJECTCLASS, new String[]{"org.example.MyService"},
-            "key1", "value1");
-        ServiceReference<?> ref2 = createServiceRef(Constants.OBJECTCLASS, new String[]{"org.example.OtherService"}, "key2", 1);
-
-        addRegisteredServices(bundle1, ref1, ref2);
-        addRegisteredServices(bundle2, ref2);
-        expect(bundle3.getRegisteredServices()).andReturn(null).anyTimes();
-
-        expect(bundle1.getServicesInUse()).andReturn(null).anyTimes();
-        addUsedServices(bundle2, ref1);
-        addUsedServices(bundle3, ref1, ref2);
-        
-        expect(ref1.getUsingBundles()).andReturn(new Bundle[]{bundle2, bundle3}).anyTimes();
-        expect(ref2.getUsingBundles()).andReturn(new Bundle[]{bundle3}).anyTimes();
-
-        replay(bundle1, bundle2, bundle3, ref1, ref2);
-        return new Bundle[] { bundle1, bundle2, bundle3 };
-    }
-    
-    private void addUsedServices(Bundle bundle, ServiceReference<?> ... refs) {
-        expect(bundle.getServicesInUse()).andReturn(refs).anyTimes();
-    }
-    
-    private void addRegisteredServices(Bundle bundle, ServiceReference<?> ... refs) {
-        expect(bundle.getRegisteredServices()).andReturn(refs).anyTimes();
-        for (ServiceReference<?> ref : refs) {
-            expect(ref.getBundle()).andReturn(bundle);
-        }
-    }
-
-    public BundleContext createBundleContext() {
-        BundleContext bundleContext = createMock(BundleContext.class);
-        Bundle[] bundles = createBundles();
-        expect(bundleContext.getBundles()).andReturn(bundles).anyTimes();
-        expect(bundleContext.getBundle(0)).andReturn(null).anyTimes();
-        expect(bundleContext.getBundle(1)).andReturn(bundles[0]).anyTimes();
-        expect(bundleContext.getBundle(2)).andReturn(bundles[1]).anyTimes();
-        replay(bundleContext);
-        return bundleContext;
-    }
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d0180939/bundle/command/src/test/java/org/apache/karaf/bundle/command/bundletree/TreeTest.java
----------------------------------------------------------------------
diff --git a/bundle/command/src/test/java/org/apache/karaf/bundle/command/bundletree/TreeTest.java b/bundle/command/src/test/java/org/apache/karaf/bundle/command/bundletree/TreeTest.java
deleted file mode 100644
index df0d7d6..0000000
--- a/bundle/command/src/test/java/org/apache/karaf/bundle/command/bundletree/TreeTest.java
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * 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.karaf.bundle.command.bundletree;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.io.StringReader;
-import java.io.StringWriter;
-import java.util.Set;
-
-import org.apache.karaf.bundle.command.bundletree.Node;
-import org.apache.karaf.bundle.command.bundletree.Tree;
-import org.junit.Test;
-
-/**
- * Test cases for {@link org.apache.karaf.shell.dev.util.Tree}
- * and {@link org.apache.karaf.shell.dev.util.Node}
- */
-public class TreeTest {
-
-    @Test
-    public void writeTreeWithOneChild() throws IOException {
-        Tree<String> tree = new Tree<String>("root");
-        tree.addChild("child");
-
-        BufferedReader reader = read(tree);
-
-        assertEquals("root"     , reader.readLine());
-        assertEquals("+- child" , reader.readLine());
-    }
-
-    @Test
-    public void writeTreeWithOneChildAndNodeConverter() throws IOException {
-        Tree<String> tree = new Tree<String>("root");
-        tree.addChild("child");
-
-        StringWriter writer = new StringWriter();
-        tree.write(new PrintWriter(writer), new Tree.Converter<String>() {
-            public String toString(Node<String> node) {
-                return "my " + node.getValue();
-            }
-        });
-
-        BufferedReader reader = new BufferedReader(new StringReader(writer.getBuffer().toString()));
-
-        assertEquals("my root"     , reader.readLine());
-        assertEquals("+- my child" , reader.readLine());
-    }
-
-    @Test
-    public void writeTreeWithChildAndGrandChild() throws IOException {
-        Tree<String> tree = new Tree<String>("root");
-        Node<String> node = tree.addChild("child");
-        node.addChild("grandchild");
-
-        BufferedReader reader = read(tree);
-
-        assertEquals("root"            , reader.readLine());
-        assertEquals("+- child"        , reader.readLine());
-        assertEquals("   +- grandchild", reader.readLine());
-    }
-
-    @Test
-    public void writeTreeWithTwoChildrenAndOneGrandchild() throws IOException {
-        Tree<String> tree = new Tree<String>("root");
-        Node<String> child = tree.addChild("child1");
-        child.addChild("grandchild");
-        tree.addChild("child2");
-
-        BufferedReader reader = read(tree);
-
-        assertEquals("root"            , reader.readLine());
-        assertEquals("+- child1"       , reader.readLine());
-        assertEquals("|  +- grandchild", reader.readLine());
-        assertEquals("+- child2"       , reader.readLine());
-    }
-
-    @Test
-    public void flattenTree() throws IOException {
-        Tree<String> tree = new Tree<String>("root");
-        Node<String> child1 = tree.addChild("child1");
-        child1.addChild("grandchild");
-        Node child2 = tree.addChild("child2");
-        child2.addChild("grandchild");
-
-        Set<String> elements = tree.flatten();
-        assertNotNull(elements);
-        assertEquals(4, elements.size());
-        assertTrue(elements.contains("root"));
-        assertTrue(elements.contains("child1"));
-        assertTrue(elements.contains("child2"));
-        assertTrue(elements.contains("grandchild"));
-    }
-
-    @Test
-    public void hasAncestor() throws IOException {
-        Tree<String> tree = new Tree<String>("root");
-        Node<String> child1 = tree.addChild("child1");
-        child1.addChild("grandchild");
-        Node child2 = tree.addChild("child2");
-        Node node = child2.addChild("grandchild2");
-
-        assertTrue(node.hasAncestor("child2"));
-        assertTrue(node.hasAncestor("root"));
-        assertFalse(node.hasAncestor("child1"));
-    }
-
-    private BufferedReader read(Tree<String> tree) {
-        StringWriter writer = new StringWriter();
-        tree.write(new PrintWriter(writer));
-
-        BufferedReader reader = new BufferedReader(new StringReader(writer.getBuffer().toString()));
-        return reader;
-    }
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d0180939/bundle/command/src/test/java/org/apache/karaf/bundle/command/wikidoc/WikiParserTest.java
----------------------------------------------------------------------
diff --git a/bundle/command/src/test/java/org/apache/karaf/bundle/command/wikidoc/WikiParserTest.java b/bundle/command/src/test/java/org/apache/karaf/bundle/command/wikidoc/WikiParserTest.java
deleted file mode 100644
index 37101c3..0000000
--- a/bundle/command/src/test/java/org/apache/karaf/bundle/command/wikidoc/WikiParserTest.java
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * 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.karaf.bundle.command.wikidoc;
-
-import java.io.IOException;
-import java.io.StringReader;
-
-import org.easymock.EasyMock;
-import org.junit.Test;
-
-public class WikiParserTest {
-
-	private static final String TESTDOC = 
-		"h1. myTestdoc\n" +
-		"\n" +
-		"Some text\n" +
-		"* enumeration\n" +
-		" some text [a link] some more text\n" +
-		"h1 is no heading";
-	
-	private static final String HEADINGCASES = 
-		"h1.\n" +
-		"hf.";
-
-	@Test
-	public void parseTestDoc() throws IOException {
-		WikiVisitor visitor = EasyMock.createStrictMock(WikiVisitor.class);
-		visitor.heading(1, "myTestdoc");
-		EasyMock.expectLastCall();
-		visitor.text("\n");
-		EasyMock.expectLastCall();
-		visitor.text("\n");
-		EasyMock.expectLastCall();
-		visitor.text("Some text");
-		EasyMock.expectLastCall();
-		visitor.text("\n");
-		EasyMock.expectLastCall();
-		visitor.enumeration("enumeration");
-		EasyMock.expectLastCall();
-		visitor.text("\n");
-		EasyMock.expectLastCall();		
-		visitor.text(" some text ");
-		EasyMock.expectLastCall();
-		visitor.link("a link", "");
-		EasyMock.expectLastCall();
-		visitor.text(" some more text");
-		EasyMock.expectLastCall();
-		visitor.text("\n");
-		EasyMock.expectLastCall();
-		visitor.text("h1 is no heading");
-		EasyMock.expectLastCall();
-		visitor.text("\n");
-		EasyMock.expectLastCall();
-
-		EasyMock.replay(visitor);
-		WikiParser parser = new WikiParser(visitor);
-		parser.parse(new StringReader(TESTDOC));
-		EasyMock.verify(visitor);
-	}
-	
-	@Test
-	public void parseHeadingSpecialCases() throws IOException {
-		WikiVisitor visitor = EasyMock.createStrictMock(WikiVisitor.class);
-
-		visitor.heading(1, "");
-		EasyMock.expectLastCall();
-		visitor.text("\n");
-		EasyMock.expectLastCall();
-
-		visitor.text("hf.");
-		EasyMock.expectLastCall();
-		visitor.text("\n");
-		EasyMock.expectLastCall();
-		
-		EasyMock.replay(visitor);
-		WikiParser parser = new WikiParser(visitor);
-		parser.parse(new StringReader(HEADINGCASES));
-		EasyMock.verify(visitor);
-	}
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d0180939/bundle/core/pom.xml
----------------------------------------------------------------------
diff --git a/bundle/core/pom.xml b/bundle/core/pom.xml
index f3cccd8..b698d48 100644
--- a/bundle/core/pom.xml
+++ b/bundle/core/pom.xml
@@ -79,6 +79,12 @@
         </dependency>
 
         <dependency>
+            <groupId>org.apache.karaf.shell</groupId>
+            <artifactId>org.apache.karaf.shell.core</artifactId>
+            <optional>true</optional>
+        </dependency>
+
+        <dependency>
             <groupId>org.slf4j</groupId>
             <artifactId>slf4j-jdk14</artifactId>
             <scope>test</scope>
@@ -111,6 +117,7 @@
                             org.apache.karaf.bundle.core;-noimport:=true
                         </Export-Package>
                         <Private-Package>
+                            org.apache.karaf.bundle.command*,
                             org.apache.karaf.bundle.core.internal,
                             org.apache.karaf.bundle.core.internal.osgi,
                             org.apache.karaf.util.maven,
@@ -121,6 +128,7 @@
                         <Bundle-Activator>
                             org.apache.karaf.bundle.core.internal.osgi.Activator
                         </Bundle-Activator>
+                        <Karaf-Commands>org.apache.karaf.bundle.command.*</Karaf-Commands>
                     </instructions>
                 </configuration>
             </plugin>

http://git-wip-us.apache.org/repos/asf/karaf/blob/d0180939/bundle/core/src/main/java/org/apache/karaf/bundle/command/BundleCommand.java
----------------------------------------------------------------------
diff --git a/bundle/core/src/main/java/org/apache/karaf/bundle/command/BundleCommand.java b/bundle/core/src/main/java/org/apache/karaf/bundle/command/BundleCommand.java
new file mode 100644
index 0000000..dce0ca8
--- /dev/null
+++ b/bundle/core/src/main/java/org/apache/karaf/bundle/command/BundleCommand.java
@@ -0,0 +1,69 @@
+/*
+ * 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.karaf.bundle.command;
+
+import org.apache.karaf.bundle.core.BundleService;
+import org.apache.karaf.shell.api.action.Action;
+import org.apache.karaf.shell.api.action.Argument;
+import org.apache.karaf.shell.api.action.lifecycle.Reference;
+import org.apache.karaf.shell.support.ShellUtil;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+
+/**
+ * Unique bundle command.
+ */
+public abstract class BundleCommand implements Action {
+
+    @Argument(index = 0, name = "id", description = "The bundle ID or name or name/version", required = true, multiValued = false)
+    String id;
+
+    boolean defaultAllBundles = true;
+
+    @Reference
+    BundleService bundleService;
+
+    @Reference
+    BundleContext bundleContext;
+
+    public BundleCommand(boolean defaultAllBundles) {
+        this.defaultAllBundles = defaultAllBundles;
+    }
+
+    public Object execute() throws Exception {
+        return doExecute(true);
+    }
+
+    protected Object doExecute(boolean force) throws Exception {
+        Bundle bundle = bundleService.getBundle(id, defaultAllBundles);
+        if (bundle != null) {
+            if (force || !ShellUtil.isASystemBundle(bundleContext, bundle)) {
+                doExecute(bundle);
+            } else {
+                System.err.println("Access to system bundle " + id + " is discouraged. You may override with -f");
+            }
+        }
+        return null;
+    }
+
+    protected abstract void doExecute(Bundle bundle) throws Exception;
+
+    public void setBundleService(BundleService bundleService) {
+        this.bundleService = bundleService;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d0180939/bundle/core/src/main/java/org/apache/karaf/bundle/command/BundleCommandWithConfirmation.java
----------------------------------------------------------------------
diff --git a/bundle/core/src/main/java/org/apache/karaf/bundle/command/BundleCommandWithConfirmation.java b/bundle/core/src/main/java/org/apache/karaf/bundle/command/BundleCommandWithConfirmation.java
new file mode 100644
index 0000000..c07a357
--- /dev/null
+++ b/bundle/core/src/main/java/org/apache/karaf/bundle/command/BundleCommandWithConfirmation.java
@@ -0,0 +1,37 @@
+/*
+ * 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.karaf.bundle.command;
+
+import org.apache.karaf.shell.api.action.Option;
+
+/**
+ * Unique bundle command with confirmation while accessing system bundle.
+ */
+public abstract class BundleCommandWithConfirmation extends BundleCommand {
+
+    @Option(name = "--force", aliases = {"-f"}, description = "Forces the command to execute", required = false, multiValued = false)
+    boolean force;
+
+    public BundleCommandWithConfirmation() {
+        super(true);
+    }
+
+    public Object execute() throws Exception {
+        return doExecute(force);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d0180939/bundle/core/src/main/java/org/apache/karaf/bundle/command/BundlesCommand.java
----------------------------------------------------------------------
diff --git a/bundle/core/src/main/java/org/apache/karaf/bundle/command/BundlesCommand.java b/bundle/core/src/main/java/org/apache/karaf/bundle/command/BundlesCommand.java
new file mode 100644
index 0000000..ff4dd53
--- /dev/null
+++ b/bundle/core/src/main/java/org/apache/karaf/bundle/command/BundlesCommand.java
@@ -0,0 +1,79 @@
+/*
+ * 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.karaf.bundle.command;
+
+import java.util.List;
+
+import org.apache.karaf.bundle.core.BundleService;
+import org.apache.karaf.shell.api.action.Action;
+import org.apache.karaf.shell.api.action.Argument;
+import org.apache.karaf.shell.api.action.lifecycle.Reference;
+import org.apache.karaf.shell.support.ShellUtil;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+
+public abstract class BundlesCommand implements Action {
+
+    @Argument(index = 0, name = "ids", description = "The list of bundle (identified by IDs or name or name/version) separated by whitespaces", required = false, multiValued = true)
+    List<String> ids;
+    
+    boolean defaultAllBundles = true;
+
+    @Reference
+    BundleContext bundleContext;
+
+    @Reference
+    BundleService bundleService;
+    
+    public BundlesCommand(boolean defaultAllBundles) {
+        this.defaultAllBundles = defaultAllBundles;
+    }
+
+    public void setBundleContext(BundleContext bundleContext) {
+        this.bundleContext = bundleContext;
+    }
+
+    @Override
+    public Object execute() throws Exception {
+        doExecute(true);
+        return null;
+    }
+
+    protected Object doExecute(boolean force) throws Exception {
+        List<Bundle> bundles = bundleService.selectBundles(ids, defaultAllBundles);
+        if (!force) {
+            assertNoSystemBundles(bundles);
+        }
+        doExecute(bundles);
+        return null;
+    }
+    
+    private void assertNoSystemBundles(List<Bundle> bundles) {
+        for (Bundle bundle : bundles) {
+            if (ShellUtil.isASystemBundle(bundleContext, bundle)) {
+                throw new RuntimeException("Access to system bundle " + bundle.getBundleId() + " denied. You can override with -f");
+            }
+        }
+    }
+      
+    protected abstract void doExecute(List<Bundle> bundles) throws Exception;
+
+    public void setBundleService(BundleService bundleService) {
+        this.bundleService = bundleService;
+    }
+
+}


[29/59] [abbrv] [KARAF-2852] Merge instance/core and instance/command

Posted by gn...@apache.org.
http://git-wip-us.apache.org/repos/asf/karaf/blob/7c2db062/instance/core/pom.xml
----------------------------------------------------------------------
diff --git a/instance/core/pom.xml b/instance/core/pom.xml
deleted file mode 100644
index 0180bd3..0000000
--- a/instance/core/pom.xml
+++ /dev/null
@@ -1,181 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-
-    <!--
-
-        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.
-    -->
-
-    <modelVersion>4.0.0</modelVersion>
-
-    <parent>
-        <groupId>org.apache.karaf.instance</groupId>
-        <artifactId>instance</artifactId>
-        <version>4.0.0-SNAPSHOT</version>
-        <relativePath>../pom.xml</relativePath>
-    </parent>
-
-    <artifactId>org.apache.karaf.instance.core</artifactId>
-    <packaging>bundle</packaging>
-    <name>Apache Karaf :: Instance :: Core</name>
-    <description>Core implementation of the instance feature to manipulate Karaf child instances.</description>
-
-    <properties>
-        <appendedResourcesDirectory>${project.basedir}/../../etc/appended-resources</appendedResourcesDirectory>
-    </properties>
-
-    <dependencies>
-
-        <dependency>
-            <groupId>org.osgi</groupId>
-            <artifactId>org.osgi.core</artifactId>
-            <scope>provided</scope>
-        </dependency>
-
-        <dependency>
-            <groupId>org.slf4j</groupId>
-            <artifactId>slf4j-api</artifactId>
-            <scope>provided</scope>
-        </dependency>
-
-        <dependency>
-            <groupId>org.apache.felix</groupId>
-            <artifactId>org.apache.felix.utils</artifactId>
-            <scope>provided</scope>
-        </dependency>
-
-        <dependency>
-            <groupId>org.apache.karaf.shell</groupId>
-            <artifactId>org.apache.karaf.shell.core</artifactId>
-        </dependency>
-
-        <dependency>
-            <groupId>org.apache.karaf</groupId>
-            <artifactId>org.apache.karaf.util</artifactId>
-        </dependency>
-
-        <dependency>
-            <groupId>org.slf4j</groupId>
-            <artifactId>slf4j-jdk14</artifactId>
-            <scope>test</scope>
-        </dependency>
-    </dependencies>
-
-    <build>
-        <resources>
-            <resource>
-                <directory>${project.basedir}/src/main/resources</directory>
-                <includes>
-                    <include>**/*</include>
-                </includes>
-            </resource>
-            <resource>
-                <directory>${project.basedir}/src/main/resources</directory>
-                <filtering>true</filtering>
-                <includes>
-                    <include>**/*.info</include>
-                </includes>
-            </resource>
-            <resource>
-                <directory>${project.build.directory}/generated-resources</directory>
-                <includes>
-                    <include>**/*.*</include>
-                </includes>
-            </resource>
-        </resources>
-        <plugins>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-resources-plugin</artifactId>
-                <executions>
-                    <execution>
-                        <id>copy-resources</id>
-                        <phase>generate-resources</phase>
-                        <goals>
-                            <goal>copy-resources</goal>
-                        </goals>
-                        <configuration>
-                            <outputDirectory>${project.build.directory}/generated-resources/org/apache/karaf/instance/</outputDirectory>
-                            <resources>
-                                <resource>
-                                    <directory>${project.basedir}/../../assemblies/features/framework/src/main/resources</directory>
-                                    <excludes>
-                                        <exclude>**/org.apache.karaf.management.cfg</exclude>
-                                        <exclude>**/org.apache.karaf.shell.cfg</exclude>
-                                        <exclude>**/system.properties</exclude>
-                                    </excludes>
-                                </resource>
-                                <resource>
-                                    <directory>${project.basedir}/../../assemblies/features/framework/src/main/filtered-resources</directory>
-                                    <filtering>true</filtering>
-                                    <includes>
-                                        <include>**/*.properties</include>
-                                        <include>**/*.cfg</include>
-                                        <include>**/*.xml</include>
-                                        <include>**/*.info</include>
-                                    </includes>
-                                </resource>
-                                <resource>
-                                	<directory>${project.basedir}/../../assemblies/features/framework/src/main/snapshot</directory>
-                                	<filtering>true</filtering>
-                                    <includes>
-                                        <include>**/*.cfg</include>
-                                    </includes>
-                                </resource>
-                            </resources>
-                        </configuration>
-                    </execution>
-                </executions>
-            </plugin>
-            <plugin>
-                <groupId>org.apache.felix</groupId>
-                <artifactId>maven-bundle-plugin</artifactId>
-                <configuration>
-                    <instructions>
-                        <Export-Package>
-                            org.apache.karaf.instance.core,
-                        </Export-Package>
-                        <Provide-Capability>
-                            service-reference;effective:=active;objectClass=org.apache.karaf.instance.core.InstanceService
-                        </Provide-Capability>
-                        <Private-Package>
-                            org.apache.karaf.jpm,
-                            org.apache.karaf.jpm.impl,
-                            org.apache.karaf.instance.core.internal,
-                            org.apache.karaf.instance.core.internal.osgi,
-                            org.apache.felix.utils.properties;-split-package:=merge-first,
-                            org.apache.karaf.util.locks,
-                            org.apache.karaf.util.tracker
-                        </Private-Package>
-                        <Bundle-Activator>
-                            org.apache.karaf.instance.core.internal.osgi.Activator
-                        </Bundle-Activator>
-                    </instructions>
-                </configuration>
-            </plugin>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-surefire-plugin</artifactId>
-                <configuration>
-                  <excludes>
-                    <!-- this is not a unit test but an application used for testing -->
-                    <exclude>**/MainTest.java</exclude>
-                  </excludes>
-                </configuration>
-           </plugin>
-        </plugins>
-    </build>
-</project>

http://git-wip-us.apache.org/repos/asf/karaf/blob/7c2db062/instance/core/src/main/java/org/apache/karaf/instance/core/Instance.java
----------------------------------------------------------------------
diff --git a/instance/core/src/main/java/org/apache/karaf/instance/core/Instance.java b/instance/core/src/main/java/org/apache/karaf/instance/core/Instance.java
deleted file mode 100644
index 5e78bb2..0000000
--- a/instance/core/src/main/java/org/apache/karaf/instance/core/Instance.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * 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.karaf.instance.core;
-
-public interface Instance {
-
-    String STOPPED = "Stopped";
-    String STARTING = "Starting";
-    String STARTED = "Started";
-    String ERROR = "Error";
-
-    String getName();
-
-    @Deprecated
-    void setName(String name);
-    
-    boolean isRoot();
-
-    String getLocation();
-
-    @Deprecated
-    void setLocation(String location);
-
-    int getPid();
-
-    int getSshPort();
-
-    void changeSshPort(int port) throws Exception;
-
-    int getRmiRegistryPort();
-
-    void changeRmiRegistryPort(int port) throws Exception;
-
-    int getRmiServerPort();
-
-    void changeRmiServerPort(int port) throws Exception;
-
-    String getJavaOpts();
-
-    void changeJavaOpts(String javaOpts) throws Exception;
-
-    void start(String javaOpts) throws Exception;
-
-    void stop() throws Exception;
-
-    void destroy() throws Exception;
-
-    String getState() throws Exception;
-
-    @Deprecated
-    boolean isAttached();
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/7c2db062/instance/core/src/main/java/org/apache/karaf/instance/core/InstanceService.java
----------------------------------------------------------------------
diff --git a/instance/core/src/main/java/org/apache/karaf/instance/core/InstanceService.java b/instance/core/src/main/java/org/apache/karaf/instance/core/InstanceService.java
deleted file mode 100644
index cc6c10c..0000000
--- a/instance/core/src/main/java/org/apache/karaf/instance/core/InstanceService.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * 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.karaf.instance.core;
-
-public interface InstanceService {
-
-    Instance createInstance(String name, InstanceSettings settings, boolean printOutput) throws Exception;
-
-    void renameInstance(String name, String newName, boolean printOutput) throws Exception;
-
-    @Deprecated
-    void refreshInstance() throws Exception;
-
-    Instance cloneInstance(String name, String cloneName, InstanceSettings settings, boolean printOutput) throws Exception;
-
-    Instance[] getInstances();
-
-    Instance getInstance(String name);    
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/7c2db062/instance/core/src/main/java/org/apache/karaf/instance/core/InstanceSettings.java
----------------------------------------------------------------------
diff --git a/instance/core/src/main/java/org/apache/karaf/instance/core/InstanceSettings.java b/instance/core/src/main/java/org/apache/karaf/instance/core/InstanceSettings.java
deleted file mode 100644
index 0f9cf97..0000000
--- a/instance/core/src/main/java/org/apache/karaf/instance/core/InstanceSettings.java
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * 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.karaf.instance.core;
-
-import java.util.List;
-
-public class InstanceSettings {
-
-    private final int sshPort;
-    private final int rmiRegistryPort;
-    private final int rmiServerPort;
-    private final String location;
-    private final String javaOpts;
-    private final List<String> featureURLs;
-    private final List<String> features;
-
-    public InstanceSettings(int sshPort, int rmiRegistryPort, int rmiServerPort, String location, String javaOpts, List<String> featureURLs, List<String> features) {
-        this.sshPort = sshPort;
-        this.rmiRegistryPort = rmiRegistryPort;
-        this.rmiServerPort = rmiServerPort;
-        this.location = location;
-        this.javaOpts = javaOpts;
-        this.featureURLs = featureURLs;
-        this.features = features;
-    }
-
-    public int getSshPort() {
-        return sshPort;
-    }
-
-    public int getRmiRegistryPort() {
-        return rmiRegistryPort;
-    }
-
-    public int getRmiServerPort() {
-        return rmiServerPort;
-    }
-
-    public String getLocation() {
-        return location;
-    }
-
-    public String getJavaOpts() {
-        return javaOpts;
-    }
-
-    public List<String> getFeatureURLs() {
-        return featureURLs;
-    }
-
-    public List<String> getFeatures() {
-        return features;
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (o == this) {
-            return true;
-        }
-        if (!(o instanceof InstanceSettings)) {
-            return false;
-        }
-        InstanceSettings is = (InstanceSettings) o;
-        return is.sshPort == sshPort &&
-               is.rmiRegistryPort == rmiRegistryPort &&
-               is.rmiServerPort == rmiServerPort &&
-               (location == null ? is.location == null : location.equals(is.location)) &&
-               (javaOpts == null ? is.javaOpts == null : javaOpts.equals(is.javaOpts)) &&
-               (featureURLs == null ? is.featureURLs == null : featureURLs.equals(is.featureURLs)) &&
-               (features == null ? is.features == null : features.equals(is.features));
-    }
-
-    @Override
-    public int hashCode() {
-        int result = sshPort + rmiRegistryPort + rmiServerPort;
-        result = 31 * result + (location != null ? location.hashCode() : 0);
-        result = 31 * result + (javaOpts != null ? javaOpts.hashCode() : 0);
-        result = 31 * result + (featureURLs != null ? featureURLs.hashCode() : 0);
-        result = 31 * result + (features != null ? features.hashCode() : 0);
-        return result;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/7c2db062/instance/core/src/main/java/org/apache/karaf/instance/core/InstancesMBean.java
----------------------------------------------------------------------
diff --git a/instance/core/src/main/java/org/apache/karaf/instance/core/InstancesMBean.java b/instance/core/src/main/java/org/apache/karaf/instance/core/InstancesMBean.java
deleted file mode 100644
index f75e099..0000000
--- a/instance/core/src/main/java/org/apache/karaf/instance/core/InstancesMBean.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * 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.karaf.instance.core;
-
-import javax.management.MBeanException;
-import javax.management.openmbean.TabularData;
-
-public interface InstancesMBean {
-
-    String INSTANCE_PID = "Pid";
-    String INSTANCE_NAME = "Name";
-    String INSTANCE_IS_ROOT = "Is Root";
-    String INSTANCE_SSH_PORT = "SSH Port";
-    String INSTANCE_RMI_REGISTRY_PORT = "RMI Registry Port";
-    String INSTANCE_RMI_SERVER_PORT = "RMI Server Port";
-    String INSTANCE_STATE = "State";
-    String INSTANCE_LOCATION = "Location";
-    String INSTANCE_JAVAOPTS = "JavaOpts";
-
-    String[] INSTANCE = {INSTANCE_PID, INSTANCE_NAME, INSTANCE_IS_ROOT, INSTANCE_SSH_PORT, INSTANCE_RMI_REGISTRY_PORT,
-            INSTANCE_RMI_SERVER_PORT, INSTANCE_STATE, INSTANCE_LOCATION, INSTANCE_JAVAOPTS };
-
-    // Operations
-    int createInstance(String name, int sshPort, int rmiRegistryPort, int rmiServerPort, String location, String javaOpts, String features, String featureURLs) throws MBeanException;
-    void changeSshPort(String name, int port) throws MBeanException;
-    void changeRmiRegistryPort(String name, int port) throws MBeanException;
-    void changeRmiServerPort(String name, int port) throws MBeanException;
-    void changeJavaOpts(String name, String javaopts) throws MBeanException;
-    void destroyInstance(String name) throws MBeanException;
-    void startInstance(String name) throws MBeanException;
-    void startInstance(String name, String opts) throws MBeanException;
-    void startInstance(String name, String opts, boolean wait, boolean debug) throws MBeanException;
-    void stopInstance(String name) throws MBeanException;
-    void renameInstance(String originalName, String newName) throws MBeanException;
-    void renameInstance(String originalName, String newName, boolean verbose) throws MBeanException;
-    void cloneInstance(String name, String cloneName, int sshPort, int rmiRegistryPort, int rmiServerPort, String location, String javaOpts) throws MBeanException;
-
-    // Attributes
-    TabularData getInstances() throws MBeanException;
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/7c2db062/instance/core/src/main/java/org/apache/karaf/instance/core/internal/InstanceImpl.java
----------------------------------------------------------------------
diff --git a/instance/core/src/main/java/org/apache/karaf/instance/core/internal/InstanceImpl.java b/instance/core/src/main/java/org/apache/karaf/instance/core/internal/InstanceImpl.java
deleted file mode 100644
index edc4ec5..0000000
--- a/instance/core/src/main/java/org/apache/karaf/instance/core/internal/InstanceImpl.java
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * 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.karaf.instance.core.internal;
-
-import org.apache.karaf.instance.core.Instance;
-
-public class InstanceImpl implements Instance {
-
-    private final InstanceServiceImpl service;
-    private String name;
-
-    public InstanceImpl(InstanceServiceImpl service, String name) {
-        this.service = service;
-        this.name = name;
-    }
-
-    public String getName() {
-        return name;
-    }
-
-    public void setName(String name) {
-        throw new UnsupportedOperationException();
-    }
-
-    void doSetName(String name) {
-        this.name = name;
-    }
-
-    public boolean isRoot() {
-        return service.isInstanceRoot(name);
-    }
-
-    public String getLocation() {
-        return service.getInstanceLocation(name);
-    }
-
-    public void setLocation(String location) {
-        throw new UnsupportedOperationException();
-    }
-
-    public int getPid() {
-        return service.getInstancePid(name);
-    }
-
-    public int getSshPort() {
-        return service.getInstanceSshPort(name);
-    }
-
-    public void changeSshPort(int port) throws Exception {
-        service.changeInstanceSshPort(name, port);
-    }
-
-    public int getRmiRegistryPort() {
-        return service.getInstanceRmiRegistryPort(name);
-    }
-
-    public void changeRmiRegistryPort(int port) throws Exception {
-        service.changeInstanceRmiRegistryPort(name, port);
-    }
-
-    public int getRmiServerPort() {
-        return service.getInstanceRmiServerPort(name);
-    }
-
-    public void changeRmiServerPort(int port) throws Exception {
-        service.changeInstanceRmiServerPort(name, port);
-    }
-
-    public String getJavaOpts() {
-        return service.getInstanceJavaOpts(name);
-    }
-
-    public void changeJavaOpts(String javaOpts) throws Exception {
-        service.changeInstanceJavaOpts(name, javaOpts);
-    }
-
-    public void start(String javaOpts) throws Exception {
-        service.startInstance(name, javaOpts);
-    }
-
-    public void stop() throws Exception {
-        service.stopInstance(name);
-    }
-
-    public void destroy() throws Exception {
-        service.destroyInstance(name);
-    }
-
-    public String getState() throws Exception {
-        return service.getInstanceState(name);
-    }
-
-    public boolean isAttached() {
-        return getPid() != 0;
-    }
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/karaf/blob/7c2db062/instance/core/src/main/java/org/apache/karaf/instance/core/internal/InstanceServiceImpl.java
----------------------------------------------------------------------
diff --git a/instance/core/src/main/java/org/apache/karaf/instance/core/internal/InstanceServiceImpl.java b/instance/core/src/main/java/org/apache/karaf/instance/core/internal/InstanceServiceImpl.java
deleted file mode 100644
index 535c2a0..0000000
--- a/instance/core/src/main/java/org/apache/karaf/instance/core/internal/InstanceServiceImpl.java
+++ /dev/null
@@ -1,1166 +0,0 @@
-/*
- * 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.karaf.instance.core.internal;
-
-import org.apache.karaf.instance.core.Instance;
-import org.apache.karaf.instance.core.InstanceService;
-import org.apache.karaf.instance.core.InstanceSettings;
-import org.apache.karaf.jpm.Process;
-import org.apache.karaf.jpm.impl.ProcessBuilderFactoryImpl;
-import org.apache.karaf.jpm.impl.ScriptUtils;
-import org.apache.karaf.util.locks.FileLockUtils;
-import org.fusesource.jansi.Ansi;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.FilenameFilter;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.InterruptedIOException;
-import java.io.OutputStream;
-import java.io.PrintStream;
-import java.net.Socket;
-import java.net.URL;
-import java.util.ArrayList;
-import java.util.Enumeration;
-import java.util.HashMap;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Properties;
-import java.util.Scanner;
-
-public class InstanceServiceImpl implements InstanceService {
-
-    public static final String STORAGE_FILE = "instance.properties";
-    public static final String BACKUP_EXTENSION = ".bak";
-    private static final String FEATURES_CFG = "etc/org.apache.karaf.features.cfg";
-
-    private static final Logger LOGGER = LoggerFactory.getLogger(InstanceServiceImpl.class);
-
-    private static final String CONFIG_PROPERTIES_FILE_NAME = "config.properties";
-
-    private static final String KARAF_SHUTDOWN_PORT = "karaf.shutdown.port";
-
-    private static final String KARAF_SHUTDOWN_HOST = "karaf.shutdown.host";
-
-    private static final String KARAF_SHUTDOWN_PORT_FILE = "karaf.shutdown.port.file";
-
-    private static final String KARAF_SHUTDOWN_COMMAND = "karaf.shutdown.command";
-
-    private static final String KARAF_SHUTDOWN_PID_FILE = "karaf.shutdown.pid.file";
-
-    private static final String DEFAULT_SHUTDOWN_COMMAND = "SHUTDOWN";
-
-    public static final String DEFAULT_JAVA_OPTS = "-server -Xmx512M -Dcom.sun.management.jmxremote -XX:+UnlockDiagnosticVMOptions -XX:+UnsyncloadClass";
-
-    private LinkedHashMap<String, InstanceImpl> proxies = new LinkedHashMap<String, InstanceImpl>();
-
-    private File storageLocation;
-
-    private long stopTimeout = 30000;
-
-    static class InstanceState {
-        String name;
-        String loc;
-        String opts;
-        int pid;
-        boolean root;
-    }
-
-    static class State {
-        int defaultSshPortStart = 8101;
-        int defaultRmiRegistryPortStart = 1099;
-        int defaultRmiServerPortStart = 44444;
-        Map<String, InstanceState> instances;
-    }
-
-    public InstanceServiceImpl() {
-        String prop = System.getProperty("karaf.instances");
-        if (prop != null) {
-            storageLocation = new File(prop);
-        }
-    }
-
-    public File getStorageLocation() {
-        return storageLocation;
-    }
-
-    public void setStorageLocation(File storage) {
-        this.storageLocation = storage;
-    }
-
-    public long getStopTimeout() {
-        return stopTimeout;
-    }
-
-    public void setStopTimeout(long stopTimeout) {
-        this.stopTimeout = stopTimeout;
-    }
-
-    private State loadData(org.apache.felix.utils.properties.Properties storage) {
-        State state = new State();
-        int count = getInt(storage, "count", 0);
-        state.defaultSshPortStart = getInt(storage, "ssh.port", state.defaultSshPortStart);
-        state.defaultRmiRegistryPortStart = getInt(storage, "rmi.registry.port", state.defaultRmiRegistryPortStart);
-        state.defaultRmiServerPortStart = getInt(storage, "rmi.server.port", state.defaultRmiServerPortStart);
-        state.instances = new LinkedHashMap<String, InstanceState>();
-
-        for (int i = 0; i < count; i++) {
-            InstanceState instance = new InstanceState();
-            instance.name = getString(storage, "item." + i + ".name", null);
-            instance.loc = getString(storage, "item." + i + ".loc", null);
-            instance.opts = getString(storage, "item." + i + ".opts", null);
-            instance.pid = getInt(storage, "item." + i + ".pid", 0);
-            instance.root = getBool(storage, "item." + i + ".root", false);
-            state.instances.put(instance.name, instance);
-        }
-        // Update proxies list
-        for (InstanceState instance : state.instances.values()) {
-            if (!this.proxies.containsKey(instance.name)) {
-                proxies.put(instance.name, new InstanceImpl(this, instance.name));
-            }
-        }
-        List<String> names = new ArrayList<String>(this.proxies.keySet());
-        for (String name : names) {
-            if (!state.instances.containsKey(name)) {
-                this.proxies.remove(name);
-            }
-        }
-        return state;
-    }
-
-    private void saveData(State state, org.apache.felix.utils.properties.Properties storage) {
-        storage.put("ssh.port", Integer.toString(state.defaultSshPortStart));
-        storage.put("rmi.registry.port", Integer.toString(state.defaultRmiRegistryPortStart));
-        storage.put("rmi.server.port", Integer.toString(state.defaultRmiServerPortStart));
-        storage.put("count", Integer.toString(state.instances.size()));
-        int i = 0;
-        for (InstanceState instance : state.instances.values()) {
-            storage.put("item." + i + ".name", instance.name);
-            storage.put("item." + i + ".root", Boolean.toString(instance.root));
-            storage.put("item." + i + ".loc", instance.loc);
-            storage.put("item." + i + ".pid", Integer.toString(instance.pid));
-            storage.put("item." + i + ".opts", instance.opts != null ? instance.opts : "");
-            i++;
-        }
-        while (storage.containsKey("item." + i + ".name")) {
-            storage.remove("item." + i + ".name");
-            storage.remove("item." + i + ".root");
-            storage.remove("item." + i + ".loc");
-            storage.remove("item." + i + ".pid");
-            storage.remove("item." + i + ".opts");
-            i++;
-        }
-    }
-
-    private boolean getBool(org.apache.felix.utils.properties.Properties storage, String name, boolean def) {
-        Object value = storage.get(name);
-        if (value != null) {
-            return Boolean.parseBoolean(value.toString());
-        } else {
-            return def;
-        }
-    }
-
-    private int getInt(org.apache.felix.utils.properties.Properties storage, String name, int def) {
-        Object value = storage.get(name);
-        if (value != null) {
-            return Integer.parseInt(value.toString());
-        } else {
-            return def;
-        }
-    }
-
-    private String getString(org.apache.felix.utils.properties.Properties storage, String name, String def) {
-        Object value = storage.get(name);
-        return value != null ? value.toString() : def;
-    }
-
-    interface Task<T> {
-        T call(State state) throws IOException;
-    }
-
-    synchronized <T> T execute(final Task<T> callback) {
-        final File storageFile = new File(storageLocation, STORAGE_FILE);
-        if (!storageFile.exists()) {
-            storageFile.getParentFile().mkdirs();
-            try {
-                storageFile.createNewFile();
-            } catch (IOException e) {
-                // Ignore
-            }
-        }
-        if (storageFile.exists()) {
-            if (!storageFile.isFile()) {
-                throw new IllegalStateException("Instance storage location should be a file: " + storageFile);
-            }
-            try {
-                return FileLockUtils.execute(storageFile, new FileLockUtils.CallableWithProperties<T>() {
-                    public T call(org.apache.felix.utils.properties.Properties properties) throws IOException {
-                        State state = loadData(properties);
-                        T t = callback.call(state);
-                        saveData(state, properties);
-                        return t;
-                    }
-                });
-            } catch (IOException e) {
-                throw new RuntimeException(e);
-            }
-        } else {
-            throw new IllegalStateException("Instance storage location does not exist: " + storageFile);
-        }
-    }
-
-    public synchronized void refreshInstance() throws Exception {
-    }
-
-    private void logInfo(String message, boolean printOutput, Object... args) {
-        if (LOGGER.isInfoEnabled() || printOutput) {
-            String formatted = String.format(message, args);
-            LOGGER.info(formatted);
-            if (printOutput) {
-                println(formatted);
-            }
-        }
-    }
-
-    public synchronized Instance createInstance(final String name, final InstanceSettings settings, final boolean printOutput) throws Exception {
-        return execute(new Task<Instance>() {
-            public Instance call(State state) throws IOException {
-                if (state.instances.get(name) != null) {
-                    throw new IllegalArgumentException("Instance '" + name + "' already exists");
-                }
-                String loc = settings.getLocation() != null ? settings.getLocation() : name;
-                File karafBase = new File(loc);
-                if (!karafBase.isAbsolute()) {
-                    karafBase = new File(storageLocation, loc);
-                }
-                int sshPort = settings.getSshPort();
-                if (sshPort <= 0) {
-                    sshPort = ++state.defaultSshPortStart;
-                }
-                int rmiRegistryPort = settings.getRmiRegistryPort();
-                if (rmiRegistryPort <= 0) {
-                    rmiRegistryPort = ++state.defaultRmiRegistryPortStart;
-                }
-                int rmiServerPort = settings.getRmiServerPort();
-                if (rmiServerPort <= 0) {
-                    rmiServerPort = ++state.defaultRmiServerPortStart;
-                }
-                logInfo("Creating new instance on SSH port %d and registry port %d / RMI server port %d at: %s",
-                        printOutput, sshPort, rmiRegistryPort, rmiServerPort, karafBase);
-
-                mkdir(karafBase, "bin", printOutput);
-                mkdir(karafBase, "etc", printOutput);
-                mkdir(karafBase, "system", printOutput);
-                mkdir(karafBase, "deploy", printOutput);
-                mkdir(karafBase, "data", printOutput);
-
-                copyResourceToDir(karafBase, "etc/all.policy", printOutput);
-                copyResourceToDir(karafBase, "etc/config.properties", printOutput);
-                copyResourceToDir(karafBase, "etc/custom.properties", printOutput);
-                copyResourceToDir(karafBase, "etc/distribution.info", printOutput);
-                copyResourceToDir(karafBase, "etc/equinox-debug.properties", printOutput);
-                copyResourceToDir(karafBase, "etc/java.util.logging.properties", printOutput);
-                copyResourceToDir(karafBase, "etc/jmx.acl.cfg", printOutput);
-                copyResourceToDir(karafBase, "etc/jmx.acl.java.lang.Memory.cfg", printOutput);
-                copyResourceToDir(karafBase, "etc/jmx.acl.org.apache.karaf.bundle.cfg", printOutput);
-                copyResourceToDir(karafBase, "etc/jmx.acl.org.apache.karaf.config.cfg", printOutput);
-                copyResourceToDir(karafBase, "etc/jmx.acl.org.apache.karaf.security.jmx.cfg", printOutput);
-                copyResourceToDir(karafBase, "etc/jmx.acl.osgi.compendium.cm.cfg", printOutput);
-                copyResourceToDir(karafBase, "etc/jre.properties", printOutput);
-                copyResourceToDir(karafBase, "etc/keys.properties", printOutput);
-                copyResourceToDir(karafBase, "etc/org.apache.felix.fileinstall-deploy.cfg", printOutput);
-                copyResourceToDir(karafBase, "etc/org.apache.karaf.command.acl.bundle.cfg", printOutput);
-                copyResourceToDir(karafBase, "etc/org.apache.karaf.command.acl.config.cfg", printOutput);
-                copyResourceToDir(karafBase, "etc/org.apache.karaf.command.acl.feature.cfg", printOutput);
-                copyResourceToDir(karafBase, "etc/org.apache.karaf.command.acl.jaas.cfg", printOutput);
-                copyResourceToDir(karafBase, "etc/org.apache.karaf.command.acl.kar.cfg", printOutput);
-                copyResourceToDir(karafBase, "etc/org.apache.karaf.command.acl.shell.cfg", printOutput);
-                copyResourceToDir(karafBase, "etc/org.apache.karaf.command.acl.system.cfg", printOutput);
-                copyResourceToDir(karafBase, "etc/org.apache.karaf.features.obr.cfg", printOutput);
-                copyResourceToDir(karafBase, "etc/org.apache.karaf.features.repos.cfg", printOutput);
-                copyResourceToDir(karafBase, "etc/org.apache.karaf.jaas.cfg", printOutput);
-                copyResourceToDir(karafBase, "etc/org.apache.karaf.kar.cfg", printOutput);
-                copyResourceToDir(karafBase, "etc/org.apache.karaf.log.cfg", printOutput);
-                copyResourceToDir(karafBase, "etc/org.ops4j.pax.logging.cfg", printOutput);
-                copyResourceToDir(karafBase, "etc/org.ops4j.pax.url.mvn.cfg", printOutput);
-                copyResourceToDir(karafBase, "etc/regions-config.xml", printOutput);
-                copyResourceToDir(karafBase, "etc/shell.init.script", printOutput);
-                copyResourceToDir(karafBase, "etc/users.properties", printOutput);
-
-                copyResourceToDir(karafBase, FEATURES_CFG, printOutput);
-                addFeaturesFromSettings(new File(karafBase, FEATURES_CFG), settings);
-
-                // The startup.properties is now generated by the karaf maven plugin, so
-                // we use the one from the root instance instead of embedding it
-                File rootEtc = new File(System.getProperty("karaf.etc"));
-                copy(new File(rootEtc, "startup.properties"), new File(karafBase, "etc/startup.properties"));
-
-                HashMap<String, String> props = new HashMap<String, String>();
-                props.put("${SUBST-KARAF-NAME}", name);
-                props.put("${SUBST-KARAF-HOME}", System.getProperty("karaf.home"));
-                props.put("${SUBST-KARAF-BASE}", karafBase.getPath());
-                props.put("${SUBST-SSH-PORT}", Integer.toString(sshPort));
-                props.put("${SUBST-RMI-REGISTRY-PORT}", Integer.toString(rmiRegistryPort));
-                props.put("${SUBST-RMI-SERVER-PORT}", Integer.toString(rmiServerPort));
-                copyFilteredResourceToDir(karafBase, "etc/system.properties", props, printOutput);
-                copyFilteredResourceToDir(karafBase, "etc/org.apache.karaf.shell.cfg", props, printOutput);
-                copyFilteredResourceToDir(karafBase, "etc/org.apache.karaf.management.cfg", props, printOutput);
-               
-                copyFilteredResourceToDir(karafBase, "bin/karaf", props, printOutput);
-                copyFilteredResourceToDir(karafBase, "bin/start", props, printOutput);
-                copyFilteredResourceToDir(karafBase, "bin/stop", props, printOutput);
-
-                copyFilteredResourceToDir(karafBase, "bin/karaf.bat", props, printOutput);
-                copyFilteredResourceToDir(karafBase, "bin/start.bat", props, printOutput);
-                copyFilteredResourceToDir(karafBase, "bin/stop.bat", props, printOutput);
-
-                try {
-                    chmod(new File(karafBase, "bin/karaf"), "a+x");
-                    chmod(new File(karafBase, "bin/start"), "a+x");
-                    chmod(new File(karafBase, "bin/stop"), "a+x");
-                } catch (IOException e) {
-                    LOGGER.debug("Could not set file mode on scripts.", e);
-                }
-
-                String javaOpts = settings.getJavaOpts();
-                if (javaOpts == null || javaOpts.length() == 0) {
-                    javaOpts = DEFAULT_JAVA_OPTS;
-                }
-                InstanceState is = new InstanceState();
-                is.name = name;
-                is.loc = karafBase.toString();
-                is.opts = javaOpts;
-                state.instances.put(name, is);
-                InstanceImpl instance = new InstanceImpl(InstanceServiceImpl.this, name);
-                InstanceServiceImpl.this.proxies.put(name, instance);
-                return instance;
-            }
-        });
-    }
-
-    void addFeaturesFromSettings(File featuresCfg, final InstanceSettings settings) throws IOException {
-        FileLockUtils.execute(featuresCfg, new FileLockUtils.RunnableWithProperties() {
-            public void run(org.apache.felix.utils.properties.Properties properties) throws IOException {
-                appendToPropList(properties, "featuresBoot", settings.getFeatures());
-                appendToPropList(properties, "featuresRepositories", settings.getFeatureURLs());
-            }
-        });
-    }
-
-    private void appendToPropList(org.apache.felix.utils.properties.Properties p, String key, List<String> elements) {
-        if (elements == null) {
-            return;
-        }
-        StringBuilder sb = new StringBuilder(p.get(key).toString().trim());
-        for (String f : elements) {
-            if (sb.length() > 0) {
-                sb.append(',');
-            }
-            sb.append(f);
-        }
-        p.put(key, sb.toString());
-    }
-
-    public Instance[] getInstances() {
-        return execute(new Task<Instance[]>() {
-            public Instance[] call(State state) throws IOException {
-                return proxies.values().toArray(new Instance[proxies.size()]);
-            }
-        });
-    }
-
-    public Instance getInstance(final String name) {
-        return execute(new Task<Instance>() {
-            public Instance call(State state) throws IOException {
-                return proxies.get(name);
-            }
-        });
-    }
-
-    public void startInstance(final String name, final String javaOpts) {
-        execute(new Task<Object>() {
-            public Object call(State state) throws IOException {
-                InstanceState instance = state.instances.get(name);
-                if (instance == null) {
-                    throw new IllegalArgumentException("Instance " + name + " not found");
-                }
-                checkPid(instance);
-                if (instance.pid != 0) {
-                    throw new IllegalStateException("Instance already started");
-                }
-                String opts = javaOpts;
-                if (opts == null || opts.length() == 0) {
-                    opts = instance.opts;
-                }
-                if (opts == null || opts.length() == 0) {
-                    opts = DEFAULT_JAVA_OPTS;
-                }
-
-                // fallback and read karafOpts from KARAF_OPTS environment if no System property present
-                String karafOptsEnv = System.getenv("KARAF_OPTS");
-                String karafOpts = System.getProperty("karaf.opts", karafOptsEnv != null ? karafOptsEnv : "");
-                
-                String location = instance.loc;
-
-                File libDir = new File(System.getProperty("karaf.home"), "lib");
-                File childLibDir = new File(location, "lib");
-                
-                StringBuilder classpath = classpathFromLibDir(libDir);
-                StringBuilder childClasspath = classpathFromLibDir(childLibDir);
-                if (childClasspath.length() > 0 && !libDir.equals(childLibDir)) {
-                    classpath.append(System.getProperty("path.separator"));
-                    classpath.append(childClasspath);
-                }    
-
-                String command = "\""
-                        + new File(System.getProperty("java.home"), ScriptUtils.isWindows() ? "bin\\java.exe" : "bin/java").getCanonicalPath()
-                        + "\" " + opts
-                        + " " + karafOpts
-                        + " -Djava.util.logging.config.file=\"" + new File(location, "etc/java.util.logging.properties").getCanonicalPath() + "\""
-                        + " -Djava.endorsed.dirs=\"" + new File(new File(new File(System.getProperty("java.home"), "jre"), "lib"), "endorsed") + System.getProperty("path.separator") + new File(new File(System.getProperty("java.home"), "lib"), "endorsed") + System.getProperty("path.separator") + new File(libDir, "endorsed").getCanonicalPath() + "\""
-                        + " -Djava.ext.dirs=\"" + new File(new File(new File(System.getProperty("java.home"), "jre"), "lib"), "ext") + System.getProperty("path.separator") + new File(new File(System.getProperty("java.home"), "lib"), "ext") + System.getProperty("path.separator") + new File(libDir, "ext").getCanonicalPath() + "\""
-                        + " -Dkaraf.home=\"" + System.getProperty("karaf.home") + "\""
-                        + " -Dkaraf.base=\"" + new File(location).getCanonicalPath() + "\""
-                        + " -Dkaraf.data=\"" + new File(new File(location).getCanonicalPath(), "data") + "\""
-                        + " -Dkaraf.etc=\"" + new File(new File(location).getCanonicalPath(), "etc") + "\""
-                        + " -Djavax.management.builder.initial=org.apache.karaf.management.boot.KarafMBeanServerBuilder"
-                        + " -Dkaraf.startLocalConsole=false"
-                        + " -Dkaraf.startRemoteShell=true"
-                        + " -classpath \"" + classpath.toString() + "\""
-                        + " org.apache.karaf.main.Main";
-                LOGGER.debug("Starting instance " + name + " with command: " + command);
-                org.apache.karaf.jpm.Process process = new ProcessBuilderFactoryImpl().newBuilder()
-                        .directory(new File(location))
-                        .command(command)
-                        .start();
-                instance.pid = process.getPid();
-                return null;
-            }
-
-            private StringBuilder classpathFromLibDir(File libDir) throws IOException {
-                File[] jars = libDir.listFiles(new FilenameFilter() {
-                    public boolean accept(File dir, String name) {
-                        return name.endsWith(".jar");
-                    }
-                });
-                StringBuilder classpath = new StringBuilder();
-                if (jars != null) {
-                    for (File jar : jars) {
-                        if (classpath.length() > 0) {
-                            classpath.append(System.getProperty("path.separator"));
-                        }
-                        classpath.append(jar.getCanonicalPath());
-                    }
-                }
-                return classpath;
-            }
-        });
-    }
-
-    public void stopInstance(final String name) {
-        execute(new Task<Object>() {
-            public Object call(State state) throws IOException {
-                InstanceState instance = state.instances.get(name);
-                if (instance == null) {
-                    throw new IllegalArgumentException("Instance " + name + " not found");
-                }
-                checkPid(instance);
-                if (instance.pid == 0) {
-                    throw new IllegalStateException("Instance already stopped");
-                }
-                cleanShutdown(instance);
-                if (instance.pid > 0) {
-                    Process process = new ProcessBuilderFactoryImpl().newBuilder().attach(instance.pid);
-                    process.destroy();
-                }
-                return null;
-            }
-        });
-    }
-
-    public void destroyInstance(final String name) {
-        execute(new Task<Object>() {
-            public Object call(State state) throws IOException {
-                InstanceState instance = state.instances.get(name);
-                if (instance == null) {
-                    throw new IllegalArgumentException("Instance " + name + " not found");
-                }
-                checkPid(instance);
-                if (instance.pid != 0) {
-                    throw new IllegalStateException("Instance not stopped");
-                }
-                deleteFile(new File(instance.loc));
-                state.instances.remove(name);
-                InstanceServiceImpl.this.proxies.remove(name);
-                return null;
-            }
-        });
-    }
-
-    public void renameInstance(final String oldName, final String newName, final boolean printOutput) throws Exception {
-        execute(new Task<Object>() {
-            public Object call(State state) throws IOException {
-                if (state.instances.get(newName) != null) {
-                    throw new IllegalArgumentException("Instance " + newName + " already exists");
-                }
-                InstanceState instance = state.instances.get(oldName);
-                if (instance == null) {
-                    throw new IllegalArgumentException("Instance " + oldName + " not found");
-                }
-                if (instance.root) {
-                    throw new IllegalArgumentException("Root instance cannot be renamed");
-                }
-                checkPid(instance);
-                if (instance.pid != 0) {
-                    throw new IllegalStateException("Instance not stopped");
-                }
-
-                println(Ansi.ansi().a("Renaming instance ")
-                        .a(Ansi.Attribute.INTENSITY_BOLD).a(oldName).a(Ansi.Attribute.RESET)
-                        .a(" to ")
-                        .a(Ansi.Attribute.INTENSITY_BOLD).a(newName).a(Ansi.Attribute.RESET).toString());
-                // rename directory
-                String oldLocationPath = instance.loc;
-                File oldLocation = new File(oldLocationPath);
-                String basedir = oldLocation.getParent();
-                File newLocation = new File(basedir, newName);
-                oldLocation.renameTo(newLocation);
-                // create the properties map including the instance name and instance location
-                // TODO: replacing is bad, we should re-extract the needed files
-                HashMap<String, String> props = new HashMap<String, String>();
-                props.put(oldName, newName);
-                props.put(oldLocationPath, newLocation.getPath());
-                // replace all references to the "old" name by the new one in etc/system.properties
-                // NB: it's replacement to avoid to override the user's changes
-                filterResource(newLocation, "etc/system.properties", props);
-                // replace all references to the "old" name by the new one in bin/karaf
-                filterResource(newLocation, "bin/karaf", props);
-                filterResource(newLocation, "bin/start", props);
-                filterResource(newLocation, "bin/stop", props);
-                filterResource(newLocation, "bin/karaf.bat", props);
-                filterResource(newLocation, "bin/start.bat", props);
-                filterResource(newLocation, "bin/stop.bat", props);
-                // update instance
-                instance.name = newName;
-                instance.loc = newLocation.getPath();
-                state.instances.put(newName, instance);
-                state.instances.remove(oldName);
-                InstanceImpl proxy = InstanceServiceImpl.this.proxies.remove(oldName);
-                if (proxy == null) {
-                    proxy = new InstanceImpl(InstanceServiceImpl.this, newName);
-                } else {
-                    proxy.doSetName(newName);
-                }
-                InstanceServiceImpl.this.proxies.put(newName, proxy);
-                return null;
-            }
-        });
-    }
-
-    public synchronized Instance cloneInstance(final String name, final String cloneName, final InstanceSettings settings, final boolean printOutput) throws Exception {
-        final int instanceSshPort = getInstanceSshPort(name);
-        final int instanceRmiRegistryPort = getInstanceRmiRegistryPort(name);
-        final int instanceRmiServerPort = getInstanceRmiServerPort(name);
-
-        return execute(new Task<Instance>() {
-            public Instance call(State state) throws IOException {
-                if (state.instances.get(cloneName) != null) {
-                    throw new IllegalArgumentException("Instance " + cloneName + " already exists");
-                }
-                InstanceState instance = state.instances.get(name);
-                if (instance == null) {
-                    throw new IllegalArgumentException("Instance " + name + " not found");
-                }
-
-                // define the clone instance location
-                String cloneLocationPath = settings.getLocation() != null ? settings.getLocation() : cloneName;
-                File cloneLocation = new File(cloneLocationPath);
-                if (!cloneLocation.isAbsolute()) {
-                    cloneLocation = new File(storageLocation, cloneLocationPath);
-                }
-                // copy instance directory
-                String locationPath = instance.loc;
-                File location = new File(locationPath);
-                copy(location, cloneLocation);
-                // create the properties map including the instance name, location, ssh and rmi port numbers
-                // TODO: replacing stuff anywhere is not really good, we might end up replacing unwanted stuff
-                // TODO: if no ports are overriden, shouldn't we choose new ports ?
-                HashMap<String, String> props = new HashMap<String, String>();
-                props.put(name, cloneName);
-                props.put(locationPath, cloneLocationPath);
-                if (settings.getSshPort() > 0)
-                    props.put(Integer.toString(instanceSshPort), Integer.toString(settings.getSshPort()));
-                if (settings.getRmiRegistryPort() > 0)
-                    props.put(Integer.toString(instanceRmiRegistryPort), Integer.toString(settings.getRmiRegistryPort()));
-                if (settings.getRmiServerPort() > 0)
-                    props.put(Integer.toString(instanceRmiServerPort), Integer.toString(settings.getRmiServerPort()));
-
-                // filtering clone files
-                filterResource(cloneLocation, "etc/custom.properties", props);
-                filterResource(cloneLocation, "etc/org.apache.karaf.management.cfg", props);
-                filterResource(cloneLocation, "etc/org.apache.karaf.shell.cfg", props);
-                filterResource(cloneLocation, "etc/system.properties", props);
-                filterResource(cloneLocation, "bin/karaf", props);
-                filterResource(cloneLocation, "bin/start", props);
-                filterResource(cloneLocation, "bin/stop", props);
-                filterResource(cloneLocation, "bin/karaf.bat", props);
-                filterResource(cloneLocation, "bin/start.bat", props);
-                filterResource(cloneLocation, "bin/stop.bat", props);
-                // create and add the clone instance in the registry
-                String javaOpts = settings.getJavaOpts();
-                if (javaOpts == null || javaOpts.length() == 0) {
-                    javaOpts = DEFAULT_JAVA_OPTS;
-                }
-                InstanceState is = new InstanceState();
-                is.name = cloneName;
-                is.loc = cloneLocation.toString();
-                is.opts = javaOpts;
-                state.instances.put(cloneName, is);
-                InstanceImpl cloneInstance = new InstanceImpl(InstanceServiceImpl.this, cloneName);
-                InstanceServiceImpl.this.proxies.put(cloneName, cloneInstance);
-                return cloneInstance;
-            }
-        });
-    }
-
-    private void checkPid(InstanceState instance) throws IOException {
-        if (instance.pid != 0) {
-            Process process = new ProcessBuilderFactoryImpl().newBuilder().attach(instance.pid);
-            if (!process.isRunning()) {
-                instance.pid = 0;
-            }
-        }
-    }
-
-    protected void cleanShutdown(InstanceState instance) {
-        try {
-            File file = new File(new File(instance.loc, "etc"), CONFIG_PROPERTIES_FILE_NAME);
-            URL configPropURL = file.toURI().toURL();
-            Properties props = loadPropertiesFile(configPropURL);
-            props.put("karaf.base", new File(instance.loc).getCanonicalPath());
-            props.put("karaf.home", System.getProperty("karaf.home"));
-            props.put("karaf.data", new File(new File(instance.loc), "data").getCanonicalPath());
-            props.put("karaf.etc", new File(new File(instance.loc), "etc").getCanonicalPath());
-            for (Enumeration e = props.propertyNames(); e.hasMoreElements();) {
-                String key = (String) e.nextElement();
-                props.setProperty(key,
-                        substVars(props.getProperty(key), key, null, props));
-            }
-            int port = Integer.parseInt(props.getProperty(KARAF_SHUTDOWN_PORT, "0"));
-            String host = props.getProperty(KARAF_SHUTDOWN_HOST, "localhost");
-            String portFile = props.getProperty(KARAF_SHUTDOWN_PORT_FILE);
-            String shutdown = props.getProperty(KARAF_SHUTDOWN_COMMAND, DEFAULT_SHUTDOWN_COMMAND);
-            if (port == 0 && portFile != null) {
-                BufferedReader r = new BufferedReader(new InputStreamReader(new FileInputStream(portFile)));
-                String portStr = r.readLine();
-                port = Integer.parseInt(portStr);
-                r.close();
-            }
-            // We found the port, try to send the command
-            if (port > 0) {
-                Socket s = new Socket(host, port);
-                s.getOutputStream().write(shutdown.getBytes());
-                s.close();
-                long t = System.currentTimeMillis() + getStopTimeout();
-                do {
-                    Thread.sleep(100);
-                    checkPid(instance);
-                } while (System.currentTimeMillis() < t && instance.pid > 0);
-            }
-        } catch (Exception e) {
-            LOGGER.debug("Unable to cleanly shutdown instance " + instance.name, e);
-        }
-    }
-
-    int getInstanceSshPort(String name) {
-        return getKarafPort(name, "etc/org.apache.karaf.shell.cfg", "sshPort");
-    }
-
-    void changeInstanceSshPort(String name, final int port) throws Exception {
-        setKarafPort(name, "etc/org.apache.karaf.shell.cfg", "sshPort", port);
-    }
-
-    int getInstanceRmiRegistryPort(String name) {
-        return getKarafPort(name, "etc/org.apache.karaf.management.cfg", "rmiRegistryPort");
-    }
-
-    void changeInstanceRmiRegistryPort(String name, final int port) throws Exception {
-        setKarafPort(name, "etc/org.apache.karaf.management.cfg", "rmiRegistryPort", port);
-    }
-
-    int getInstanceRmiServerPort(String name) {
-        return getKarafPort(name, "etc/org.apache.karaf.management.cfg", "rmiServerPort");
-    }
-
-    void changeInstanceRmiServerPort(String name, int port) throws Exception {
-        setKarafPort(name, "etc/org.apache.karaf.management.cfg", "rmiServerPort", port);
-    }
-
-    private int getKarafPort(final String name, final String path, final String key) {
-        return execute(new Task<Integer>() {
-            public Integer call(State state) throws IOException {
-                return InstanceServiceImpl.this.getKarafPort(state, name, path, key);
-            }
-        });
-    }
-
-    private Integer getKarafPort(State state, String name, String path, final String key) {
-        InstanceState instance = state.instances.get(name);
-        if (instance == null) {
-            throw new IllegalArgumentException("Instance " + name + " not found");
-        }
-        File f = new File(instance.loc, path);
-        try {
-            return FileLockUtils.execute(f, new FileLockUtils.CallableWithProperties<Integer>() {
-                public Integer call(org.apache.felix.utils.properties.Properties properties) throws IOException {
-                    return Integer.parseInt(properties.get(key).toString());
-                }
-            });
-        } catch (IOException e) {
-            return 0;
-        }
-    }
-
-    private void setKarafPort(final String name, final String path, final String key, final int port) throws IOException {
-        execute(new Task<Object>() {
-            public Object call(State state) throws IOException {
-                InstanceState instance = state.instances.get(name);
-                if (instance == null) {
-                    throw new IllegalArgumentException("Instance " + name + " not found");
-                }
-                checkPid(instance);
-                if (instance.pid != 0) {
-                    throw new IllegalStateException("Instance is not stopped");
-                }
-                File f = new File(instance.loc, path);
-                FileLockUtils.execute(f, new FileLockUtils.RunnableWithProperties() {
-                    public void run(org.apache.felix.utils.properties.Properties properties) throws IOException {
-                        properties.put(key, Integer.toString(port));
-                    }
-                });
-                return null;
-            }
-        });
-    }
-
-    boolean isInstanceRoot(final String name) {
-        return execute(new Task<Boolean>() {
-            public Boolean call(State state) throws IOException {
-                InstanceState instance = state.instances.get(name);
-                if (instance == null) {
-                    throw new IllegalArgumentException("Instance " + name + " not found");
-                }
-                return instance.root;
-            }
-        });
-    }
-
-    String getInstanceLocation(final String name) {
-        return execute(new Task<String>() {
-            public String call(State state) throws IOException {
-                InstanceState instance = state.instances.get(name);
-                if (instance == null) {
-                    throw new IllegalArgumentException("Instance " + name + " not found");
-                }
-                return instance.loc;
-            }
-        });
-    }
-
-    int getInstancePid(final String name) {
-        return execute(new Task<Integer>() {
-            public Integer call(State state) throws IOException {
-                InstanceState instance = state.instances.get(name);
-                if (instance == null) {
-                    throw new IllegalArgumentException("Instance " + name + " not found");
-                }
-                checkPid(instance);
-                return instance.pid;
-            }
-        });
-    }
-
-    String getInstanceJavaOpts(final String name) {
-        return execute(new Task<String>() {
-            public String call(State state) throws IOException {
-                InstanceState instance = state.instances.get(name);
-                if (instance == null) {
-                    throw new IllegalArgumentException("Instance " + name + " not found");
-                }
-                return instance.opts;
-            }
-        });
-    }
-
-    void changeInstanceJavaOpts(final String name, final String opts) {
-        execute(new Task<String>() {
-            public String call(State state) throws IOException {
-                InstanceState instance = state.instances.get(name);
-                if (instance == null) {
-                    throw new IllegalArgumentException("Instance " + name + " not found");
-                }
-                instance.opts = opts;
-                return null;
-            }
-        });
-    }
-
-    String getInstanceState(final String name) {
-        return execute(new Task<String>() {
-            public String call(State state) throws IOException {
-                InstanceState instance = state.instances.get(name);
-                if (instance == null) {
-                    throw new IllegalArgumentException("Instance " + name + " not found");
-                }
-                int port = getKarafPort(state, name, "etc/org.apache.karaf.shell.cfg", "sshPort");
-                if (!new File(instance.loc).isDirectory() || port <= 0) {
-                    return Instance.ERROR;
-                }
-                checkPid(instance);
-                if (instance.pid == 0) {
-                    return Instance.STOPPED;
-                } else {
-                    try {
-                        Socket s = new Socket("localhost", port);
-                        s.close();
-                        return Instance.STARTED;
-                    } catch (Exception e) {
-                        // ignore
-                    }
-                    return Instance.STARTING;
-                }
-            }
-        });
-    }
-
-    private boolean deleteFile(File fileToDelete) {
-        if (fileToDelete == null || !fileToDelete.exists()) {
-            return true;
-        }
-        boolean result = true;
-        if (fileToDelete.isDirectory()) {
-            File[] files = fileToDelete.listFiles();
-            if (files == null) {
-                result = false;
-            } else {
-                for (int i = 0; i < files.length; i++) {
-                    File file = files[i];
-                    if (file.getName().equals(".") || file.getName().equals("..")) {
-                        continue;
-                    }
-                    if (file.isDirectory()) {
-                        result &= deleteFile(file);
-                    } else {
-                        result &= file.delete();
-                    }
-                }
-            }
-        }
-        result &= fileToDelete.delete();
-        return result;
-    }
-
-    private void copyResourceToDir(File target, String resource, boolean printOutput) throws IOException {
-        File outFile = new File(target, resource);
-        if( !outFile.exists() ) {
-            logInfo("Creating file: %s", printOutput, outFile.getPath());
-            InputStream is = getClass().getClassLoader().getResourceAsStream("org/apache/karaf/instance/resources/" + resource);
-            try {
-                // Read it line at a time so that we can use the platform line ending when we write it out.
-                PrintStream out = new PrintStream(new FileOutputStream(outFile));
-                try {
-                    Scanner scanner = new Scanner(is);
-                    while (scanner.hasNextLine() ) {
-                        String line = scanner.nextLine();
-                        out.println(line);
-                    }
-                } finally {
-                    safeClose(out);
-                }
-            } finally {
-                safeClose(is);
-            }
-        }
-    }
-
-    private void println(String st) {
-        System.out.println(st);
-    }
-
-    protected static Properties loadPropertiesFile(URL configPropURL) throws Exception {
-        // Read the properties file.
-        Properties configProps = new Properties();
-        InputStream is = null;
-        try {
-            is = configPropURL.openConnection().getInputStream();
-            configProps.load(is);
-            is.close();
-        }
-        catch (Exception ex) {
-            System.err.println(
-                    "Error loading config properties from " + configPropURL);
-            System.err.println("Main: " + ex);
-            try {
-                if (is != null) is.close();
-            }
-            catch (IOException ex2) {
-                // Nothing we can do.
-            }
-            return null;
-        }
-        return configProps;
-    }
-
-    private void filterResource(File basedir, String path, HashMap<String, String> props) throws IOException {
-        File file = new File(basedir, path);
-        File bak = new File(basedir, path + BACKUP_EXTENSION);
-        if (!file.exists()) {
-            return;
-        }
-        // rename the file to the backup one
-        file.renameTo(bak);
-        // copy and filter the bak file back to the original name
-        copyAndFilterResource(new FileInputStream(bak), new FileOutputStream(file), props);
-        // remove the bak file
-        bak.delete();
-    }
-
-    private void copyFilteredResourceToDir(File target, String resource, HashMap<String, String> props, boolean printOutput) throws IOException {
-        File outFile = new File(target, resource);
-        if( !outFile.exists() ) {
-            logInfo("Creating file: %s", printOutput, outFile.getPath());
-            InputStream is = getClass().getClassLoader().getResourceAsStream("org/apache/karaf/instance/resources/" + resource);
-            copyAndFilterResource(is, new FileOutputStream(outFile), props);
-        }
-    }
-
-    private void copyAndFilterResource(InputStream source, OutputStream target, HashMap<String, String> props) throws IOException {
-        try {
-            // read it line at a time so that we can use the platform line ending when we write it out.
-            PrintStream out = new PrintStream(target);
-            try {
-                Scanner scanner = new Scanner(source);
-                while (scanner.hasNextLine()) {
-                    String line = scanner.nextLine();
-                    line = filter(line, props);
-                    out.println(line);
-                }
-            } finally {
-                safeClose(out);
-            }
-        } finally {
-            safeClose(source);
-        }
-    }
-
-    private void safeClose(InputStream is) throws IOException {
-        if (is == null) {
-            return;
-        }
-        try {
-            is.close();
-        } catch (Throwable ignore) {
-        }
-    }
-
-    private void safeClose(OutputStream is) throws IOException {
-        if (is == null) {
-            return;
-        }
-        try {
-            is.close();
-        } catch (Throwable ignore) {
-        }
-    }
-
-    private String filter(String line, HashMap<String, String> props) {
-        for (Map.Entry<String, String> i : props.entrySet()) {
-            int p1 = line.indexOf(i.getKey());
-            if( p1 >= 0 ) {
-                String l1 = line.substring(0, p1);
-                String l2 = line.substring(p1+i.getKey().length());
-                line = l1+i.getValue()+l2;
-            }
-        }
-        return line;
-    }
-
-    private void mkdir(File karafBase, String path, boolean printOutput) {
-        File file = new File(karafBase, path);
-        if( !file.exists() ) {
-            logInfo("Creating dir: %s", printOutput, file.getPath());
-            file.mkdirs();
-        }
-    }
-
-    private int chmod(File serviceFile, String mode) throws IOException {
-        java.lang.ProcessBuilder builder = new java.lang.ProcessBuilder();
-        builder.command("chmod", mode, serviceFile.getCanonicalPath());
-        java.lang.Process p = builder.start();
-
-        // gnodet: Fix SMX4KNL-46: cpu goes to 100% after running the 'admin create' command
-        // Not sure exactly what happens, but commenting the process io redirection seems
-        // to work around the problem.
-        //
-        //PumpStreamHandler handler = new PumpStreamHandler(io.inputStream, io.outputStream, io.errorStream);
-        //handler.attach(p);
-        //handler.start();
-        try {
-            return p.waitFor();
-        } catch (InterruptedException e) {
-            throw (IOException) new InterruptedIOException().initCause(e);
-        }
-        //handler.stop();
-    }
-
-    private void copy(File source, File destination) throws IOException {
-        if (source.getName().equals("cache.lock")) {
-            // ignore cache.lock file
-            return;
-        }
-        if (source.getName().equals("lock")) {
-            // ignore lock file
-            return;
-        }
-        if (source.getName().matches("transaction_\\d+\\.log")) {
-            // ignore active txlog files
-            return;
-        }
-        if (source.isDirectory()) {
-            if (!destination.exists()) {
-                destination.mkdirs();
-            }
-            String[] children = source.list();
-            for (String child : children) {
-                if (!child.contains("instances") && !child.contains("lib"))
-                    copy(new File(source, child), new File(destination, child));
-            }
-        } else {
-            InputStream in = new FileInputStream(source);
-            OutputStream out = new FileOutputStream(destination);
-            byte[] buffer = new byte[1024];
-            int length;
-            while ((length = in.read(buffer)) > 0) {
-                out.write(buffer, 0, length);
-            }
-            in.close();
-            out.close();
-        }
-    }
-
-    private static final String DELIM_START = "${";
-    private static final String DELIM_STOP = "}";
-
-    protected static String substVars(String val, String currentKey,
-                                      Map<String, String> cycleMap, Properties configProps)
-            throws IllegalArgumentException {
-        // If there is currently no cycle map, then create
-        // one for detecting cycles for this invocation.
-        if (cycleMap == null) {
-            cycleMap = new HashMap<String, String>();
-        }
-
-        // Put the current key in the cycle map.
-        cycleMap.put(currentKey, currentKey);
-
-        // Assume we have a value that is something like:
-        // "leading ${foo.${bar}} middle ${baz} trailing"
-
-        // Find the first ending '}' variable delimiter, which
-        // will correspond to the first deepest nested variable
-        // placeholder.
-        int stopDelim = val.indexOf(DELIM_STOP);
-
-        // Find the matching starting "${" variable delimiter
-        // by looping until we find a start delimiter that is
-        // greater than the stop delimiter we have found.
-        int startDelim = val.indexOf(DELIM_START);
-        while (stopDelim >= 0) {
-            int idx = val.indexOf(DELIM_START, startDelim + DELIM_START.length());
-            if ((idx < 0) || (idx > stopDelim)) {
-                break;
-            } else if (idx < stopDelim) {
-                startDelim = idx;
-            }
-        }
-
-        // If we do not have a start or stop delimiter, then just
-        // return the existing value.
-        if ((startDelim < 0) && (stopDelim < 0)) {
-            return val;
-        }
-        // At this point, we found a stop delimiter without a start,
-        // so throw an exception.
-        else if (((startDelim < 0) || (startDelim > stopDelim))
-                && (stopDelim >= 0)) {
-            throw new IllegalArgumentException(
-                    "stop delimiter with no start delimiter: "
-                            + val);
-        }
-
-        // At this point, we have found a variable placeholder so
-        // we must perform a variable substitution on it.
-        // Using the start and stop delimiter indices, extract
-        // the first, deepest nested variable placeholder.
-        String variable =
-                val.substring(startDelim + DELIM_START.length(), stopDelim);
-
-        // Verify that this is not a recursive variable reference.
-        if (cycleMap.get(variable) != null) {
-            throw new IllegalArgumentException(
-                    "recursive variable reference: " + variable);
-        }
-
-        // Get the value of the deepest nested variable placeholder.
-        // Try to configuration properties first.
-        String substValue = (configProps != null)
-                ? configProps.getProperty(variable, null)
-                : null;
-        if (substValue == null) {
-            // Ignore unknown property values.
-            substValue = System.getProperty(variable, "");
-        }
-
-        // Remove the found variable from the cycle map, since
-        // it may appear more than once in the value and we don't
-        // want such situations to appear as a recursive reference.
-        cycleMap.remove(variable);
-
-        // Append the leading characters, the substituted value of
-        // the variable, and the trailing characters to get the new
-        // value.
-        val = val.substring(0, startDelim)
-                + substValue
-                + val.substring(stopDelim + DELIM_STOP.length(), val.length());
-
-        // Now perform substitution again, since there could still
-        // be substitutions to make.
-        val = substVars(val, currentKey, cycleMap, configProps);
-
-        // Return the value.
-        return val;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/7c2db062/instance/core/src/main/java/org/apache/karaf/instance/core/internal/InstanceToTableMapper.java
----------------------------------------------------------------------
diff --git a/instance/core/src/main/java/org/apache/karaf/instance/core/internal/InstanceToTableMapper.java b/instance/core/src/main/java/org/apache/karaf/instance/core/internal/InstanceToTableMapper.java
deleted file mode 100644
index baaedaf..0000000
--- a/instance/core/src/main/java/org/apache/karaf/instance/core/internal/InstanceToTableMapper.java
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * 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.karaf.instance.core.internal;
-
-import java.util.List;
-
-import javax.management.openmbean.CompositeDataSupport;
-import javax.management.openmbean.CompositeType;
-import javax.management.openmbean.OpenDataException;
-import javax.management.openmbean.OpenType;
-import javax.management.openmbean.SimpleType;
-import javax.management.openmbean.TabularData;
-import javax.management.openmbean.TabularDataSupport;
-import javax.management.openmbean.TabularType;
-
-import org.apache.karaf.instance.core.Instance;
-import org.apache.karaf.instance.core.InstancesMBean;
-
-public class InstanceToTableMapper {
-    
-    private InstanceToTableMapper() {
-    }
-
-    private static CompositeDataSupport mapInstance(Instance instance, CompositeType comp) throws OpenDataException {
-        String state;
-        try {
-            state = instance.getState();
-        } catch (Exception e) {
-            state = "Error";
-        }
-        Object[] itemValues = new Object[] {instance.getPid(), instance.getName(), instance.isRoot(),
-                                            instance.getSshPort(), instance.getRmiRegistryPort(),
-                                            instance.getRmiServerPort(), state, instance.getLocation(),
-                                            instance.getJavaOpts()};
-        return new CompositeDataSupport(comp, InstancesMBean.INSTANCE, itemValues);
-    }
-
-    private static CompositeType createRowType() throws OpenDataException {
-        String desc = "This type describes Karaf instance";
-        OpenType<?>[] itemTypes = new OpenType[] {SimpleType.INTEGER, SimpleType.STRING, SimpleType.BOOLEAN,
-                                                  SimpleType.INTEGER, SimpleType.INTEGER, SimpleType.INTEGER,
-                                                  SimpleType.STRING, SimpleType.STRING, SimpleType.STRING};
-        String[] descriptions = new String[] {"The Process ID of the instance or 0 if not running",
-                                              "The name of the instance", "Whether the instance is root",
-                                              "The SSH port that can be used to connect to the instance",
-                                              "The RMI registry port that can be used to manage the instance",
-                                              "The RMI server port that can be used to manage the instance",
-                                              "The state of the instance", "The location of the instance",
-                                              "The Java options of the instance"};
-        CompositeType comp = new CompositeType("Instances", desc, InstancesMBean.INSTANCE, descriptions, itemTypes);
-        return comp;
-    }
-
-    public static TabularData tableFrom(List<Instance> instances) {
-        try {
-            CompositeType rowType = createRowType();
-            TabularType tableType = new TabularType("Instances", "Table of all Karaf instances", rowType,
-                                                    new String[] {InstancesMBean.INSTANCE_NAME});
-            TabularDataSupport table = new TabularDataSupport(tableType);
-            for (Instance instance : instances) {
-                CompositeDataSupport row = mapInstance(instance, rowType);
-                table.put(row);
-            }
-            return table;
-        } catch (OpenDataException e) {
-            throw new IllegalStateException("Error building instance table", e);
-        }
-    }
-}


[35/59] [abbrv] [KARAF-2852] Merge log/core and log/command

Posted by gn...@apache.org.
http://git-wip-us.apache.org/repos/asf/karaf/blob/7f1463c5/log/src/main/java/org/apache/karaf/log/core/internal/LruList.java
----------------------------------------------------------------------
diff --git a/log/src/main/java/org/apache/karaf/log/core/internal/LruList.java b/log/src/main/java/org/apache/karaf/log/core/internal/LruList.java
new file mode 100644
index 0000000..ea51b34
--- /dev/null
+++ b/log/src/main/java/org/apache/karaf/log/core/internal/LruList.java
@@ -0,0 +1,124 @@
+/*
+ * 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.karaf.log.core.internal;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.ops4j.pax.logging.spi.PaxAppender;
+import org.ops4j.pax.logging.spi.PaxLoggingEvent;
+
+/**
+ * A list that only keep the last N elements added
+ */
+public class LruList implements PaxAppender {
+
+    private PaxLoggingEvent[] elements;
+    private transient int start = 0;
+    private transient int end = 0;
+    private transient boolean full = false;
+    private final int maxElements;
+    private final List<PaxAppender> appenders;
+
+    public LruList(int size) {
+        if (size <= 0) {
+            throw new IllegalArgumentException("The size must be greater than 0");
+        }
+        elements = new PaxLoggingEvent[size];
+        maxElements = elements.length;
+        appenders = new ArrayList<PaxAppender>();
+    }
+
+    public synchronized int size() {
+        int size = 0;
+        if (end < start) {
+            size = maxElements - start + end;
+        } else if (end == start) {
+            size = (full ? maxElements : 0);
+        } else {
+            size = end - start;
+        }
+        return size;
+    }
+
+    public synchronized void clear() {
+        start = 0;
+        end = 0;
+        elements = new PaxLoggingEvent[maxElements];
+    }
+
+    public synchronized void add(PaxLoggingEvent element) {
+        if (null == element) {
+             throw new NullPointerException("Attempted to add null object to buffer");
+        }
+        if (size() == maxElements) {
+            Object e = elements[start];
+            if (null != e) {
+                elements[start++] = null;
+                if (start >= maxElements) {
+                    start = 0;
+                }
+                full = false;
+            }
+        }
+        elements[end++] = element;
+        if (end >= maxElements) {
+            end = 0;
+        }
+        if (end == start) {
+            full = true;
+        }
+        for (PaxAppender appender : appenders) {
+            try {
+                appender.doAppend(element);
+            } catch (Throwable t) {
+                // Ignore
+            }
+        }
+    }
+
+    public synchronized Iterable<PaxLoggingEvent> getElements() {
+        return getElements(size());
+    }
+
+    public synchronized Iterable<PaxLoggingEvent> getElements(int nb) {
+        int s = size();
+        nb = Math.min(Math.max(0, nb), s);
+        PaxLoggingEvent[] e = new PaxLoggingEvent[nb];
+        for (int i = 0; i < nb; i++) {
+            e[i] = elements[(i + s - nb + start) % maxElements];
+        }
+        return Arrays.asList(e);
+    }
+
+    public synchronized void addAppender(PaxAppender appender) {
+        this.appenders.add(appender);
+    }
+
+    public synchronized void removeAppender(PaxAppender appender) {
+        this.appenders.remove(appender);
+    }
+    
+    public void doAppend(PaxLoggingEvent event) {
+        event.getProperties(); // ensure MDC properties are copied
+        add(event);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/7f1463c5/log/src/main/java/org/apache/karaf/log/core/internal/layout/AbsoluteTimeDateFormat.java
----------------------------------------------------------------------
diff --git a/log/src/main/java/org/apache/karaf/log/core/internal/layout/AbsoluteTimeDateFormat.java b/log/src/main/java/org/apache/karaf/log/core/internal/layout/AbsoluteTimeDateFormat.java
new file mode 100644
index 0000000..8bb3ff3
--- /dev/null
+++ b/log/src/main/java/org/apache/karaf/log/core/internal/layout/AbsoluteTimeDateFormat.java
@@ -0,0 +1,142 @@
+/*
+ * 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.karaf.log.core.internal.layout;
+
+import java.text.DateFormat;
+import java.text.FieldPosition;
+import java.text.ParsePosition;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.TimeZone;
+
+/**
+ * Copied from log4j
+ */
+/**
+   Formats a {@link Date} in the format "HH:mm:ss,SSS" for example,
+   "15:49:37,459".
+
+   @since 0.7.5
+*/
+public class AbsoluteTimeDateFormat extends DateFormat {
+
+  /**
+     String constant used to specify {@link
+     org.apache.log4j.helpers.AbsoluteTimeDateFormat} in layouts. Current
+     value is <b>ABSOLUTE</b>.  */
+  public final static String ABS_TIME_DATE_FORMAT = "ABSOLUTE";
+
+  /**
+     String constant used to specify {@link
+     org.apache.log4j.helpers.DateTimeDateFormat} in layouts.  Current
+     value is <b>DATE</b>.
+  */
+  public final static String DATE_AND_TIME_DATE_FORMAT = "DATE";
+
+  /**
+     String constant used to specify {@link
+     org.apache.log4j.helpers.ISO8601DateFormat} in layouts. Current
+     value is <b>ISO8601</b>.
+  */
+  public final static String ISO8601_DATE_FORMAT = "ISO8601";
+
+  public
+  AbsoluteTimeDateFormat() {
+    setCalendar(Calendar.getInstance());
+  }
+
+  public
+  AbsoluteTimeDateFormat(TimeZone timeZone) {
+    setCalendar(Calendar.getInstance(timeZone));
+  }
+
+  private static long   previousTime;
+  private static char[] previousTimeWithoutMillis = new char[9]; // "HH:mm:ss."
+
+  /**
+     Appends to <code>sbuf</code> the time in the format
+     "HH:mm:ss,SSS" for example, "15:49:37,459"
+
+     @param date the date to format
+     @param sbuf the string buffer to write to
+     @param fieldPosition remains untouched
+    */
+  public
+  StringBuffer format(Date date, StringBuffer sbuf,
+		      FieldPosition fieldPosition) {
+
+    long now = date.getTime();
+    int millis = (int)(now % 1000);
+
+    if ((now - millis) != previousTime) {
+      // We reach this point at most once per second
+      // across all threads instead of each time format()
+      // is called. This saves considerable CPU time.
+
+      calendar.setTime(date);
+
+      int start = sbuf.length();
+
+      int hour = calendar.get(Calendar.HOUR_OF_DAY);
+      if(hour < 10) {
+	sbuf.append('0');
+      }
+      sbuf.append(hour);
+      sbuf.append(':');
+
+      int mins = calendar.get(Calendar.MINUTE);
+      if(mins < 10) {
+	sbuf.append('0');
+      }
+      sbuf.append(mins);
+      sbuf.append(':');
+
+      int secs = calendar.get(Calendar.SECOND);
+      if(secs < 10) {
+	sbuf.append('0');
+      }
+      sbuf.append(secs);
+      sbuf.append(',');
+
+      // store the time string for next time to avoid recomputation
+      sbuf.getChars(start, sbuf.length(), previousTimeWithoutMillis, 0);
+
+      previousTime = now - millis;
+    }
+    else {
+      sbuf.append(previousTimeWithoutMillis);
+    }
+
+
+
+    if(millis < 100)
+      sbuf.append('0');
+    if(millis < 10)
+      sbuf.append('0');
+
+    sbuf.append(millis);
+    return sbuf;
+  }
+
+  /**
+     This method does not do anything but return <code>null</code>.
+   */
+  public
+  Date parse(String s, ParsePosition pos) {
+    return null;
+  }
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/7f1463c5/log/src/main/java/org/apache/karaf/log/core/internal/layout/DateTimeDateFormat.java
----------------------------------------------------------------------
diff --git a/log/src/main/java/org/apache/karaf/log/core/internal/layout/DateTimeDateFormat.java b/log/src/main/java/org/apache/karaf/log/core/internal/layout/DateTimeDateFormat.java
new file mode 100644
index 0000000..1aa884d
--- /dev/null
+++ b/log/src/main/java/org/apache/karaf/log/core/internal/layout/DateTimeDateFormat.java
@@ -0,0 +1,85 @@
+/*
+ * 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.karaf.log.core.internal.layout;
+
+import java.text.DateFormatSymbols;
+import java.text.FieldPosition;
+import java.text.ParsePosition;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.TimeZone;
+
+/**
+ * Copied from log4j
+ */
+/**
+   Formats a {@link Date} in the format "dd MMM yyyy HH:mm:ss,SSS" for example,
+   "06 Nov 1994 15:49:37,459".
+
+   @since 0.7.5
+*/
+public class DateTimeDateFormat extends AbsoluteTimeDateFormat {
+
+  String[] shortMonths;
+
+  public
+  DateTimeDateFormat() {
+    super();
+    shortMonths = new DateFormatSymbols().getShortMonths();
+  }
+
+  public
+  DateTimeDateFormat(TimeZone timeZone) {
+    this();
+    setCalendar(Calendar.getInstance(timeZone));
+  }
+
+  /**
+     Appends to <code>sbuf</code> the date in the format "dd MMM yyyy
+     HH:mm:ss,SSS" for example, "06 Nov 1994 08:49:37,459".
+
+     @param sbuf the string buffer to write to
+  */
+  public
+  StringBuffer format(Date date, StringBuffer sbuf,
+		      FieldPosition fieldPosition) {
+
+    calendar.setTime(date);
+
+    int day = calendar.get(Calendar.DAY_OF_MONTH);
+    if(day < 10)
+      sbuf.append('0');
+    sbuf.append(day);
+    sbuf.append(' ');
+    sbuf.append(shortMonths[calendar.get(Calendar.MONTH)]);
+    sbuf.append(' ');
+
+    int year =  calendar.get(Calendar.YEAR);
+    sbuf.append(year);
+    sbuf.append(' ');
+
+    return super.format(date, sbuf, fieldPosition);
+  }
+
+  /**
+     This method does not do anything but return <code>null</code>.
+   */
+  public
+  Date parse(java.lang.String s, ParsePosition pos) {
+    return null;
+  }
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/7f1463c5/log/src/main/java/org/apache/karaf/log/core/internal/layout/FormattingInfo.java
----------------------------------------------------------------------
diff --git a/log/src/main/java/org/apache/karaf/log/core/internal/layout/FormattingInfo.java b/log/src/main/java/org/apache/karaf/log/core/internal/layout/FormattingInfo.java
new file mode 100644
index 0000000..6fd728f
--- /dev/null
+++ b/log/src/main/java/org/apache/karaf/log/core/internal/layout/FormattingInfo.java
@@ -0,0 +1,44 @@
+/*
+ * 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.karaf.log.core.internal.layout;
+
+
+/**
+ * Copied from log4j
+ */
+/**
+   FormattingInfo instances contain the information obtained when parsing
+   formatting modifiers in conversion modifiers.
+
+   @since 0.8.2
+ */
+public class FormattingInfo {
+  int min = -1;
+  int max = 0x7FFFFFFF;
+  boolean leftAlign = false;
+
+  void reset() {
+    min = -1;
+    max = 0x7FFFFFFF;
+    leftAlign = false;
+  }
+
+  void dump() {
+    //LogLog.debug("min="+min+", max="+max+", leftAlign="+leftAlign);
+  }
+}
+

http://git-wip-us.apache.org/repos/asf/karaf/blob/7f1463c5/log/src/main/java/org/apache/karaf/log/core/internal/layout/ISO8601DateFormat.java
----------------------------------------------------------------------
diff --git a/log/src/main/java/org/apache/karaf/log/core/internal/layout/ISO8601DateFormat.java b/log/src/main/java/org/apache/karaf/log/core/internal/layout/ISO8601DateFormat.java
new file mode 100644
index 0000000..80155a0
--- /dev/null
+++ b/log/src/main/java/org/apache/karaf/log/core/internal/layout/ISO8601DateFormat.java
@@ -0,0 +1,152 @@
+/*
+ * 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.karaf.log.core.internal.layout;
+
+import java.text.FieldPosition;
+import java.text.ParsePosition;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.TimeZone;
+
+/**
+ * Copied from log4j
+ */
+// Contributors: Arndt Schoenewald <ar...@ibm23093i821.mc.schoenewald.de>
+/**
+   Formats a {@link Date} in the format "yyyy-MM-dd HH:mm:ss,SSS" for example
+   "1999-11-27 15:49:37,459".
+
+   <p>Refer to the <a
+   href=http://www.cl.cam.ac.uk/~mgk25/iso-time.html>summary of the
+   International Standard Date and Time Notation</a> for more
+   information on this format.
+
+   @since 0.7.5
+*/
+public class ISO8601DateFormat extends AbsoluteTimeDateFormat {
+
+  public
+  ISO8601DateFormat() {
+  }
+
+  public
+  ISO8601DateFormat(TimeZone timeZone) {
+    super(timeZone);
+  }
+
+  static private long   lastTime;
+  static private char[] lastTimeString = new char[20];
+
+  /**
+     Appends a date in the format "YYYY-mm-dd HH:mm:ss,SSS"
+     to <code>sbuf</code>. For example: "1999-11-27 15:49:37,459".
+
+     @param sbuf the <code>StringBuffer</code> to write to
+  */
+  public
+  StringBuffer format(Date date, StringBuffer sbuf,
+		      FieldPosition fieldPosition) {
+
+    long now = date.getTime();
+    int millis = (int)(now % 1000);
+
+    if ((now - millis) != lastTime) {
+      // We reach this point at most once per second
+      // across all threads instead of each time format()
+      // is called. This saves considerable CPU time.
+
+      calendar.setTime(date);
+
+      int start = sbuf.length();
+
+      int year =  calendar.get(Calendar.YEAR);
+      sbuf.append(year);
+
+      String month;
+      switch(calendar.get(Calendar.MONTH)) {
+      case Calendar.JANUARY: month = "-01-"; break;
+      case Calendar.FEBRUARY: month = "-02-";  break;
+      case Calendar.MARCH: month = "-03-"; break;
+      case Calendar.APRIL: month = "-04-";  break;
+      case Calendar.MAY: month = "-05-"; break;
+      case Calendar.JUNE: month = "-06-";  break;
+      case Calendar.JULY: month = "-07-"; break;
+      case Calendar.AUGUST: month = "-08-";  break;
+      case Calendar.SEPTEMBER: month = "-09-"; break;
+      case Calendar.OCTOBER: month = "-10-"; break;
+      case Calendar.NOVEMBER: month = "-11-";  break;
+      case Calendar.DECEMBER: month = "-12-";  break;
+      default: month = "-NA-"; break;
+      }
+      sbuf.append(month);
+
+      int day = calendar.get(Calendar.DAY_OF_MONTH);
+      if(day < 10)
+	sbuf.append('0');
+      sbuf.append(day);
+
+      sbuf.append(' ');
+
+      int hour = calendar.get(Calendar.HOUR_OF_DAY);
+      if(hour < 10) {
+	sbuf.append('0');
+      }
+      sbuf.append(hour);
+      sbuf.append(':');
+
+      int mins = calendar.get(Calendar.MINUTE);
+      if(mins < 10) {
+	sbuf.append('0');
+      }
+      sbuf.append(mins);
+      sbuf.append(':');
+
+      int secs = calendar.get(Calendar.SECOND);
+      if(secs < 10) {
+	sbuf.append('0');
+      }
+      sbuf.append(secs);
+
+      sbuf.append(',');
+
+      // store the time string for next time to avoid recomputation
+      sbuf.getChars(start, sbuf.length(), lastTimeString, 0);
+      lastTime = now - millis;
+    }
+    else {
+      sbuf.append(lastTimeString);
+    }
+
+
+    if (millis < 100)
+      sbuf.append('0');
+    if (millis < 10)
+      sbuf.append('0');
+
+    sbuf.append(millis);
+    return sbuf;
+  }
+
+  /**
+    This method does not do anything but return <code>null</code>.
+   */
+  public
+  Date parse(java.lang.String s, ParsePosition pos) {
+    return null;
+  }
+}
+

http://git-wip-us.apache.org/repos/asf/karaf/blob/7f1463c5/log/src/main/java/org/apache/karaf/log/core/internal/layout/PatternConverter.java
----------------------------------------------------------------------
diff --git a/log/src/main/java/org/apache/karaf/log/core/internal/layout/PatternConverter.java b/log/src/main/java/org/apache/karaf/log/core/internal/layout/PatternConverter.java
new file mode 100644
index 0000000..0d91e8c
--- /dev/null
+++ b/log/src/main/java/org/apache/karaf/log/core/internal/layout/PatternConverter.java
@@ -0,0 +1,106 @@
+/*
+ * 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.karaf.log.core.internal.layout;
+
+import org.ops4j.pax.logging.spi.PaxLoggingEvent;
+
+/**
+   <p>PatternConverter is an abtract class that provides the
+   formatting functionality that derived classes need.
+
+   <p>Conversion specifiers in a conversion patterns are parsed to
+   individual PatternConverters. Each of which is responsible for
+   converting a logging event in a converter specific manner.
+
+   @since 0.8.2
+ */
+public abstract class PatternConverter {
+  public PatternConverter next;
+  int min = -1;
+  int max = 0x7FFFFFFF;
+  boolean leftAlign = false;
+
+  protected
+  PatternConverter() {  }
+
+  protected
+  PatternConverter(FormattingInfo fi) {
+    min = fi.min;
+    max = fi.max;
+    leftAlign = fi.leftAlign;
+  }
+
+  /**
+     Derived pattern converters must override this method in order to
+     convert conversion specifiers in the correct way.
+  */
+  abstract
+  protected
+  String convert(PaxLoggingEvent event);
+
+  /**
+     A template method for formatting in a converter specific way.
+   */
+  public
+  void format(StringBuffer sbuf, PaxLoggingEvent e) {
+    String s = convert(e);
+
+    if(s == null) {
+      if(0 < min)
+	spacePad(sbuf, min);
+      return;
+    }
+
+    int len = s.length();
+
+    if(len > max)
+      sbuf.append(s.substring(len-max));
+    else if(len < min) {
+      if(leftAlign) {
+	sbuf.append(s);
+	spacePad(sbuf, min-len);
+      }
+      else {
+	spacePad(sbuf, min-len);
+	sbuf.append(s);
+      }
+    }
+    else
+      sbuf.append(s);
+  }
+
+  static String[] SPACES = {" ", "  ", "    ", "        ", //1,2,4,8 spaces
+			    "                ", // 16 spaces
+			    "                                " }; // 32 spaces
+
+  /**
+     Fast space padding method.
+  */
+  public
+  void spacePad(StringBuffer sbuf, int length) {
+    while(length >= 32) {
+      sbuf.append(SPACES[5]);
+      length -= 32;
+    }
+
+    for(int i = 4; i >= 0; i--) {
+      if((length & (1<<i)) != 0) {
+	sbuf.append(SPACES[i]);
+      }
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/7f1463c5/log/src/main/java/org/apache/karaf/log/core/internal/layout/PatternParser.java
----------------------------------------------------------------------
diff --git a/log/src/main/java/org/apache/karaf/log/core/internal/layout/PatternParser.java b/log/src/main/java/org/apache/karaf/log/core/internal/layout/PatternParser.java
new file mode 100644
index 0000000..f61b278
--- /dev/null
+++ b/log/src/main/java/org/apache/karaf/log/core/internal/layout/PatternParser.java
@@ -0,0 +1,560 @@
+/*
+ * 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.karaf.log.core.internal.layout;
+
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.Map;
+
+import org.apache.log4j.spi.LoggingEvent;
+import org.ops4j.pax.logging.spi.PaxLocationInfo;
+import org.ops4j.pax.logging.spi.PaxLoggingEvent;
+
+/**
+ * Copied from log4j
+ */
+/**
+   Most of the work of the {@link org.apache.log4j.PatternLayout} class
+   is delegated to the PatternParser class.
+
+   @since 0.8.2
+*/
+public class PatternParser {
+
+  private static final String LINE_SEP = System.getProperty("line.separator");
+
+  private static final char ESCAPE_CHAR = '%';
+
+  private static final int LITERAL_STATE = 0;
+  private static final int CONVERTER_STATE = 1;
+  private static final int MINUS_STATE = 2;
+  private static final int DOT_STATE = 3;
+  private static final int MIN_STATE = 4;
+  private static final int MAX_STATE = 5;
+
+  static final int FULL_LOCATION_CONVERTER = 1000;
+  static final int METHOD_LOCATION_CONVERTER = 1001;
+  static final int CLASS_LOCATION_CONVERTER = 1002;
+  static final int LINE_LOCATION_CONVERTER = 1003;
+  static final int FILE_LOCATION_CONVERTER = 1004;
+
+  static final int RELATIVE_TIME_CONVERTER = 2000;
+  static final int THREAD_CONVERTER = 2001;
+  static final int LEVEL_CONVERTER = 2002;
+  static final int NDC_CONVERTER = 2003;
+  static final int MESSAGE_CONVERTER = 2004;
+
+  int state;
+  protected StringBuffer currentLiteral = new StringBuffer(32);
+  protected int patternLength;
+  protected int i;
+  PatternConverter head;
+  PatternConverter tail;
+  protected FormattingInfo formattingInfo = new FormattingInfo();
+  protected String pattern;
+
+  public
+  PatternParser(String pattern) {
+    this.pattern = pattern;
+    patternLength =  pattern.length();
+    state = LITERAL_STATE;
+  }
+
+  private
+  void  addToList(PatternConverter pc) {
+    if(head == null) {
+      head = tail = pc;
+    } else {
+      tail.next = pc;
+      tail = pc;
+    }
+  }
+
+  protected
+  String extractOption() {
+    if((i < patternLength) && (pattern.charAt(i) == '{')) {
+      int end = pattern.indexOf('}', i);
+      if (end > i) {
+	String r = pattern.substring(i + 1, end);
+	i = end+1;
+	return r;
+      }
+    }
+    return null;
+  }
+
+
+  /**
+     The option is expected to be in decimal and positive. In case of
+     error, zero is returned.  */
+  protected
+  int extractPrecisionOption() {
+    String opt = extractOption();
+    int r = 0;
+    if(opt != null) {
+      try {
+	r = Integer.parseInt(opt);
+	if(r <= 0) {
+	    //LogLog.error("Precision option (" + opt + ") isn't a positive integer.");
+	    r = 0;
+	}
+      }
+      catch (NumberFormatException e) {
+	//LogLog.error("Category option \""+opt+"\" not a decimal integer.", e);
+      }
+    }
+    return r;
+  }
+
+  public
+  PatternConverter parse() {
+    char c;
+    i = 0;
+    while(i < patternLength) {
+      c = pattern.charAt(i++);
+      switch(state) {
+      case LITERAL_STATE:
+        // In literal state, the last char is always a literal.
+        if(i == patternLength) {
+          currentLiteral.append(c);
+          continue;
+        }
+        if(c == ESCAPE_CHAR) {
+          // peek at the next char.
+          switch(pattern.charAt(i)) {
+          case ESCAPE_CHAR:
+            currentLiteral.append(c);
+            i++; // move pointer
+            break;
+          case 'n':
+            currentLiteral.append(LINE_SEP);
+            i++; // move pointer
+            break;
+          default:
+            if(currentLiteral.length() != 0) {
+              addToList(new LiteralPatternConverter(
+                                                  currentLiteral.toString()));
+              //LogLog.debug("Parsed LITERAL converter: \""
+              //           +currentLiteral+"\".");
+            }
+            currentLiteral.setLength(0);
+            currentLiteral.append(c); // append %
+            state = CONVERTER_STATE;
+            formattingInfo.reset();
+          }
+        }
+        else {
+          currentLiteral.append(c);
+        }
+        break;
+      case CONVERTER_STATE:
+	currentLiteral.append(c);
+	switch(c) {
+	case '-':
+	  formattingInfo.leftAlign = true;
+	  break;
+	case '.':
+	  state = DOT_STATE;
+	  break;
+	default:
+	  if(c >= '0' && c <= '9') {
+	    formattingInfo.min = c - '0';
+	    state = MIN_STATE;
+	  }
+	  else
+	    finalizeConverter(c);
+	} // switch
+	break;
+      case MIN_STATE:
+	currentLiteral.append(c);
+	if(c >= '0' && c <= '9')
+	  formattingInfo.min = formattingInfo.min*10 + (c - '0');
+	else if(c == '.')
+	  state = DOT_STATE;
+	else {
+	  finalizeConverter(c);
+	}
+	break;
+      case DOT_STATE:
+	currentLiteral.append(c);
+	if(c >= '0' && c <= '9') {
+	  formattingInfo.max = c - '0';
+	   state = MAX_STATE;
+	}
+	else {
+	  //LogLog.error("Error occured in position "+i+".\n Was expecting digit, instead got char \""+c+"\".");
+	  state = LITERAL_STATE;
+	}
+	break;
+      case MAX_STATE:
+	currentLiteral.append(c);
+	if(c >= '0' && c <= '9')
+	  formattingInfo.max = formattingInfo.max*10 + (c - '0');
+	else {
+	  finalizeConverter(c);
+	  state = LITERAL_STATE;
+	}
+	break;
+      } // switch
+    } // while
+    if(currentLiteral.length() != 0) {
+      addToList(new LiteralPatternConverter(currentLiteral.toString()));
+      //LogLog.debug("Parsed LITERAL converter: \""+currentLiteral+"\".");
+    }
+    return head;
+  }
+
+  protected
+  void finalizeConverter(char c) {
+    PatternConverter pc = null;
+    switch(c) {
+    case 'c':
+      pc = new CategoryPatternConverter(formattingInfo,
+					extractPrecisionOption());
+      //LogLog.debug("CATEGORY converter.");
+      //formattingInfo.dump();
+      currentLiteral.setLength(0);
+      break;
+    case 'C':
+      pc = new ClassNamePatternConverter(formattingInfo,
+					 extractPrecisionOption());
+      //LogLog.debug("CLASS_NAME converter.");
+      //formattingInfo.dump();
+      currentLiteral.setLength(0);
+      break;
+    case 'd':
+      String dateFormatStr = AbsoluteTimeDateFormat.ISO8601_DATE_FORMAT;
+      DateFormat df;
+      String dOpt = extractOption();
+      if(dOpt != null)
+	dateFormatStr = dOpt;
+
+      if(dateFormatStr.equalsIgnoreCase(
+                                    AbsoluteTimeDateFormat.ISO8601_DATE_FORMAT))
+	df = new  ISO8601DateFormat();
+      else if(dateFormatStr.equalsIgnoreCase(
+                                   AbsoluteTimeDateFormat.ABS_TIME_DATE_FORMAT))
+	df = new AbsoluteTimeDateFormat();
+      else if(dateFormatStr.equalsIgnoreCase(
+                              AbsoluteTimeDateFormat.DATE_AND_TIME_DATE_FORMAT))
+	df = new DateTimeDateFormat();
+      else {
+	try {
+	  df = new SimpleDateFormat(dateFormatStr);
+	}
+	catch (IllegalArgumentException e) {
+	  //LogLog.error("Could not instantiate SimpleDateFormat with " + dateFormatStr, e);
+	  df = new ISO8601DateFormat();
+	}
+      }
+      pc = new DatePatternConverter(formattingInfo, df);
+      //LogLog.debug("DATE converter {"+dateFormatStr+"}.");
+      //formattingInfo.dump();
+      currentLiteral.setLength(0);
+      break;
+    case 'F':
+      pc = new LocationPatternConverter(formattingInfo,
+					FILE_LOCATION_CONVERTER);
+      //LogLog.debug("File name converter.");
+      //formattingInfo.dump();
+      currentLiteral.setLength(0);
+      break;
+    /*case 'l':
+      pc = new LocationPatternConverter(formattingInfo,
+					FULL_LOCATION_CONVERTER);
+      //LogLog.debug("Location converter.");
+      //formattingInfo.dump();
+      currentLiteral.setLength(0);
+      break;*/
+    case 'L':
+      pc = new LocationPatternConverter(formattingInfo,
+					LINE_LOCATION_CONVERTER);
+      //LogLog.debug("LINE NUMBER converter.");
+      //formattingInfo.dump();
+      currentLiteral.setLength(0);
+      break;
+    case 'm':
+      pc = new BasicPatternConverter(formattingInfo, MESSAGE_CONVERTER);
+      //LogLog.debug("MESSAGE converter.");
+      //formattingInfo.dump();
+      currentLiteral.setLength(0);
+      break;
+    case 'M':
+      pc = new LocationPatternConverter(formattingInfo,
+					METHOD_LOCATION_CONVERTER);
+      //LogLog.debug("METHOD converter.");
+      //formattingInfo.dump();
+      currentLiteral.setLength(0);
+      break;
+    case 'p':
+      pc = new BasicPatternConverter(formattingInfo, LEVEL_CONVERTER);
+      //LogLog.debug("LEVEL converter.");
+      //formattingInfo.dump();
+      currentLiteral.setLength(0);
+      break;
+    case 'r':
+      pc = new BasicPatternConverter(formattingInfo,
+					 RELATIVE_TIME_CONVERTER);
+      //LogLog.debug("RELATIVE time converter.");
+      //formattingInfo.dump();
+      currentLiteral.setLength(0);
+      break;
+    case 't':
+      pc = new BasicPatternConverter(formattingInfo, THREAD_CONVERTER);
+      //LogLog.debug("THREAD converter.");
+      //formattingInfo.dump();
+      currentLiteral.setLength(0);
+      break;
+      /*case 'u':
+      if(i < patternLength) {
+	char cNext = pattern.charAt(i);
+	if(cNext >= '0' && cNext <= '9') {
+	  pc = new UserFieldPatternConverter(formattingInfo, cNext - '0');
+	  LogLog.debug("USER converter ["+cNext+"].");
+	  formattingInfo.dump();
+	  currentLiteral.setLength(0);
+	  i++;
+	}
+	else
+	  LogLog.error("Unexpected char" +cNext+" at position "+i);
+      }
+      break;*/
+    /*case 'x':
+      pc = new BasicPatternConverter(formattingInfo, NDC_CONVERTER);
+      //LogLog.debug("NDC converter.");
+      currentLiteral.setLength(0);
+      break;*/
+    case 'X':
+      String xOpt = extractOption();
+      pc = new MDCPatternConverter(formattingInfo, xOpt);
+      currentLiteral.setLength(0);
+      break;
+    default:
+      //LogLog.error("Unexpected char [" +c+"] at position "+i+" in conversion patterrn.");
+      pc = new LiteralPatternConverter(currentLiteral.toString());
+      currentLiteral.setLength(0);
+    }
+
+    addConverter(pc);
+  }
+
+  protected
+  void addConverter(PatternConverter pc) {
+    currentLiteral.setLength(0);
+    // Add the pattern converter to the list.
+    addToList(pc);
+    // Next pattern is assumed to be a literal.
+    state = LITERAL_STATE;
+    // Reset formatting info
+    formattingInfo.reset();
+  }
+
+  // ---------------------------------------------------------------------
+  //                      PatternConverters
+  // ---------------------------------------------------------------------
+
+  private static class BasicPatternConverter extends PatternConverter {
+    int type;
+
+    BasicPatternConverter(FormattingInfo formattingInfo, int type) {
+      super(formattingInfo);
+      this.type = type;
+    }
+
+    public
+    String convert(PaxLoggingEvent event) {
+      switch(type) {
+      case RELATIVE_TIME_CONVERTER:
+	return (Long.toString(event.getTimeStamp() - LoggingEvent.getStartTime()));
+      case THREAD_CONVERTER:
+	return event.getThreadName();
+      case LEVEL_CONVERTER:
+	return event.getLevel().toString();
+    //  case NDC_CONVERTER:
+	//return event.getNDC();
+      case MESSAGE_CONVERTER: {
+	return event.getRenderedMessage();
+      }
+      default: return null;
+      }
+    }
+  }
+
+  private static class LiteralPatternConverter extends PatternConverter {
+    private String literal;
+
+    LiteralPatternConverter(String value) {
+      literal = value;
+    }
+
+    public
+    final
+    void format(StringBuffer sbuf, LoggingEvent event) {
+      sbuf.append(literal);
+    }
+
+    public
+    String convert(PaxLoggingEvent event) {
+      return literal;
+    }
+  }
+
+  private static class DatePatternConverter extends PatternConverter {
+    private DateFormat df;
+    private Date date;
+
+    DatePatternConverter(FormattingInfo formattingInfo, DateFormat df) {
+      super(formattingInfo);
+      date = new Date();
+      this.df = df;
+    }
+
+    public
+    String convert(PaxLoggingEvent event) {
+      date.setTime(event.getTimeStamp());
+      String converted = null;
+      try {
+        converted = df.format(date);
+      }
+      catch (Exception ex) {
+        //LogLog.error("Error occured while converting date.", ex);
+      }
+      return converted;
+    }
+  }
+
+  private class LocationPatternConverter extends PatternConverter {
+    int type;
+
+    LocationPatternConverter(FormattingInfo formattingInfo, int type) {
+      super(formattingInfo);
+      this.type = type;
+    }
+
+    public
+    String convert(PaxLoggingEvent event) {
+      PaxLocationInfo locationInfo = event.getLocationInformation();
+      switch(type) {
+      /*case FULL_LOCATION_CONVERTER:
+	return locationInfo.fullInfo;*/
+      case METHOD_LOCATION_CONVERTER:
+	return locationInfo.getMethodName();
+      case LINE_LOCATION_CONVERTER:
+	return locationInfo.getLineNumber();
+      case FILE_LOCATION_CONVERTER:
+	return locationInfo.getFileName();
+      default: return null;
+      }
+    }
+  }
+
+  private static abstract class NamedPatternConverter extends PatternConverter {
+    int precision;
+
+    NamedPatternConverter(FormattingInfo formattingInfo, int precision) {
+      super(formattingInfo);
+      this.precision =  precision;
+    }
+
+    abstract
+    String getFullyQualifiedName(PaxLoggingEvent event);
+
+    public
+    String convert(PaxLoggingEvent event) {
+      String n = getFullyQualifiedName(event);
+      if(precision <= 0)
+	return n;
+      else {
+	int len = n.length();
+
+	// We substract 1 from 'len' when assigning to 'end' to avoid out of
+	// bounds exception in return r.substring(end+1, len). This can happen if
+	// precision is 1 and the category name ends with a dot.
+	int end = len -1 ;
+	for(int i = precision; i > 0; i--) {
+	  end = n.lastIndexOf('.', end-1);
+	  if(end == -1)
+	    return n;
+	}
+	return n.substring(end+1, len);
+      }
+    }
+  }
+
+  private class ClassNamePatternConverter extends NamedPatternConverter {
+
+    ClassNamePatternConverter(FormattingInfo formattingInfo, int precision) {
+      super(formattingInfo, precision);
+    }
+
+    String getFullyQualifiedName(PaxLoggingEvent event) {
+      return event.getLocationInformation().getClassName();
+    }
+  }
+
+  private class CategoryPatternConverter extends NamedPatternConverter {
+
+    CategoryPatternConverter(FormattingInfo formattingInfo, int precision) {
+      super(formattingInfo, precision);
+    }
+
+    String getFullyQualifiedName(PaxLoggingEvent event) {
+      return event.getLoggerName();
+    }
+  }
+
+  private class MDCPatternConverter extends PatternConverter {
+    String key;
+
+    MDCPatternConverter(FormattingInfo formattingInfo, String key) {
+      super(formattingInfo);
+      this.key = key;
+    }
+
+    public
+    String convert(PaxLoggingEvent event) {
+        if (key == null) {
+            StringBuffer buf = new StringBuffer("{");
+            Map properties = event.getProperties();
+            if (properties.size() > 0) {
+              Object[] keys = properties.keySet().toArray();
+              Arrays.sort(keys);
+              for (int i = 0; i < keys.length; i++) {
+                  buf.append('{');
+                  buf.append(keys[i]);
+                  buf.append(',');
+                  buf.append(properties.get(keys[i]));
+                  buf.append('}');
+              }
+            }
+            buf.append('}');
+            return buf.toString();
+        } else {
+          Object val = event.getProperties().get(key);
+          if(val == null) {
+              return null;
+          } else {
+              return val.toString();
+          }
+        }
+    }
+
+  }
+}
+

http://git-wip-us.apache.org/repos/asf/karaf/blob/7f1463c5/log/src/main/java/org/apache/karaf/log/core/internal/osgi/Activator.java
----------------------------------------------------------------------
diff --git a/log/src/main/java/org/apache/karaf/log/core/internal/osgi/Activator.java b/log/src/main/java/org/apache/karaf/log/core/internal/osgi/Activator.java
new file mode 100644
index 0000000..2e8c4d8
--- /dev/null
+++ b/log/src/main/java/org/apache/karaf/log/core/internal/osgi/Activator.java
@@ -0,0 +1,77 @@
+/*
+ * 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.karaf.log.core.internal.osgi;
+
+import java.util.Hashtable;
+
+import org.apache.karaf.log.core.LogEventFormatter;
+import org.apache.karaf.log.core.LogService;
+import org.apache.karaf.log.core.internal.LogEventFormatterImpl;
+import org.apache.karaf.log.core.internal.LogMBeanImpl;
+import org.apache.karaf.log.core.internal.LogServiceImpl;
+import org.apache.karaf.log.core.internal.LruList;
+import org.apache.karaf.util.tracker.BaseActivator;
+import org.ops4j.pax.logging.spi.PaxAppender;
+import org.osgi.service.cm.ConfigurationAdmin;
+import org.osgi.service.cm.ManagedService;
+
+public class Activator extends BaseActivator implements ManagedService {
+
+    @Override
+    protected void doOpen() throws Exception {
+        manage("org.apache.karaf.log");
+        trackService(ConfigurationAdmin.class);
+    }
+
+    protected void doStart() throws Exception {
+        ConfigurationAdmin configurationAdmin = getTrackedService(ConfigurationAdmin.class);
+        if (configurationAdmin == null) {
+            return;
+        }
+
+        int size = getInt("size", 500);
+        String pattern = getString("pattern", "%d{ABSOLUTE} | %-5.5p | %-16.16t | %-32.32c{1} | %-32.32C %4L | %m%n");
+        String fatalColor = getString("fatalColor", "31");
+        String errorColor = getString("errorColor", "31");
+        String warnColor = getString("warnColor", "35");
+        String infoColor = getString("infoColor", "36");
+        String debugColor = getString("debugColor", "39");
+        String traceColor = getString("traceColor", "39");
+
+        LruList events = new LruList(size);
+        Hashtable<String, Object> props = new Hashtable<String, Object>();
+        props.put("org.ops4j.pax.logging.appender.name", "VmLogAppender");
+        register(PaxAppender.class, events, props);
+
+        LogEventFormatterImpl formatter = new LogEventFormatterImpl();
+        formatter.setPattern(pattern);
+        formatter.setFatalColor(fatalColor);
+        formatter.setErrorColor(errorColor);
+        formatter.setWarnColor(warnColor);
+        formatter.setInfoColor(infoColor);
+        formatter.setDebugColor(debugColor);
+        formatter.setTraceColor(traceColor);
+        register(LogEventFormatter.class, formatter);
+
+        LogServiceImpl logService = new LogServiceImpl(configurationAdmin, events);
+        register(LogService.class, logService);
+
+        LogMBeanImpl securityMBean = new LogMBeanImpl(logService);
+        registerMBean(securityMBean, "type=log");
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/7f1463c5/log/src/main/resources/OSGI-INF/bundle.info
----------------------------------------------------------------------
diff --git a/log/src/main/resources/OSGI-INF/bundle.info b/log/src/main/resources/OSGI-INF/bundle.info
new file mode 100644
index 0000000..2bd45bd
--- /dev/null
+++ b/log/src/main/resources/OSGI-INF/bundle.info
@@ -0,0 +1,24 @@
+h1. Synopsis
+
+${project.name}
+
+${project.description}
+
+Maven URL:
+[mvn:${project.groupId}/${project.artifactId}/${project.version}]
+
+h1. Description
+
+The log mbean management bundle exposes a Log MBean that can be used with any JMX client (for instance JConsole).
+
+The Log MBean allows quite the same actions that can be performed using log:* commands:
+  * display()
+  * display(logger)
+  * get()
+  * get(logger)
+  * set(level)
+  * list(level, logger)
+
+h1. See also
+
+  * Monitoring and Administration using JMX - section of the Karaf User Guide

http://git-wip-us.apache.org/repos/asf/karaf/blob/7f1463c5/log/src/main/resources/OSGI-INF/metatype/metatype.properties
----------------------------------------------------------------------
diff --git a/log/src/main/resources/OSGI-INF/metatype/metatype.properties b/log/src/main/resources/OSGI-INF/metatype/metatype.properties
new file mode 100644
index 0000000..713283f
--- /dev/null
+++ b/log/src/main/resources/OSGI-INF/metatype/metatype.properties
@@ -0,0 +1,31 @@
+#
+#  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.
+#
+
+#
+# This file contains localization strings for configuration labels and
+# descriptions as used in the metatype.xml descriptor
+
+log.name = Apache Karaf Log
+log.description = Configuration of Apache Karaf Log
+
+size.name = Size
+size.description = size of the log to keep in memory
+
+pattern.name = Pattern
+pattern.description = Pattern used to display log entries

http://git-wip-us.apache.org/repos/asf/karaf/blob/7f1463c5/log/src/main/resources/OSGI-INF/metatype/metatype.xml
----------------------------------------------------------------------
diff --git a/log/src/main/resources/OSGI-INF/metatype/metatype.xml b/log/src/main/resources/OSGI-INF/metatype/metatype.xml
new file mode 100644
index 0000000..147cb82
--- /dev/null
+++ b/log/src/main/resources/OSGI-INF/metatype/metatype.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    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.
+
+-->
+<metatype:MetaData xmlns:metatype="http://www.osgi.org/xmlns/metatype/v1.0.0" localization="OSGI-INF/metatype/metatype">
+    <OCD id="org.apache.karaf.log" name="%log.name" description="%log.description">
+        <AD id="size" type="Integer" default="500" name="%size.name"
+            description="%size.description"/>
+        <AD id="pattern" type="String" default="%d{ABSOLUTE} | %-5.5p | %-16.16t | %-32.32c{1} | %-32.32C %4L | %m%n" name="%pattern.name"
+            description="%pattern.description"/>
+    </OCD>
+    <Designate pid="org.apache.karaf.log">
+        <Object ocdref="org.apache.karaf.log"/>
+    </Designate>
+</metatype:MetaData>

http://git-wip-us.apache.org/repos/asf/karaf/blob/7f1463c5/log/src/test/java/org/apache/karaf/log/core/internal/SetLogLevelTest.java
----------------------------------------------------------------------
diff --git a/log/src/test/java/org/apache/karaf/log/core/internal/SetLogLevelTest.java b/log/src/test/java/org/apache/karaf/log/core/internal/SetLogLevelTest.java
new file mode 100644
index 0000000..73459d3
--- /dev/null
+++ b/log/src/test/java/org/apache/karaf/log/core/internal/SetLogLevelTest.java
@@ -0,0 +1,129 @@
+/*
+ * 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.karaf.log.core.internal;
+
+import java.util.Hashtable;
+
+import junit.framework.TestCase;
+
+import org.apache.karaf.log.core.LogMBean;
+import org.apache.karaf.log.core.LogService;
+import org.easymock.EasyMock;
+import org.osgi.service.cm.Configuration;
+import org.osgi.service.cm.ConfigurationAdmin;
+
+/**
+ * Test cases for {@link SetLogLevel}
+ */
+@SuppressWarnings("unchecked")
+public class SetLogLevelTest extends TestCase {
+    
+    private static final String ROOT_LOGGER = "log4j.rootLogger";
+    private static final String PACKAGE_LOGGER = "log4j.logger.org.apache.karaf.test";
+    
+    private LogService logService;
+    private LogMBean logMBean;
+    @SuppressWarnings("rawtypes")
+    private Hashtable properties;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        properties = new Hashtable<String, String>();
+        final Configuration configuration = EasyMock.createMock(Configuration.class);
+        EasyMock.expect(configuration.getProperties()).andReturn(properties);
+        configuration.update(properties);        
+        ConfigurationAdmin configAdmin = EasyMock.createMock(ConfigurationAdmin.class);
+        EasyMock.expect(configAdmin.getConfiguration(LogServiceImpl.CONFIGURATION_PID, null)).andReturn(configuration);
+        logService = new LogServiceImpl(configAdmin, new LruList(100));
+        logMBean = new LogMBeanImpl(logService);
+        EasyMock.replay(configAdmin);
+        EasyMock.replay(configuration);
+    }
+    
+    @Override
+    protected void tearDown() throws Exception {
+        super.tearDown();
+    }
+    
+    public void testInvalidLogLevel() throws Exception {
+        try {
+            logMBean.setLevel("INVALID");
+            fail("Exception expected");
+        } catch(IllegalArgumentException e) {
+            // Expected
+        }
+    }
+    
+    public void testSetLogLevel() throws Exception {
+        logMBean.setLevel("org.apache.karaf.test", "INFO");
+        assertEquals("INFO", properties.get(PACKAGE_LOGGER));
+    }
+    
+    public void testSetRootLogLevel() throws Exception {
+        logMBean.setLevel("INFO");
+        assertEquals("INFO", properties.get(ROOT_LOGGER));
+    }
+    
+    public void testSetLogLevelLowerCase() throws Exception {
+        logMBean.setLevel("org.apache.karaf.test", "info");
+        assertEquals("INFO", properties.get(PACKAGE_LOGGER));
+    }
+    
+    public void testSetRootLogLevelLowerCase() throws Exception {
+        logMBean.setLevel("info");
+        assertEquals("INFO", properties.get(ROOT_LOGGER));
+    }
+    
+    public void testChangeLogLevel() throws Exception {
+        properties.put(PACKAGE_LOGGER, "DEBUG");
+        logMBean.setLevel("org.apache.karaf.test", "INFO");
+        assertEquals("INFO", properties.get(PACKAGE_LOGGER));
+    }
+    
+    public void testChangeRootLogLevel() throws Exception {
+        properties.put(ROOT_LOGGER, "DEBUG");
+        logMBean.setLevel("INFO");
+        assertEquals("INFO", properties.get(ROOT_LOGGER));
+    }
+    
+    public void testChangeLogLevelWithAppender() throws Exception {
+        properties.put(PACKAGE_LOGGER, "DEBUG, APPENDER1");
+        logMBean.setLevel("org.apache.karaf.test", "INFO");
+        assertEquals("INFO, APPENDER1", properties.get(PACKAGE_LOGGER));
+    }
+    
+    public void testChangeRootLogLevelWithAppender() throws Exception {
+        properties.put(ROOT_LOGGER, "DEBUG, APPENDER1");
+        logMBean.setLevel("INFO");
+        assertEquals("INFO, APPENDER1", properties.get(ROOT_LOGGER));
+    }
+
+    public void testUnsetLogLevel() throws Exception {
+        properties.put(PACKAGE_LOGGER, "DEBUG");
+        logMBean.setLevel("org.apache.karaf.test", "DEFAULT");
+        assertFalse("Configuration for logger org.apache.karaf.test has been removed", properties.containsKey(PACKAGE_LOGGER));
+    }
+
+    public void testUnsetRootLogLevel() throws Exception {
+        properties.put(ROOT_LOGGER, "INFO");
+        logMBean.setLevel("org.apache.karaf.test", "DEFAULT");
+        assertEquals("Configuration for root logger should not be removed", "INFO", properties.get(ROOT_LOGGER));
+    }
+    
+}


[03/59] [abbrv] [KARAF-2852] Merge features/core and features/command

Posted by gn...@apache.org.
http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/src/main/java/org/apache/karaf/features/internal/service/Overrides.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/service/Overrides.java b/features/src/main/java/org/apache/karaf/features/internal/service/Overrides.java
new file mode 100644
index 0000000..233a8a2
--- /dev/null
+++ b/features/src/main/java/org/apache/karaf/features/internal/service/Overrides.java
@@ -0,0 +1,132 @@
+/*
+ * 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.karaf.features.internal.service;
+
+import java.io.BufferedReader;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.felix.utils.manifest.Clause;
+import org.apache.felix.utils.manifest.Parser;
+import org.apache.felix.utils.version.VersionRange;
+import org.osgi.framework.Version;
+import org.osgi.resource.Resource;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import static org.apache.felix.resolver.Util.getSymbolicName;
+import static org.apache.felix.resolver.Util.getVersion;
+
+/**
+ * Helper class to deal with overriden bundles at feature installation time.
+ */
+public class Overrides {
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(Overrides.class);
+
+    protected static final String OVERRIDE_RANGE = "range";
+
+    /**
+     * Compute a list of bundles to install, taking into account overrides.
+     *
+     * The file containing the overrides will be loaded from the given url.
+     * Blank lines and lines starting with a '#' will be ignored, all other lines
+     * are considered as urls to override bundles.
+     *
+     * The list of resources to resolve will be scanned and for each bundle,
+     * if a bundle override matches that resource, it will be used instead.
+     *
+     * Matching is done on bundle symbolic name (they have to be the same)
+     * and version (the bundle override version needs to be greater than the
+     * resource to be resolved, and less than the next minor version.  A range
+     * directive can be added to the override url in which case, the matching
+     * will succeed if the resource to be resolved is within the given range.
+     *
+     * @param resources the list of resources to resolve
+     * @param overrides list of bundle overrides
+     */
+    public static void override(Map<String, Resource> resources, Collection<String> overrides) {
+        // Do override replacement
+        for (Clause override : Parser.parseClauses(overrides.toArray(new String[overrides.size()]))) {
+            String url = override.getName();
+            String vr  = override.getAttribute(OVERRIDE_RANGE);
+            Resource over = resources.get(url);
+            if (over == null) {
+                // Ignore invalid overrides
+                continue;
+            }
+            for (String uri : new ArrayList<String>(resources.keySet())) {
+                Resource res = resources.get(uri);
+                if (getSymbolicName(res).equals(getSymbolicName(over))) {
+                    VersionRange range;
+                    if (vr == null) {
+                        // default to micro version compatibility
+                        Version v1 = getVersion(res);
+                        Version v2 = new Version(v1.getMajor(), v1.getMinor() + 1, 0);
+                        range = new VersionRange(false, v1, v2, true);
+                    } else {
+                        range = VersionRange.parseVersionRange(vr);
+                    }
+                    // The resource matches, so replace it with the overridden resource
+                    // if the override is actually a newer version than what we currently have
+                    if (range.contains(getVersion(over)) && getVersion(res).compareTo(getVersion(over)) < 0) {
+                        resources.put(uri, over);
+                    }
+                }
+            }
+        }
+    }
+
+    public static Set<String> loadOverrides(String overridesUrl) {
+        Set<String> overrides = new HashSet<String>();
+        try {
+            if (overridesUrl != null) {
+                InputStream is = new URL(overridesUrl).openStream();
+                try {
+                    BufferedReader reader = new BufferedReader(new InputStreamReader(is));
+                    String line;
+                    while ((line = reader.readLine()) != null) {
+                        line = line.trim();
+                        if (!line.isEmpty() && !line.startsWith("#")) {
+                            overrides.add(line);
+                        }
+                    }
+                } finally {
+                    is.close();
+                }
+            }
+        } catch (Exception e) {
+            LOGGER.debug("Unable to load overrides bundles list", e);
+        }
+        return overrides;
+    }
+
+    public static String extractUrl(String override) {
+        Clause[] cs = Parser.parseClauses(new String[] { override });
+        if (cs.length != 1) {
+            throw new IllegalStateException("Override contains more than one clause: " + override);
+        }
+        return cs[0].getName();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/src/main/java/org/apache/karaf/features/internal/service/RepositoryImpl.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/service/RepositoryImpl.java b/features/src/main/java/org/apache/karaf/features/internal/service/RepositoryImpl.java
new file mode 100644
index 0000000..4bf1502
--- /dev/null
+++ b/features/src/main/java/org/apache/karaf/features/internal/service/RepositoryImpl.java
@@ -0,0 +1,103 @@
+/*
+ * 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.karaf.features.internal.service;
+
+import java.io.FilterInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InterruptedIOException;
+import java.net.URI;
+
+import org.apache.karaf.features.Repository;
+import org.apache.karaf.features.internal.model.Features;
+import org.apache.karaf.features.internal.model.JaxbUtil;
+
+/**
+ * The repository implementation.
+ */
+public class RepositoryImpl implements Repository {
+
+    private final URI uri;
+    private Features features;
+
+    public RepositoryImpl(URI uri) {
+        this.uri = uri;
+    }
+
+    public URI getURI() {
+        return uri;
+    }
+
+    public String getName() {
+        // TODO: catching this exception is ugly
+        try {
+            load();
+        } catch (IOException e) {
+            throw new RuntimeException("Unable to load repository", e);
+        }
+        return features.getName();
+    }
+
+    public URI[] getRepositories() throws Exception {
+        load();
+        URI[] result = new URI[features.getRepository().size()];
+        for (int i = 0; i < features.getRepository().size(); i++) {
+            String uri = features.getRepository().get(i);
+            uri = uri.trim();
+            result[i] = URI.create(uri);
+        }
+        return result;
+    }
+
+    public org.apache.karaf.features.Feature[] getFeatures() throws Exception {
+        load();
+        return features.getFeature().toArray(new org.apache.karaf.features.Feature[features.getFeature().size()]);
+    }
+
+
+    public void load() throws IOException {
+        if (features == null) {
+            try {
+                InputStream inputStream = uri.toURL().openStream();
+                inputStream = new FilterInputStream(inputStream) {
+    				@Override
+    				public int read(byte[] b, int off, int len) throws IOException {
+    					if (Thread.currentThread().isInterrupted()) {
+    						throw new InterruptedIOException();
+    					}
+    					return super.read(b, off, len);
+    				}
+    			};
+                try {
+                    features = JaxbUtil.unmarshal(inputStream, false);
+                } finally {
+                    inputStream.close();
+                }
+            } catch (IllegalArgumentException e) {
+                throw (IOException) new IOException(e.getMessage() + " : " + uri).initCause(e);
+            } catch (Exception e) {
+                throw (IOException) new IOException(e.getMessage() + " : " + uri).initCause(e);
+            }
+        }
+    }
+
+    @Override
+    public boolean isValid() {
+        throw new UnsupportedOperationException();
+    }
+}
+

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/src/main/java/org/apache/karaf/features/internal/service/RequirementSort.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/service/RequirementSort.java b/features/src/main/java/org/apache/karaf/features/internal/service/RequirementSort.java
new file mode 100644
index 0000000..e9ecece
--- /dev/null
+++ b/features/src/main/java/org/apache/karaf/features/internal/service/RequirementSort.java
@@ -0,0 +1,107 @@
+/*
+ * 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.karaf.features.internal.service;
+
+
+import org.apache.karaf.features.internal.resolver.RequirementImpl;
+import org.apache.karaf.features.internal.resolver.SimpleFilter;
+import org.osgi.framework.Constants;
+import org.osgi.resource.Capability;
+import org.osgi.resource.Requirement;
+import org.osgi.resource.Resource;
+
+import java.util.Collection;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Set;
+
+public class RequirementSort  {
+
+    /**
+     * Sorts {@link Resource} based on their {@link Requirement}s and {@link Capability}s.
+     * @param resources
+     * @return
+     */
+    public static <T extends Resource> Collection<T> sort(Collection<T> resources) {
+        Set<T> sorted = new LinkedHashSet<T>();
+        Set<T> visited = new LinkedHashSet<T>();
+        for (T r : resources) {
+            visit(r, resources, visited, sorted);
+        }
+        return sorted;
+    }
+
+
+    private static <T extends Resource> void visit(T resource, Collection<T> resources, Set<T> visited, Set<T> sorted) {
+        if (visited.contains(resource)) {
+            return;
+        }
+        visited.add(resource);
+        for (T r : collectDependencies(resource, resources)) {
+            visit(r, resources, visited, sorted);
+        }
+        sorted.add(resource);
+    }
+
+    /**
+     * Finds the dependencies of the current resource.
+     * @param resource
+     * @param allResources
+     * @return
+     */
+    private static <T extends Resource> Set<T> collectDependencies(T resource, Collection<T> allResources) {
+        Set<T> result = new LinkedHashSet<T>();
+        List<Requirement> requirements = resource.getRequirements(null);
+        for (Requirement requirement : requirements) {
+            boolean isSatisfied = false;
+            for (Resource r : result) {
+                for (Capability capability : r.getCapabilities(null)) {
+                    if (isSatisfied(requirement, capability)) {
+                        isSatisfied = true;
+                        break;
+                    }
+                }
+            }
+
+            for (T r : allResources) {
+                if (!isSatisfied) {
+                    for (Capability capability : r.getCapabilities(null)) {
+                        if (isSatisfied(requirement, capability)) {
+                            result.add(r);
+                            break;
+                        }
+                    }
+                }
+            }
+        }
+        return result;
+    }
+
+    private static boolean isSatisfied(Requirement requirement, Capability capability) {
+        RequirementImpl br;
+        if (requirement instanceof RequirementImpl) {
+            br = (RequirementImpl) requirement;
+        } else {
+            String filter = requirement.getDirectives().get(Constants.FILTER_DIRECTIVE);
+            SimpleFilter sf = (filter != null)
+                    ? SimpleFilter.parse(filter)
+                    : new SimpleFilter(null, null, SimpleFilter.MATCH_ALL);
+            br = new RequirementImpl(null, requirement.getNamespace(), requirement.getDirectives(), requirement.getAttributes(), sf);
+        }
+        return br.matches(capability);
+    }
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/src/main/java/org/apache/karaf/features/internal/service/SimpleDownloader.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/service/SimpleDownloader.java b/features/src/main/java/org/apache/karaf/features/internal/service/SimpleDownloader.java
new file mode 100644
index 0000000..d1f16b9
--- /dev/null
+++ b/features/src/main/java/org/apache/karaf/features/internal/service/SimpleDownloader.java
@@ -0,0 +1,51 @@
+/*
+ * 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.karaf.features.internal.service;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.MalformedURLException;
+import java.net.URL;
+
+import org.apache.karaf.features.internal.deployment.Downloader;
+import org.apache.karaf.features.internal.deployment.StreamProvider;
+import org.apache.karaf.features.internal.util.MultiException;
+
+public class SimpleDownloader implements Downloader {
+
+    private final MultiException exception = new MultiException("Error");
+
+    @Override
+    public void await() throws InterruptedException, MultiException {
+        exception.throwIfExceptions();
+    }
+
+    @Override
+    public void download(final String location, final DownloadCallback downloadCallback) throws MalformedURLException {
+        final URL url = new URL(location);
+        try {
+            downloadCallback.downloaded(new StreamProvider() {
+                @Override
+                public InputStream open() throws IOException {
+                    return url.openStream();
+                }
+            });
+        } catch (Exception e) {
+            exception.addException(e);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/src/main/java/org/apache/karaf/features/internal/service/State.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/service/State.java b/features/src/main/java/org/apache/karaf/features/internal/service/State.java
new file mode 100644
index 0000000..c84f4e0
--- /dev/null
+++ b/features/src/main/java/org/apache/karaf/features/internal/service/State.java
@@ -0,0 +1,34 @@
+/*
+ * 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.karaf.features.internal.service;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+public class State {
+
+    public final AtomicBoolean bootDone = new AtomicBoolean();
+    public final Set<String> repositories = new TreeSet<String>();
+    public final Set<String> features = new TreeSet<String>();
+    public final Set<String> installedFeatures = new TreeSet<String>();
+    public final Set<Long> managedBundles = new TreeSet<Long>();
+    public final Map<String, Long> bundleChecksums = new HashMap<String, Long>();
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/src/main/java/org/apache/karaf/features/internal/service/StateStorage.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/service/StateStorage.java b/features/src/main/java/org/apache/karaf/features/internal/service/StateStorage.java
new file mode 100644
index 0000000..574e52e
--- /dev/null
+++ b/features/src/main/java/org/apache/karaf/features/internal/service/StateStorage.java
@@ -0,0 +1,174 @@
+/*
+ * 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.karaf.features.internal.service;
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+import java.util.TreeSet;
+
+import org.apache.karaf.features.Feature;
+
+public abstract class StateStorage {
+
+    public void load(State state) throws IOException {
+        state.repositories.clear();
+        state.features.clear();
+        state.installedFeatures.clear();
+        state.managedBundles.clear();
+        InputStream is = getInputStream();
+        if (is != null) {
+            try {
+                Properties props = new Properties();
+                props.load(is);
+                state.bootDone.set(loadBool(props, "bootDone"));
+                state.repositories.addAll(loadSet(props, "repositories."));
+                state.features.addAll(loadSet(props, "features."));
+                state.installedFeatures.addAll(loadSet(props, "installed."));
+                state.managedBundles.addAll(toLongSet(loadSet(props, "managed.")));
+                state.bundleChecksums.putAll(toStringLongMap(loadMap(props, "checksums.")));
+            } finally {
+                close(is);
+            }
+        }
+    }
+
+    public void save(State state) throws IOException {
+        OutputStream os = getOutputStream();
+        if (os != null) {
+            try {
+                Properties props = new Properties();
+                saveBool(props, "bootDone", state.bootDone.get());
+                saveSet(props, "repositories.", state.repositories);
+                saveSet(props, "features.", state.features);
+                saveSet(props, "installed.", state.installedFeatures);
+                saveSet(props, "managed.", toStringSet(state.managedBundles));
+                saveMap(props, "checksums.", toStringStringMap(state.bundleChecksums));
+                props.store(os, "FeaturesService State");
+            } finally {
+                close(os);
+            }
+        }
+    }
+
+    protected abstract InputStream getInputStream() throws IOException;
+    protected abstract OutputStream getOutputStream() throws IOException;
+
+    protected boolean loadBool(Properties props, String key) {
+        return Boolean.parseBoolean(props.getProperty(key));
+    }
+
+    protected void saveBool(Properties props, String key, boolean val) {
+        props.setProperty(key, Boolean.toString(val));
+    }
+
+    protected Set<String> toStringSet(Set<Long> set) {
+        Set<String> ns = new TreeSet<String>();
+        for (long l : set) {
+            ns.add(Long.toString(l));
+        }
+        return ns;
+    }
+
+    protected Set<Long> toLongSet(Set<String> set) {
+        Set<Long> ns = new TreeSet<Long>();
+        for (String s : set) {
+            ns.add(Long.parseLong(s));
+        }
+        return ns;
+    }
+
+    protected void saveSet(Properties props, String prefix, Set<String> set) {
+        List<String> l = new ArrayList<String>(set);
+        props.put(prefix + "count", Integer.toString(l.size()));
+        for (int i = 0; i < l.size(); i++) {
+            props.put(prefix + "item." + i, l.get(i));
+        }
+    }
+
+    protected Set<String> loadSet(Properties props, String prefix) {
+        Set<String> l = new HashSet<String>();
+        String countStr = (String) props.get(prefix + "count");
+        if (countStr != null) {
+            int count = Integer.parseInt(countStr);
+            for (int i = 0; i < count; i++) {
+                l.add((String) props.get(prefix + "item." + i));
+            }
+        }
+        return l;
+    }
+
+    protected Map<String, String> toStringStringMap(Map<String, Long> map) {
+        Map<String, String> nm = new HashMap<String, String>();
+        for (Map.Entry<String, Long> entry : map.entrySet()) {
+            nm.put(entry.getKey(), Long.toString(entry.getValue()));
+        }
+        return nm;
+    }
+
+    protected Map<String, Long> toStringLongMap(Map<String, String> map) {
+        Map<String, Long> nm = new HashMap<String, Long>();
+        for (Map.Entry<String, String> entry : map.entrySet()) {
+            nm.put(entry.getKey(), Long.parseLong(entry.getValue()));
+        }
+        return nm;
+    }
+
+
+    protected void saveMap(Properties props, String prefix, Map<String, String> map) {
+        List<Map.Entry<String, String>> l = new ArrayList<Map.Entry<String, String>>(map.entrySet());
+        props.put(prefix + "count", Integer.toString(l.size()));
+        for (int i = 0; i < l.size(); i++) {
+            props.put(prefix + "key." + i, l.get(i).getKey());
+            props.put(prefix + "val." + i, l.get(i).getValue());
+        }
+    }
+
+    protected Map<String, String> loadMap(Properties props, String prefix) {
+        Map<String, String> l = new HashMap<String, String>();
+        String countStr = (String) props.get(prefix + "count");
+        if (countStr != null) {
+            int count = Integer.parseInt(countStr);
+            for (int i = 0; i < count; i++) {
+                String key = (String) props.get(prefix + "key." + i);
+                String val = (String) props.get(prefix + "val." + i);
+                l.put(key, val);
+            }
+        }
+        return l;
+    }
+
+
+    protected void close(Closeable closeable) {
+        if (closeable != null) {
+            try {
+                closeable.close();
+            } catch (IOException e) {
+                // Ignore
+            }
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/src/main/java/org/apache/karaf/features/internal/util/ChecksumUtils.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/util/ChecksumUtils.java b/features/src/main/java/org/apache/karaf/features/internal/util/ChecksumUtils.java
new file mode 100644
index 0000000..19fc706
--- /dev/null
+++ b/features/src/main/java/org/apache/karaf/features/internal/util/ChecksumUtils.java
@@ -0,0 +1,56 @@
+/*
+ * 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.karaf.features.internal.util;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.zip.CRC32;
+
+public class ChecksumUtils {
+
+    private ChecksumUtils() {
+    }
+
+    /**
+     * Compute a cheksum for the file or directory that consists of the name, length and the last modified date
+     * for a file and its children in case of a directory
+     *
+     * @param is the input stream
+     * @return a checksum identifying any change
+     */
+    public static long checksum(InputStream is) throws IOException
+    {
+        try {
+            CRC32 crc = new CRC32();
+            byte[] buffer = new byte[8192];
+            int l;
+            while ((l = is.read(buffer)) > 0) {
+                crc.update(buffer, 0, l);
+            }
+            return crc.getValue();
+        } finally {
+            if (is != null) {
+                try {
+                    is.close();
+                } catch (IOException e) {
+                    // Ignore
+                }
+            }
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/src/main/java/org/apache/karaf/features/internal/util/JsonReader.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/util/JsonReader.java b/features/src/main/java/org/apache/karaf/features/internal/util/JsonReader.java
new file mode 100644
index 0000000..a53d8a5
--- /dev/null
+++ b/features/src/main/java/org/apache/karaf/features/internal/util/JsonReader.java
@@ -0,0 +1,349 @@
+/*
+ * 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.karaf.features.internal.util;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ */
+public class JsonReader {
+
+    public static Object read(Reader reader) throws IOException {
+        return new JsonReader(reader).parse();
+    }
+
+    public static Object read(InputStream is) throws IOException {
+        return new JsonReader(new InputStreamReader(is)).parse();
+    }
+
+    //
+    // Implementation
+    //
+
+    private final Reader reader;
+    private final StringBuilder recorder;
+    private int current;
+    private int line = 1;
+    private int column = 0;
+
+    JsonReader(Reader reader) {
+        this.reader = reader;
+        recorder = new StringBuilder();
+    }
+
+    public Object parse() throws IOException {
+        read();
+        skipWhiteSpace();
+        Object result = readValue();
+        skipWhiteSpace();
+        if (!endOfText()) {
+            throw error("Unexpected character");
+        }
+        return result;
+    }
+
+    private Object readValue() throws IOException {
+        switch (current) {
+            case 'n':
+                return readNull();
+            case 't':
+                return readTrue();
+            case 'f':
+                return readFalse();
+            case '"':
+                return readString();
+            case '[':
+                return readArray();
+            case '{':
+                return readObject();
+            case '-':
+            case '0':
+            case '1':
+            case '2':
+            case '3':
+            case '4':
+            case '5':
+            case '6':
+            case '7':
+            case '8':
+            case '9':
+                return readNumber();
+            default:
+                throw expected("value");
+        }
+    }
+
+    private Collection<?> readArray() throws IOException {
+        read();
+        Collection<Object> array = new ArrayList<Object>();
+        skipWhiteSpace();
+        if (readChar(']')) {
+            return array;
+        }
+        do {
+            skipWhiteSpace();
+            array.add(readValue());
+            skipWhiteSpace();
+        } while (readChar(','));
+        if (!readChar(']')) {
+            throw expected("',' or ']'");
+        }
+        return array;
+    }
+
+    private Map<String, Object> readObject() throws IOException {
+        read();
+        Map<String, Object> object = new HashMap<String, Object>();
+        skipWhiteSpace();
+        if (readChar('}')) {
+            return object;
+        }
+        do {
+            skipWhiteSpace();
+            String name = readName();
+            skipWhiteSpace();
+            if (!readChar(':')) {
+                throw expected("':'");
+            }
+            skipWhiteSpace();
+            object.put(name, readValue());
+            skipWhiteSpace();
+        } while (readChar(','));
+        if (!readChar('}')) {
+            throw expected("',' or '}'");
+        }
+        return object;
+    }
+
+    private Object readNull() throws IOException {
+        read();
+        readRequiredChar('u');
+        readRequiredChar('l');
+        readRequiredChar('l');
+        return null;
+    }
+
+    private Boolean readTrue() throws IOException {
+        read();
+        readRequiredChar('r');
+        readRequiredChar('u');
+        readRequiredChar('e');
+        return Boolean.TRUE;
+    }
+
+    private Boolean readFalse() throws IOException {
+        read();
+        readRequiredChar('a');
+        readRequiredChar('l');
+        readRequiredChar('s');
+        readRequiredChar('e');
+        return Boolean.FALSE;
+    }
+
+    private void readRequiredChar(char ch) throws IOException {
+        if (!readChar(ch)) {
+            throw expected("'" + ch + "'");
+        }
+    }
+
+    private String readString() throws IOException {
+        read();
+        recorder.setLength(0);
+        while (current != '"') {
+            if (current == '\\') {
+                readEscape();
+            } else if (current < 0x20) {
+                throw expected("valid string character");
+            } else {
+                recorder.append((char) current);
+                read();
+            }
+        }
+        read();
+        return recorder.toString();
+    }
+
+    private void readEscape() throws IOException {
+        read();
+        switch (current) {
+            case '"':
+            case '/':
+            case '\\':
+                recorder.append((char) current);
+                break;
+            case 'b':
+                recorder.append('\b');
+                break;
+            case 'f':
+                recorder.append('\f');
+                break;
+            case 'n':
+                recorder.append('\n');
+                break;
+            case 'r':
+                recorder.append('\r');
+                break;
+            case 't':
+                recorder.append('\t');
+                break;
+            case 'u':
+                char[] hexChars = new char[4];
+                for (int i = 0; i < 4; i++) {
+                    read();
+                    if (!isHexDigit(current)) {
+                        throw expected("hexadecimal digit");
+                    }
+                    hexChars[i] = (char) current;
+                }
+                recorder.append((char) Integer.parseInt(String.valueOf(hexChars), 16));
+                break;
+            default:
+                throw expected("valid escape sequence");
+        }
+        read();
+    }
+
+    private Number readNumber() throws IOException {
+        recorder.setLength(0);
+        readAndAppendChar('-');
+        int firstDigit = current;
+        if (!readAndAppendDigit()) {
+            throw expected("digit");
+        }
+        if (firstDigit != '0') {
+            while (readAndAppendDigit()) {
+            }
+        }
+        readFraction();
+        readExponent();
+        return Double.parseDouble(recorder.toString());
+    }
+
+    private boolean readFraction() throws IOException {
+        if (!readAndAppendChar('.')) {
+            return false;
+        }
+        if (!readAndAppendDigit()) {
+            throw expected("digit");
+        }
+        while (readAndAppendDigit()) {
+        }
+        return true;
+    }
+
+    private boolean readExponent() throws IOException {
+        if (!readAndAppendChar('e') && !readAndAppendChar('E')) {
+            return false;
+        }
+        if (!readAndAppendChar('+')) {
+            readAndAppendChar('-');
+        }
+        if (!readAndAppendDigit()) {
+            throw expected("digit");
+        }
+        while (readAndAppendDigit()) {
+        }
+        return true;
+    }
+
+    private String readName() throws IOException {
+        if (current != '"') {
+            throw expected("name");
+        }
+        readString();
+        return recorder.toString();
+    }
+
+    private boolean readAndAppendChar(char ch) throws IOException {
+        if (current != ch) {
+            return false;
+        }
+        recorder.append(ch);
+        read();
+        return true;
+    }
+
+    private boolean readChar(char ch) throws IOException {
+        if (current != ch) {
+            return false;
+        }
+        read();
+        return true;
+    }
+
+    private boolean readAndAppendDigit() throws IOException {
+        if (!isDigit(current)) {
+            return false;
+        }
+        recorder.append((char) current);
+        read();
+        return true;
+    }
+
+    private void skipWhiteSpace() throws IOException {
+        while (isWhiteSpace(current) && !endOfText()) {
+            read();
+        }
+    }
+
+    private void read() throws IOException {
+        if (endOfText()) {
+            throw error("Unexpected end of input");
+        }
+        column++;
+        if (current == '\n') {
+            line++;
+            column = 0;
+        }
+        current = reader.read();
+    }
+
+    private boolean endOfText() {
+        return current == -1;
+    }
+
+    private IOException expected(String expected) {
+        if (endOfText()) {
+            return error("Unexpected end of input");
+        }
+        return error("Expected " + expected);
+    }
+
+    private IOException error(String message) {
+        return new IOException(message + " at " + line + ":" + column);
+    }
+
+    private static boolean isWhiteSpace(int ch) {
+        return ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r';
+    }
+
+    private static boolean isDigit(int ch) {
+        return ch >= '0' && ch <= '9';
+    }
+
+    private static boolean isHexDigit(int ch) {
+        return ch >= '0' && ch <= '9' || ch >= 'a' && ch <= 'f' || ch >= 'A' && ch <= 'F';
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/src/main/java/org/apache/karaf/features/internal/util/JsonWriter.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/util/JsonWriter.java b/features/src/main/java/org/apache/karaf/features/internal/util/JsonWriter.java
new file mode 100644
index 0000000..cba27fb
--- /dev/null
+++ b/features/src/main/java/org/apache/karaf/features/internal/util/JsonWriter.java
@@ -0,0 +1,120 @@
+/*
+ * 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.karaf.features.internal.util;
+
+import java.io.IOException;
+import java.io.Writer;
+import java.util.Collection;
+import java.util.Map;
+
+/**
+ */
+public class JsonWriter {
+
+    public static void write(Writer writer, Object value) throws IOException {
+        if (value instanceof Map) {
+            writeObject(writer, (Map) value);
+        } else if (value instanceof Collection) {
+            writeArray(writer, (Collection) value);
+        } else if (value instanceof Number) {
+            writeNumber(writer, (Number) value);
+        } else if (value instanceof String) {
+            writeString(writer, (String) value);
+        } else if (value instanceof Boolean) {
+            writeBoolean(writer, (Boolean) value);
+        } else if (value == null) {
+            writeNull(writer);
+        } else {
+            throw new IllegalArgumentException("Unsupported value: " + value);
+        }
+    }
+
+    private static void writeObject(Writer writer, Map<?, ?> value) throws IOException {
+        writer.append('{');
+        boolean first = true;
+        for (Map.Entry entry : value.entrySet()) {
+            if (!first) {
+                writer.append(',');
+            } else {
+                first = false;
+            }
+            writeString(writer, (String) entry.getKey());
+            writer.append(':');
+            write(writer, entry.getValue());
+        }
+        writer.append('}');
+    }
+
+    private static void writeString(Writer writer, String value) throws IOException {
+        writer.append('"');
+        for (int i = 0; i < value.length(); i++) {
+            char c = value.charAt(i);
+            switch (c) {
+                case '\"':
+                case '\\':
+                case '\b':
+                case '\f':
+                case '\n':
+                case '\r':
+                case '\t':
+                    writer.append('\\');
+                    writer.append(c);
+                    break;
+                default:
+                    if (c < ' ' || (c >= '\u0080' && c < '\u00a0') || (c >= '\u2000' && c < '\u2100')) {
+                        String s = Integer.toHexString(c);
+                        writer.append('\\');
+                        writer.append('u');
+                        for (int j = s.length(); j < 4; j++) {
+                            writer.append('0');
+                        }
+                        writer.append(s);
+                    } else {
+                        writer.append(c);
+                    }
+                    break;
+            }
+        }
+        writer.append('"');
+    }
+
+    private static void writeNumber(Writer writer, Number value) throws IOException {
+        writer.append(value.toString());
+    }
+
+    private static void writeBoolean(Writer writer, Boolean value) throws IOException {
+        writer.append(Boolean.toString(value));
+    }
+
+    private static void writeArray(Writer writer, Collection<?> value) throws IOException {
+        writer.append('[');
+        boolean first = true;
+        for (Object obj : value) {
+            if (!first) {
+                writer.append(',');
+            } else {
+                first = false;
+            }
+            write(writer, obj);
+        }
+        writer.append(']');
+    }
+
+    private static void writeNull(Writer writer) throws IOException {
+        writer.append("null");
+    }
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/src/main/java/org/apache/karaf/features/internal/util/Macro.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/util/Macro.java b/features/src/main/java/org/apache/karaf/features/internal/util/Macro.java
new file mode 100644
index 0000000..d30b7b5
--- /dev/null
+++ b/features/src/main/java/org/apache/karaf/features/internal/util/Macro.java
@@ -0,0 +1,142 @@
+/*
+ * 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.karaf.features.internal.util;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.felix.utils.version.VersionTable;
+import org.osgi.framework.Version;
+
+public class Macro {
+
+    public static String transform(String macro, String value) {
+        if (macro.startsWith("${") && macro.endsWith("}")) {
+            String[] args = macro.substring(2, macro.length() - 1).split(";");
+            if ("version".equals(args[0])) {
+                if (args.length != 2) {
+                    throw new IllegalArgumentException("Invalid syntax for macro: " + macro);
+                }
+                return version(args[1], VersionTable.getVersion(value));
+            } else if ("range".equals(args[0])) {
+                if (args.length != 2) {
+                    throw new IllegalArgumentException("Invalid syntax for macro: " + macro);
+                }
+                return range(args[1], VersionTable.getVersion(value));
+            } else {
+                throw new IllegalArgumentException("Unknown macro: " + macro);
+            }
+        }
+        return value;
+    }
+
+    /**
+     * Modify a version to set a version policy. Thed policy is a mask that is
+     * mapped to a version.
+     *
+     * <pre>
+     * +           increment
+     * -           decrement
+     * =           maintain
+     * &tilde;           discard
+     *
+     * ==+      = maintain major, minor, increment micro, discard qualifier
+     * &tilde;&tilde;&tilde;=     = just get the qualifier
+     * version=&quot;[${version;==;${@}},${version;=+;${@}})&quot;
+	 * </pre>
+	 *
+	 * @param args
+     * @return
+     */
+    final static String	MASK_STRING			= "[\\-+=~0123456789]{0,3}[=~]?";
+
+    static String version(String mask, Version version) {
+        StringBuilder sb = new StringBuilder();
+        String del = "";
+
+        for (int i = 0; i < mask.length(); i++) {
+            char c = mask.charAt(i);
+            String result = null;
+            if (c != '~') {
+                if (i > 3) {
+                    throw new IllegalArgumentException("Version mask can only specify 3 digits");
+                } else if (i == 3) {
+                    result = version.getQualifier();
+                    if (result.isEmpty()) {
+                        result = null;
+                    }
+                } else if (Character.isDigit(c)) {
+                    // Handle masks like +00, =+0
+                    result = String.valueOf(c);
+                } else {
+                    int x = 0;
+                    switch (i) {
+                        case 0: x = version.getMajor(); break;
+                        case 1: x = version.getMinor(); break;
+                        case 2: x = version.getMicro(); break;
+                    }
+                    switch (c) {
+                        case '+' :
+                            x++;
+                            break;
+                        case '-' :
+                            x--;
+                            break;
+                        case '=' :
+                            break;
+                    }
+                    result = Integer.toString(x);
+                }
+                if (result != null) {
+                    sb.append(del);
+                    del = ".";
+                    sb.append(result);
+                }
+            }
+        }
+        return sb.toString();
+    }
+
+    /**
+     * Schortcut for version policy
+     *
+     * <pre>
+     * -provide-policy : ${policy;[==,=+)}
+     * -consume-policy : ${policy;[==,+)}
+     * </pre>
+     *
+     * @param args
+     * @return
+     */
+
+    static Pattern	RANGE_MASK		= Pattern.compile("(\\[|\\()(" + MASK_STRING + "),(" + MASK_STRING + ")(\\]|\\))");
+
+    static String range(String spec, Version version) {
+        Matcher m = RANGE_MASK.matcher(spec);
+        m.matches();
+        String floor = m.group(1);
+        String floorMask = m.group(2);
+        String ceilingMask = m.group(3);
+        String ceiling = m.group(4);
+
+        String left = version(floorMask, version);
+        String right = version(ceilingMask, version);
+
+        return floor + left + "," + right + ceiling;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/src/main/java/org/apache/karaf/features/internal/util/MultiException.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/internal/util/MultiException.java b/features/src/main/java/org/apache/karaf/features/internal/util/MultiException.java
new file mode 100644
index 0000000..36af452
--- /dev/null
+++ b/features/src/main/java/org/apache/karaf/features/internal/util/MultiException.java
@@ -0,0 +1,95 @@
+/*
+ * 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.karaf.features.internal.util;
+
+import java.io.PrintStream;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.List;
+
+@SuppressWarnings("serial")
+public class MultiException extends Exception {
+
+    private List<Exception> exceptions = new ArrayList<Exception>();
+
+    public MultiException(String message) {
+        super(message);
+    }
+
+    public MultiException(String message, List<Exception> exceptions) {
+        super(message);
+        this.exceptions = exceptions;
+    }
+
+    public void addException(Exception e) {
+        exceptions.add(e);
+    }
+
+    public void throwIfExceptions() throws MultiException {
+        if (!exceptions.isEmpty()) {
+            throw this;
+        }
+    }
+    
+    public Throwable[] getCauses() {
+        return exceptions.toArray(new Throwable[exceptions.size()]);
+    }
+
+    @Override
+    public void printStackTrace()
+    {
+        super.printStackTrace();
+        for (Exception e : exceptions) {
+            e.printStackTrace();
+        }
+    }
+
+
+    /* ------------------------------------------------------------------------------- */
+    /**
+     * @see Throwable#printStackTrace(java.io.PrintStream)
+     */
+    @Override
+    public void printStackTrace(PrintStream out)
+    {
+        super.printStackTrace(out);
+        for (Exception e : exceptions) {
+            e.printStackTrace(out);
+        }
+    }
+
+    @Override
+    public void printStackTrace(PrintWriter out)
+    {
+        super.printStackTrace(out);
+        for (Exception e : exceptions) {
+            e.printStackTrace(out);
+        }
+    }
+
+    public static void throwIf(String message, List<Exception> exceptions) throws MultiException {
+        if (exceptions != null && !exceptions.isEmpty()) {
+            StringBuilder sb = new StringBuilder(message);
+            sb.append(":");
+            for (Exception e : exceptions) {
+                sb.append("\n\t");
+                sb.append(e.getMessage());
+            }
+            throw new MultiException(sb.toString(), exceptions);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/src/main/java/org/apache/karaf/features/management/FeaturesServiceMBean.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/management/FeaturesServiceMBean.java b/features/src/main/java/org/apache/karaf/features/management/FeaturesServiceMBean.java
new file mode 100644
index 0000000..6afbbed
--- /dev/null
+++ b/features/src/main/java/org/apache/karaf/features/management/FeaturesServiceMBean.java
@@ -0,0 +1,142 @@
+/*
+ * 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.karaf.features.management;
+
+import javax.management.openmbean.TabularData;
+
+public interface FeaturesServiceMBean {
+
+    TabularData getFeatures() throws Exception;
+
+    TabularData getRepositories() throws Exception;
+
+    void addRepository(String url) throws Exception;
+
+    void addRepository(String url, boolean install) throws Exception;
+
+    void removeRepository(String url) throws Exception;
+
+    void removeRepository(String url, boolean uninstall) throws Exception;
+
+    void installFeature(String name) throws Exception;
+
+    void installFeature(String name, boolean noRefresh) throws Exception;
+
+    void installFeature(String name, boolean noRefresh, boolean noStart) throws Exception;
+
+    void installFeature(String name, String version) throws Exception;
+
+    void installFeature(String name, String version, boolean noRefresh) throws Exception;
+
+    void installFeature(String name, String version, boolean noRefresh, boolean noStart) throws Exception;
+
+    TabularData infoFeature(String name) throws Exception;
+
+    TabularData infoFeature(String name, String version) throws Exception;
+
+    void uninstallFeature(String name) throws Exception;
+
+    void uninstallFeature(String name, boolean noRefresh) throws Exception;
+
+    void uninstallFeature(String name, String version) throws Exception;
+
+    void uninstallFeature(String name, String version, boolean noRefresh) throws Exception;
+
+    String FEATURE_NAME = "Name";
+
+    String FEATURE_VERSION = "Version";
+
+    String FEATURE_DEPENDENCIES = "Dependencies";
+
+    String FEATURE_BUNDLES = "Bundles";
+
+    String FEATURE_CONFIGURATIONS = "Configurations";
+    
+    String FEATURE_CONFIGURATIONFILES = "Configuration Files";
+
+    String FEATURE_INSTALLED = "Installed";
+
+    String FEATURE_CONFIG_PID = "Pid";
+    String FEATURE_CONFIG_ELEMENTS = "Elements";
+    String FEATURE_CONFIG_ELEMENT_KEY = "Key";
+    String FEATURE_CONFIG_ELEMENT_VALUE = "Value";
+    
+    String FEATURE_CONFIG_FILES_ELEMENTS = "Files";
+
+    /**
+     * The type of the event which is emitted for features events
+     */
+    String FEATURE_EVENT_TYPE = "org.apache.karaf.features.featureEvent";
+
+    String FEATURE_EVENT_EVENT_TYPE = "Type";
+
+    String FEATURE_EVENT_EVENT_TYPE_INSTALLED = "Installed";
+
+    String FEATURE_EVENT_EVENT_TYPE_UNINSTALLED = "Uninstalled";
+
+    /**
+     * The item names in the CompositeData representing a feature
+     */
+    String[] FEATURE = { FEATURE_NAME, FEATURE_VERSION, FEATURE_DEPENDENCIES, FEATURE_BUNDLES,
+                         FEATURE_CONFIGURATIONS, FEATURE_CONFIGURATIONFILES, FEATURE_INSTALLED };
+
+    String[] FEATURE_IDENTIFIER = { FEATURE_NAME, FEATURE_VERSION };
+
+    String[] FEATURE_CONFIG = { FEATURE_CONFIG_PID, FEATURE_CONFIG_ELEMENTS };
+    
+    String[] FEATURE_CONFIG_FILES = { FEATURE_CONFIG_FILES_ELEMENTS };
+
+    String[] FEATURE_CONFIG_ELEMENT = { FEATURE_CONFIG_ELEMENT_KEY, FEATURE_CONFIG_ELEMENT_VALUE };
+
+    /**
+     * The item names in the CompositeData representing the event raised for
+     * feature events within the OSGi container by this bean
+     */
+    String[] FEATURE_EVENT = { FEATURE_NAME, FEATURE_VERSION, FEATURE_EVENT_EVENT_TYPE };
+
+
+    String REPOSITORY_NAME = "Name";
+
+    String REPOSITORY_URI = "Uri";
+
+    String REPOSITORY_REPOSITORIES = "Repositories";
+
+    String REPOSITORY_FEATURES = "Features";
+
+    /**
+     * The type of the event which is emitted for repositories events
+     */
+    String REPOSITORY_EVENT_TYPE = "org.apache.karaf.features.repositoryEvent";
+
+    String REPOSITORY_EVENT_EVENT_TYPE = "Type";
+
+    String REPOSITORY_EVENT_EVENT_TYPE_ADDED = "Added";
+
+    String REPOSITORY_EVENT_EVENT_TYPE_REMOVED = "Removed";
+
+    /**
+     * The item names in the CompositeData representing a feature
+     */
+    String[] REPOSITORY = { REPOSITORY_NAME, REPOSITORY_URI,  REPOSITORY_REPOSITORIES, REPOSITORY_FEATURES };
+
+    /**
+     * The item names in the CompositeData representing the event raised for
+     * feature events within the OSGi container by this bean
+     */
+    String[] REPOSITORY_EVENT = { REPOSITORY_URI, REPOSITORY_EVENT_EVENT_TYPE };
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/src/main/java/org/apache/karaf/features/management/codec/JmxFeature.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/management/codec/JmxFeature.java b/features/src/main/java/org/apache/karaf/features/management/codec/JmxFeature.java
new file mode 100644
index 0000000..54fa3c0
--- /dev/null
+++ b/features/src/main/java/org/apache/karaf/features/management/codec/JmxFeature.java
@@ -0,0 +1,323 @@
+/*
+ * 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.karaf.features.management.codec;
+
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.management.openmbean.TabularData;
+import javax.management.openmbean.TabularType;
+import javax.management.openmbean.OpenDataException;
+import javax.management.openmbean.CompositeType;
+import javax.management.openmbean.OpenType;
+import javax.management.openmbean.SimpleType;
+import javax.management.openmbean.ArrayType;
+import javax.management.openmbean.CompositeData;
+import javax.management.openmbean.CompositeDataSupport;
+import javax.management.openmbean.TabularDataSupport;
+
+import org.apache.karaf.features.BundleInfo;
+import org.apache.karaf.features.ConfigFileInfo;
+import org.apache.karaf.features.Dependency;
+import org.apache.karaf.features.Feature;
+import org.apache.karaf.features.management.FeaturesServiceMBean;
+
+public class JmxFeature {
+
+    /**
+     * The CompositeType which represents a single feature
+     */
+    public final static CompositeType FEATURE;
+
+    /**
+     * The TabularType which represents a list of features
+     */
+    public final static TabularType FEATURE_TABLE;
+
+    public final static CompositeType FEATURE_IDENTIFIER;
+
+    public final static TabularType FEATURE_IDENTIFIER_TABLE;
+
+    public final static CompositeType FEATURE_CONFIG_ELEMENT;
+
+    public final static TabularType FEATURE_CONFIG_ELEMENT_TABLE;
+
+    public final static CompositeType FEATURE_CONFIG;
+
+    public final static TabularType FEATURE_CONFIG_TABLE;
+
+    public final static CompositeType FEATURE_CONFIG_FILES;
+    
+    public final static TabularType FEATURE_CONFIG_FILES_TABLE;
+    
+    private final CompositeData data;
+
+    public JmxFeature(Feature feature, boolean installed) {
+        try {
+            String[] itemNames = FeaturesServiceMBean.FEATURE;
+            Object[] itemValues = new Object[itemNames.length];
+            itemValues[0] = feature.getName();
+            itemValues[1] = feature.getVersion();
+            itemValues[2] = getDependencyIdentifierTable(feature.getDependencies());
+            itemValues[3] = getBundleUris(feature.getBundles());
+            itemValues[4] = getConfigTable(feature.getConfigurations());
+            itemValues[5] = getConfigFileList(feature.getConfigurationFiles());
+            itemValues[6] = installed;
+            data = new CompositeDataSupport(FEATURE, itemNames, itemValues);
+        } catch (OpenDataException e) {
+            throw new IllegalStateException("Cannot form feature open data", e);
+        }
+    }
+
+    public CompositeData asCompositeData() {
+        return data;
+    }
+
+    public static TabularData tableFrom(Collection<JmxFeature> features) {
+        TabularDataSupport table = new TabularDataSupport(FEATURE_TABLE);
+        for (JmxFeature feature : features) {
+            table.put(feature.asCompositeData());
+        }
+        return table;
+    }
+
+     private static TabularData getDependencyIdentifierTable(List<Dependency> features) throws OpenDataException {
+        TabularDataSupport table = new TabularDataSupport(FEATURE_IDENTIFIER_TABLE);
+        Set<String> featureSet = new HashSet<String>();
+        for (Dependency feature : features) {
+            if (featureSet.contains(feature.getName() + feature.getVersion())) {
+                continue;
+            } else {
+                featureSet.add(feature.getName() + feature.getVersion());
+            }
+            String[] itemNames = new String[] { FeaturesServiceMBean.FEATURE_NAME, FeaturesServiceMBean.FEATURE_VERSION };
+            Object[] itemValues = new Object[] { feature.getName(), feature.getVersion() };
+            CompositeData ident = new CompositeDataSupport(FEATURE_IDENTIFIER, itemNames, itemValues);
+            table.put(ident);
+        }
+        return table;
+    }
+
+    static String[] getBundleUris(List<BundleInfo> infos) {
+        String[] array = new String[infos.size()];
+        for (int i = 0; i < array.length; i++) {
+            array[i] = infos.get(i).getLocation();
+        }
+        return array;
+    }
+
+    static TabularData getConfigTable(Map<String, Map<String, String>> configs) throws OpenDataException {
+        TabularDataSupport table = new TabularDataSupport(FEATURE_CONFIG_TABLE);
+        for (Map.Entry<String, Map<String, String>> entry : configs.entrySet()) {
+            String[] itemNames = FeaturesServiceMBean.FEATURE_CONFIG;
+            Object[] itemValues = new Object[2];
+            itemValues[0] = entry.getKey();
+            itemValues[1] = getConfigElementTable(entry.getValue());
+            CompositeData config = new CompositeDataSupport(FEATURE_CONFIG, itemNames, itemValues);
+            table.put(config);
+        }
+        return table;
+    }
+    
+    static TabularData getConfigFileList(List<ConfigFileInfo> configFiles) throws OpenDataException {
+        TabularDataSupport table = new TabularDataSupport(FEATURE_CONFIG_FILES_TABLE);
+        for (ConfigFileInfo configFile : configFiles) {
+            String[] itemNames = FeaturesServiceMBean.FEATURE_CONFIG_FILES;
+            Object[] itemValues = { configFile.getFinalname() };
+            CompositeData config = new CompositeDataSupport(FEATURE_CONFIG_FILES, itemNames, itemValues);
+            table.put(config);
+        }
+        return table;
+    }
+
+    static TabularData getConfigElementTable(Map<String, String> config) throws OpenDataException {
+        TabularDataSupport table = new TabularDataSupport(FEATURE_CONFIG_ELEMENT_TABLE);
+        for (Map.Entry<String, String> entry : config.entrySet()) {
+            String[] itemNames = FeaturesServiceMBean.FEATURE_CONFIG_ELEMENT;
+            Object[] itemValues = { entry.getKey(), entry.getValue() };
+            CompositeData element = new CompositeDataSupport(FEATURE_CONFIG_ELEMENT, itemNames, itemValues);
+            table.put(element);
+        }
+        return table;
+    }
+
+
+    static {
+        FEATURE_IDENTIFIER = createFeatureIdentifierType();
+        FEATURE_IDENTIFIER_TABLE = createFeatureIdentifierTableType();
+        FEATURE_CONFIG_ELEMENT = createFeatureConfigElementType();
+        FEATURE_CONFIG_ELEMENT_TABLE = createFeatureConfigElementTableType();
+        FEATURE_CONFIG = createFeatureConfigType();
+        FEATURE_CONFIG_TABLE = createFeatureConfigTableType();
+        FEATURE_CONFIG_FILES =  createFeatureConfigFilesType();
+        FEATURE_CONFIG_FILES_TABLE = createFeatureConfigFilesTableType();
+        FEATURE = createFeatureType();
+        FEATURE_TABLE = createFeatureTableType();
+    }
+
+    private static CompositeType createFeatureIdentifierType() {
+        try {
+            String description = "This type identify a Karaf features";
+            String[] itemNames = FeaturesServiceMBean.FEATURE_IDENTIFIER;
+            OpenType[] itemTypes = new OpenType[itemNames.length];
+            String[] itemDescriptions = new String[itemNames.length];
+            itemTypes[0] = SimpleType.STRING;
+            itemTypes[1] = SimpleType.STRING;
+
+            itemDescriptions[0] = "The id of the feature";
+            itemDescriptions[1] = "The version of the feature";
+
+            return new CompositeType("FeatureIdentifier", description, itemNames,
+                    itemDescriptions, itemTypes);
+        } catch (OpenDataException e) {
+            throw new IllegalStateException("Unable to build featureIdentifier type", e);
+        }
+    }
+
+    private static TabularType createFeatureIdentifierTableType() {
+        try {
+            return new TabularType("Features", "The table of featureIdentifiers",
+                    FEATURE_IDENTIFIER, new String[] { FeaturesServiceMBean.FEATURE_NAME, FeaturesServiceMBean.FEATURE_VERSION });
+        } catch (OpenDataException e) {
+            throw new IllegalStateException("Unable to build featureIdentifier table type", e);
+        }
+    }
+
+    private static CompositeType createFeatureConfigElementType() {
+        try {
+            String description = "This type encapsulates Karaf feature config element";
+            String[] itemNames = FeaturesServiceMBean.FEATURE_CONFIG_ELEMENT;
+            OpenType[] itemTypes = new OpenType[itemNames.length];
+            String[] itemDescriptions = new String[itemNames.length];
+            itemTypes[0] = SimpleType.STRING;
+            itemTypes[1] = SimpleType.STRING;
+
+            itemDescriptions[0] = "The key";
+            itemDescriptions[1] = "The value";
+
+            return new CompositeType("ConfigElement", description, itemNames,
+                    itemDescriptions, itemTypes);
+        } catch (OpenDataException e) {
+            throw new IllegalStateException("Unable to build configElement type", e);
+        }
+    }
+
+    private static TabularType createFeatureConfigElementTableType() {
+        try {
+            return new TabularType("ConfigElement", "The table of configurations elements",
+                    FEATURE_CONFIG_ELEMENT, new String[] { FeaturesServiceMBean.FEATURE_CONFIG_ELEMENT_KEY});
+        } catch (OpenDataException e) {
+            throw new IllegalStateException("Unable to build feature table type", e);
+        }
+    }
+
+    private static CompositeType createFeatureConfigType() {
+        try {
+            String description = "This type encapsulates Karaf feature config";
+            String[] itemNames = FeaturesServiceMBean.FEATURE_CONFIG;
+            OpenType[] itemTypes = new OpenType[itemNames.length];
+            String[] itemDescriptions = new String[itemNames.length];
+            itemTypes[0] = SimpleType.STRING;
+            itemTypes[1] = FEATURE_CONFIG_ELEMENT_TABLE;
+
+            itemDescriptions[0] = "The PID of the config";
+            itemDescriptions[1] = "The configuration elements";
+
+            return new CompositeType("Config", description, itemNames,
+                    itemDescriptions, itemTypes);
+        } catch (OpenDataException e) {
+            throw new IllegalStateException("Unable to build configElement type", e);
+        }
+    }
+    
+    private static CompositeType createFeatureConfigFilesType() {
+        try {
+            String description = "This type encapsulates Karaf feature config files";
+            String[] itemNames = FeaturesServiceMBean.FEATURE_CONFIG_FILES;
+            OpenType[] itemTypes = new OpenType[itemNames.length];
+            String[] itemDescriptions = new String[itemNames.length];
+            itemTypes[0] = SimpleType.STRING;
+
+            itemDescriptions[0] = "The configuration file";
+
+            return new CompositeType("Config", description, itemNames,
+                    itemDescriptions, itemTypes);
+        } catch (OpenDataException e) {
+            throw new IllegalStateException("Unable to build configElement type", e);
+        }
+    }
+
+    private static TabularType createFeatureConfigTableType() {
+        try {
+            return new TabularType("Features", "The table of configurations",
+                    FEATURE_CONFIG, new String[] { FeaturesServiceMBean.FEATURE_CONFIG_PID});
+        } catch (OpenDataException e) {
+            throw new IllegalStateException("Unable to build feature table type", e);
+        }
+    }
+    
+    private static TabularType createFeatureConfigFilesTableType() {
+        try {
+            return new TabularType("Features", "The table of configuration files",
+            		FEATURE_CONFIG_FILES, new String[] { FeaturesServiceMBean.FEATURE_CONFIG_FILES_ELEMENTS });
+        } catch (OpenDataException e) {
+            throw new IllegalStateException("Unable to build feature table type", e);
+        }
+    }
+
+    private static CompositeType createFeatureType() {
+        try {
+            String description = "This type encapsulates Karaf features";
+            String[] itemNames = FeaturesServiceMBean.FEATURE;
+            OpenType[] itemTypes = new OpenType[itemNames.length];
+            String[] itemDescriptions = new String[itemNames.length];
+            itemTypes[0] = SimpleType.STRING;
+            itemTypes[1] = SimpleType.STRING;
+            itemTypes[2] = FEATURE_IDENTIFIER_TABLE;
+            itemTypes[3] = new ArrayType(1, SimpleType.STRING);
+            itemTypes[4] = FEATURE_CONFIG_TABLE;
+            itemTypes[5] = FEATURE_CONFIG_FILES_TABLE;
+            itemTypes[6] = SimpleType.BOOLEAN;
+
+            itemDescriptions[0] = "The name of the feature";
+            itemDescriptions[1] = "The version of the feature";
+            itemDescriptions[2] = "The feature dependencies";
+            itemDescriptions[3] = "The feature bundles";
+            itemDescriptions[4] = "The feature configurations";
+            itemDescriptions[5] = "The feature configuration files";
+            itemDescriptions[6] = "Whether the feature is installed";
+
+            return new CompositeType("Feature", description, itemNames,
+                    itemDescriptions, itemTypes);
+        } catch (OpenDataException e) {
+            throw new IllegalStateException("Unable to build feature type", e);
+        }
+    }
+
+    private static TabularType createFeatureTableType() {
+        try {
+            return new TabularType("Features", "The table of all features",
+                    FEATURE, new String[] { FeaturesServiceMBean.FEATURE_NAME, FeaturesServiceMBean.FEATURE_VERSION });
+        } catch (OpenDataException e) {
+            throw new IllegalStateException("Unable to build feature table type", e);
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/src/main/java/org/apache/karaf/features/management/codec/JmxFeatureEvent.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/management/codec/JmxFeatureEvent.java b/features/src/main/java/org/apache/karaf/features/management/codec/JmxFeatureEvent.java
new file mode 100644
index 0000000..81f446b
--- /dev/null
+++ b/features/src/main/java/org/apache/karaf/features/management/codec/JmxFeatureEvent.java
@@ -0,0 +1,80 @@
+/*
+ * 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.karaf.features.management.codec;
+
+import javax.management.openmbean.CompositeData;
+import javax.management.openmbean.CompositeDataSupport;
+import javax.management.openmbean.OpenDataException;
+import javax.management.openmbean.CompositeType;
+import javax.management.openmbean.OpenType;
+import javax.management.openmbean.SimpleType;
+
+import org.apache.karaf.features.FeatureEvent;
+import org.apache.karaf.features.management.FeaturesServiceMBean;
+
+public class JmxFeatureEvent {
+
+    public static final CompositeType FEATURE_EVENT;
+
+    private final CompositeData data;
+
+    public JmxFeatureEvent(FeatureEvent event) {
+        try {
+            String[] itemNames = FeaturesServiceMBean.FEATURE_EVENT;
+            Object[] itemValues = new Object[itemNames.length];
+            itemValues[0] = event.getFeature().getName();
+            itemValues[1] = event.getFeature().getVersion();
+            switch (event.getType()) {
+                case FeatureInstalled:   itemValues[2] = FeaturesServiceMBean.FEATURE_EVENT_EVENT_TYPE_INSTALLED; break;
+                case FeatureUninstalled: itemValues[2] = FeaturesServiceMBean.FEATURE_EVENT_EVENT_TYPE_UNINSTALLED; break;
+                default: throw new IllegalStateException("Unsupported event type: " + event.getType());
+            }
+            data = new CompositeDataSupport(FEATURE_EVENT, itemNames, itemValues);
+        } catch (OpenDataException e) {
+            throw new IllegalStateException("Cannot form feature event open data", e);
+        }
+    }
+
+    public CompositeData asCompositeData() {
+        return data;
+    }
+
+    static {
+        FEATURE_EVENT = createFeatureEventType();
+    }
+
+    private static CompositeType createFeatureEventType() {
+        try {
+            String description = "This type identify a Karaf feature event";
+            String[] itemNames = FeaturesServiceMBean.FEATURE_EVENT;
+            OpenType[] itemTypes = new OpenType[itemNames.length];
+            String[] itemDescriptions = new String[itemNames.length];
+            itemTypes[0] = SimpleType.STRING;
+            itemTypes[1] = SimpleType.STRING;
+            itemTypes[2] = SimpleType.STRING;
+
+            itemDescriptions[0] = "The id of the feature";
+            itemDescriptions[1] = "The version of the feature";
+            itemDescriptions[2] = "The type of the event";
+
+            return new CompositeType("FeatureEvent", description, itemNames,
+                    itemDescriptions, itemTypes);
+        } catch (OpenDataException e) {
+            throw new IllegalStateException("Unable to build featureEvent type", e);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/src/main/java/org/apache/karaf/features/management/codec/JmxRepository.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/management/codec/JmxRepository.java b/features/src/main/java/org/apache/karaf/features/management/codec/JmxRepository.java
new file mode 100644
index 0000000..fee1ab2
--- /dev/null
+++ b/features/src/main/java/org/apache/karaf/features/management/codec/JmxRepository.java
@@ -0,0 +1,132 @@
+/*
+ * 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.karaf.features.management.codec;
+
+import java.util.Collection;
+import java.util.Arrays;
+import java.net.URI;
+import java.util.List;
+
+import javax.management.openmbean.TabularData;
+import javax.management.openmbean.CompositeType;
+import javax.management.openmbean.TabularType;
+import javax.management.openmbean.OpenType;
+import javax.management.openmbean.SimpleType;
+import javax.management.openmbean.OpenDataException;
+import javax.management.openmbean.ArrayType;
+import javax.management.openmbean.CompositeData;
+import javax.management.openmbean.TabularDataSupport;
+import javax.management.openmbean.CompositeDataSupport;
+
+import org.apache.karaf.features.Feature;
+import org.apache.karaf.features.Repository;
+import org.apache.karaf.features.management.FeaturesServiceMBean;
+
+public class JmxRepository {
+
+    public final static CompositeType REPOSITORY;
+
+    public final static TabularType REPOSITORY_TABLE;
+
+    private final CompositeData data;
+
+    public JmxRepository(Repository repository) {
+        try {
+            String[] itemNames = FeaturesServiceMBean.REPOSITORY;
+            Object[] itemValues = new Object[itemNames.length];
+            itemValues[0] = repository.getName();
+            itemValues[1] = repository.getURI().toString();
+            itemValues[2] = toStringArray(repository.getRepositories());
+            itemValues[3] = getFeatureIdentifierTable(Arrays.asList(repository.getFeatures()));
+            data = new CompositeDataSupport(REPOSITORY, itemNames, itemValues);
+        } catch (Exception e) {
+            throw new IllegalStateException("Cannot form repository open data", e);
+        }
+    }
+
+    public CompositeData asCompositeData() {
+        return data;
+    }
+
+    public static TabularData tableFrom(Collection<JmxRepository> repositories) {
+        TabularDataSupport table = new TabularDataSupport(REPOSITORY_TABLE);
+        for (JmxRepository repository : repositories) {
+            table.put(repository.asCompositeData());
+        }
+        return table;
+    }
+
+    private static String[] toStringArray(URI[] uris) {
+        if (uris == null) {
+            return null;
+        }
+        String[] res = new String[uris.length];
+        for (int i = 0; i < res.length; i++) {
+            res[i] = uris[i].toString();
+        }
+        return res;
+    }
+
+    static TabularData getFeatureIdentifierTable(List<Feature> features) throws OpenDataException {
+        TabularDataSupport table = new TabularDataSupport(JmxFeature.FEATURE_IDENTIFIER_TABLE);
+        for (Feature feature : features) {
+            String[] itemNames = new String[] { FeaturesServiceMBean.FEATURE_NAME, FeaturesServiceMBean.FEATURE_VERSION };
+            Object[] itemValues = new Object[] { feature.getName(), feature.getVersion() };
+            CompositeData ident = new CompositeDataSupport(JmxFeature.FEATURE_IDENTIFIER, itemNames, itemValues);
+            table.put(ident);
+        }
+        return table;
+    }
+
+    static {
+        REPOSITORY = createRepositoryType();
+        REPOSITORY_TABLE = createRepositoryTableType();
+    }
+
+    private static CompositeType createRepositoryType() {
+        try {
+            String description = "This type identify a Karaf repository";
+            String[] itemNames = FeaturesServiceMBean.REPOSITORY;
+            OpenType[] itemTypes = new OpenType[itemNames.length];
+            String[] itemDescriptions = new String[itemNames.length];
+            itemTypes[0] = SimpleType.STRING;
+            itemTypes[1] = SimpleType.STRING;
+            itemTypes[2] = new ArrayType(1, SimpleType.STRING);
+            itemTypes[3] = JmxFeature.FEATURE_IDENTIFIER_TABLE;
+
+            itemDescriptions[0] = "The name of the repository";
+            itemDescriptions[1] = "The uri of the repository";
+            itemDescriptions[2] = "The dependent repositories";
+            itemDescriptions[3] = "The list of included features";
+
+            return new CompositeType("Repository", description, itemNames,
+                    itemDescriptions, itemTypes);
+        } catch (OpenDataException e) {
+            throw new IllegalStateException("Unable to build repository type", e);
+        }
+    }
+
+    private static TabularType createRepositoryTableType() {
+        try {
+            return new TabularType("Features", "The table of repositories",
+                    REPOSITORY, new String[] { FeaturesServiceMBean.REPOSITORY_URI });
+        } catch (OpenDataException e) {
+            throw new IllegalStateException("Unable to build repository table type", e);
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/src/main/java/org/apache/karaf/features/management/codec/JmxRepositoryEvent.java
----------------------------------------------------------------------
diff --git a/features/src/main/java/org/apache/karaf/features/management/codec/JmxRepositoryEvent.java b/features/src/main/java/org/apache/karaf/features/management/codec/JmxRepositoryEvent.java
new file mode 100644
index 0000000..e00e85d
--- /dev/null
+++ b/features/src/main/java/org/apache/karaf/features/management/codec/JmxRepositoryEvent.java
@@ -0,0 +1,77 @@
+/*
+ * 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.karaf.features.management.codec;
+
+import javax.management.openmbean.CompositeData;
+import javax.management.openmbean.CompositeType;
+import javax.management.openmbean.CompositeDataSupport;
+import javax.management.openmbean.OpenDataException;
+import javax.management.openmbean.OpenType;
+import javax.management.openmbean.SimpleType;
+
+import org.apache.karaf.features.RepositoryEvent;
+import org.apache.karaf.features.management.FeaturesServiceMBean;
+
+public class JmxRepositoryEvent {
+
+    public static final CompositeType REPOSITORY_EVENT;
+
+    private final CompositeData data;
+
+    public JmxRepositoryEvent(RepositoryEvent event) {
+        try {
+            String[] itemNames = FeaturesServiceMBean.REPOSITORY_EVENT;
+            Object[] itemValues = new Object[itemNames.length];
+            itemValues[0] = event.getRepository().getURI().toString();
+            switch (event.getType()) {
+                case RepositoryAdded:   itemValues[1] = FeaturesServiceMBean.REPOSITORY_EVENT_EVENT_TYPE_ADDED; break;
+                case RepositoryRemoved: itemValues[1] = FeaturesServiceMBean.REPOSITORY_EVENT_EVENT_TYPE_REMOVED; break;
+                default: throw new IllegalStateException("Unsupported event type: " + event.getType());
+            }
+            data = new CompositeDataSupport(REPOSITORY_EVENT, itemNames, itemValues);
+        } catch (OpenDataException e) {
+            throw new IllegalStateException("Cannot form repository event open data", e);
+        }
+    }
+
+    public CompositeData asCompositeData() {
+        return data;
+    }
+
+    static {
+        REPOSITORY_EVENT = createRepositoryEventType();
+    }
+
+    private static CompositeType createRepositoryEventType() {
+        try {
+            String description = "This type identify a Karaf repository event";
+            String[] itemNames = FeaturesServiceMBean.REPOSITORY_EVENT;
+            OpenType[] itemTypes = new OpenType[itemNames.length];
+            String[] itemDescriptions = new String[itemNames.length];
+            itemTypes[0] = SimpleType.STRING;
+            itemTypes[1] = SimpleType.STRING;
+
+            itemDescriptions[0] = "The uri of the repository";
+            itemDescriptions[1] = "The type of event";
+
+            return new CompositeType("RepositoryEvent", description, itemNames,
+                    itemDescriptions, itemTypes);
+        } catch (OpenDataException e) {
+            throw new IllegalStateException("Unable to build repositoryEvent type", e);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/999f4970/features/src/main/resources/OSGI-INF/bundle.info
----------------------------------------------------------------------
diff --git a/features/src/main/resources/OSGI-INF/bundle.info b/features/src/main/resources/OSGI-INF/bundle.info
new file mode 100644
index 0000000..d5b4180
--- /dev/null
+++ b/features/src/main/resources/OSGI-INF/bundle.info
@@ -0,0 +1,20 @@
+h1. Synopsis
+
+${project.name}
+
+${project.description}
+
+Maven URL:
+[mvn:${project.groupId}/${project.artifactId}/${project.version}]
+
+h1. Description
+
+This bundle is the core implementation of the Karaf features support.
+
+Karaf provides a simple, yet flexible, way to provision applications or "features". Such a mechanism is mainly
+provided by a set of commands available in the features shell. The provisioning system uses xml "repositories"
+that define a set of features.
+
+h1. See also
+
+Provisioning - section of the Karaf User Guide


[22/59] [abbrv] [KARAF-2852] Merge config/core and config/command

Posted by gn...@apache.org.
http://git-wip-us.apache.org/repos/asf/karaf/blob/d33e0955/config/src/test/java/org/apache/karaf/config/command/EditCommandTest.java
----------------------------------------------------------------------
diff --git a/config/src/test/java/org/apache/karaf/config/command/EditCommandTest.java b/config/src/test/java/org/apache/karaf/config/command/EditCommandTest.java
new file mode 100644
index 0000000..09dc000
--- /dev/null
+++ b/config/src/test/java/org/apache/karaf/config/command/EditCommandTest.java
@@ -0,0 +1,97 @@
+/*
+ * 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.karaf.config.command;
+
+import java.util.Dictionary;
+import java.util.Properties;
+
+import junit.framework.TestCase;
+import org.apache.karaf.config.core.impl.ConfigRepositoryImpl;
+import org.apache.karaf.shell.api.console.Session;
+import org.osgi.framework.BundleContext;
+import org.osgi.service.cm.Configuration;
+import org.osgi.service.cm.ConfigurationAdmin;
+
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
+
+/**
+ * Test cases for {@link EditCommand}
+ */
+public class EditCommandTest extends TestCase {
+
+    private static final String PID = "my.test.persistent.id";
+
+    private EditCommand command;
+    private BundleContext context;
+    private ConfigurationAdmin admin;
+    private Session session;
+
+    @Override
+    protected void setUp() throws Exception {
+        command = new EditCommand();
+
+        admin = createMock(ConfigurationAdmin.class);
+        command.setConfigRepository(new ConfigRepositoryImpl(admin));
+
+        session = new MockCommandSession();
+        command.setSession(session);
+    }
+    
+    public void testExecuteOnExistingPid() throws Exception {        
+        Configuration config = createMock(Configuration.class);
+        expect(admin.getConfiguration(PID)).andReturn(config);
+        replay(admin);
+        
+        // the ConfigAdmin service returns a Dictionary for an existing PID
+        Dictionary props = new Properties();
+        expect(config.getProperties()).andReturn(props);
+        replay(config);
+        
+        command.pid = PID; 
+        command.execute();
+        
+        // the PID and Dictionary should have been set on the session
+        assertEquals("The PID should be set on the session",
+                     PID, session.get(ConfigCommandSupport.PROPERTY_CONFIG_PID));
+        assertSame("The Dictionary returned by the ConfigAdmin service should be set on the session",
+                   props, session.get(ConfigCommandSupport.PROPERTY_CONFIG_PROPS));
+    }
+    
+    @SuppressWarnings("rawtypes")
+    public void testExecuteOnNewPid() throws Exception {        
+        Configuration config = createMock(Configuration.class);
+        expect(admin.getConfiguration(PID)).andReturn(config);
+        replay(admin);
+        
+        // the ConfigAdmin service does not return a Dictionary for a new PID
+        expect(config.getProperties()).andReturn(null);
+        replay(config);
+        
+        command.pid = PID; 
+        command.execute();
+
+        // the PID and an empty Dictionary should have been set on the session        
+        assertEquals("The PID should be set on the session",
+                     PID, session.get(ConfigCommandSupport.PROPERTY_CONFIG_PID));
+        Dictionary props = (Dictionary) session.get(ConfigCommandSupport.PROPERTY_CONFIG_PROPS);
+        assertNotNull("Should have a Dictionary on the session", props);
+        assertTrue("Should have an empty Dictionary on the session", props.isEmpty());
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d33e0955/config/src/test/java/org/apache/karaf/config/command/MockCommandSession.java
----------------------------------------------------------------------
diff --git a/config/src/test/java/org/apache/karaf/config/command/MockCommandSession.java b/config/src/test/java/org/apache/karaf/config/command/MockCommandSession.java
new file mode 100644
index 0000000..7fa430b
--- /dev/null
+++ b/config/src/test/java/org/apache/karaf/config/command/MockCommandSession.java
@@ -0,0 +1,99 @@
+/*
+ * 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.karaf.config.command;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.PrintStream;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.karaf.shell.api.console.History;
+import org.apache.karaf.shell.api.console.Registry;
+import org.apache.karaf.shell.api.console.Session;
+import org.apache.karaf.shell.api.console.SessionFactory;
+import org.apache.karaf.shell.api.console.Terminal;
+
+/*
+ * A mock CommandSession implementation that only cares about the properties set on the session
+ */
+class MockCommandSession implements Session {
+
+    private Map<String, Object> properties = new HashMap<String, Object>();
+
+    public void close() {
+        // not implemented
+    }
+
+    public Object execute(CharSequence commandline) throws Exception {
+        // not implemented
+        return null;
+    }
+
+    public Object get(String name) {
+        return properties.get(name);
+    }
+
+    public PrintStream getConsole() {
+        // not implemented
+        return null;
+    }
+
+    public InputStream getKeyboard() {
+        // not implemented
+        return null;
+    }
+
+    public void put(String name, Object value) {
+        properties.put(name, value);
+    }
+
+    @Override
+    public String readLine(String prompt, Character mask) throws IOException {
+        return null;
+    }
+
+    @Override
+    public Terminal getTerminal() {
+        return null;
+    }
+
+    @Override
+    public History getHistory() {
+        return null;
+    }
+
+    @Override
+    public Registry getRegistry() {
+        return null;
+    }
+
+    @Override
+    public SessionFactory getFactory() {
+        return null;
+    }
+
+    @Override
+    public String resolveCommand(String name) {
+        return null;
+    }
+
+    @Override
+    public void run() {
+
+    }
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/d33e0955/config/src/test/java/org/apache/karaf/config/command/UpdateCommandTest.java
----------------------------------------------------------------------
diff --git a/config/src/test/java/org/apache/karaf/config/command/UpdateCommandTest.java b/config/src/test/java/org/apache/karaf/config/command/UpdateCommandTest.java
new file mode 100644
index 0000000..e3f58b5
--- /dev/null
+++ b/config/src/test/java/org/apache/karaf/config/command/UpdateCommandTest.java
@@ -0,0 +1,82 @@
+/*
+ * 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.karaf.config.command;
+
+
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
+
+import java.util.Dictionary;
+import java.util.Hashtable;
+
+import junit.framework.TestCase;
+
+import org.apache.karaf.config.core.ConfigRepository;
+import org.easymock.EasyMock;
+
+/**
+ * Test cases for {@link EditCommand}
+ */
+public class UpdateCommandTest extends TestCase {
+
+    private static final String FACTORY_PID = "myFactoryPid";
+    private static final String PID = "myPid";
+
+    public void testupdateRegularConfig() throws Exception {
+		Dictionary<String, Object> props = new Hashtable<String, Object>();
+
+        UpdateCommand command = new UpdateCommand();
+        ConfigRepository configRepo = EasyMock.createMock(ConfigRepository.class);
+        configRepo.update(EasyMock.eq(PID), EasyMock.eq(props));
+        EasyMock.expectLastCall();
+		command.setConfigRepository(configRepo);
+
+        MockCommandSession session = createMockSessionForFactoryEdit(PID, false, props);
+        command.setSession(session);
+        replay(configRepo);
+
+        command.execute();
+        EasyMock.verify(configRepo);
+    }
+    
+    public void testupdateOnNewFactoryPid() throws Exception {
+		Dictionary<String, Object> props = new Hashtable<String, Object>();
+
+        UpdateCommand command = new UpdateCommand();
+        ConfigRepository configRepo = EasyMock.createMock(ConfigRepository.class);
+        expect(configRepo.createFactoryConfiguration(EasyMock.eq(FACTORY_PID), EasyMock.eq(props)))
+        	.andReturn(PID + ".35326647");
+		command.setConfigRepository(configRepo);
+
+        MockCommandSession session = createMockSessionForFactoryEdit(FACTORY_PID, true, props);
+        command.setSession(session);
+        replay(configRepo);
+
+        command.execute();
+        EasyMock.verify(configRepo);
+    }
+
+	private MockCommandSession createMockSessionForFactoryEdit(String pid, boolean isFactory, 
+			Dictionary<String, Object> props) {
+		MockCommandSession session = new MockCommandSession();
+        session.put(ConfigCommandSupport.PROPERTY_CONFIG_PID, pid);
+        session.put(ConfigCommandSupport.PROPERTY_FACTORY, isFactory);
+        session.put(ConfigCommandSupport.PROPERTY_CONFIG_PROPS, props);
+		return session;
+	}
+
+}


[37/59] [abbrv] git commit: [KARAF-2852] Merge log/core and log/command

Posted by gn...@apache.org.
[KARAF-2852] Merge log/core and log/command

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

Branch: refs/heads/master
Commit: 7f1463c517a55d6be85091fd2bed61f46b4236e1
Parents: f13d140
Author: Guillaume Nodet <gn...@gmail.com>
Authored: Wed Apr 9 23:13:37 2014 +0200
Committer: Guillaume Nodet <gn...@gmail.com>
Committed: Thu Apr 10 16:01:42 2014 +0200

----------------------------------------------------------------------
 .../standard/src/main/feature/feature.xml       |   1 -
 log/NOTICE                                      |  71 +++
 log/command/NOTICE                              |  71 ---
 log/command/pom.xml                             | 113 ----
 .../org/apache/karaf/log/command/ClearLog.java  |  41 --
 .../karaf/log/command/DisplayException.java     |  49 --
 .../apache/karaf/log/command/DisplayLog.java    |  83 ---
 .../apache/karaf/log/command/GetLogLevel.java   |  63 ---
 .../org/apache/karaf/log/command/LogEntry.java  |  69 ---
 .../org/apache/karaf/log/command/LogTail.java   | 129 -----
 .../apache/karaf/log/command/SetLogLevel.java   |  52 --
 .../src/main/resources/OSGI-INF/bundle.info     |  24 -
 .../OSGI-INF/metatype/metatype.properties       |  31 -
 .../resources/OSGI-INF/metatype/metatype.xml    |  30 -
 log/core/NOTICE                                 |  71 ---
 log/core/pom.xml                                | 112 ----
 .../java/org/apache/karaf/log/core/Level.java   |  54 --
 .../karaf/log/core/LogEventFormatter.java       |  25 -
 .../org/apache/karaf/log/core/LogMBean.java     |  32 --
 .../org/apache/karaf/log/core/LogService.java   |  38 --
 .../core/internal/LogEventFormatterImpl.java    | 157 ------
 .../karaf/log/core/internal/LogMBeanImpl.java   |  59 --
 .../karaf/log/core/internal/LogServiceImpl.java | 261 ---------
 .../apache/karaf/log/core/internal/LruList.java | 124 ----
 .../internal/layout/AbsoluteTimeDateFormat.java | 142 -----
 .../internal/layout/DateTimeDateFormat.java     |  85 ---
 .../core/internal/layout/FormattingInfo.java    |  44 --
 .../core/internal/layout/ISO8601DateFormat.java | 152 -----
 .../core/internal/layout/PatternConverter.java  | 106 ----
 .../log/core/internal/layout/PatternParser.java | 560 -------------------
 .../karaf/log/core/internal/osgi/Activator.java |  77 ---
 .../src/main/resources/OSGI-INF/bundle.info     |  24 -
 .../log/core/internal/SetLogLevelTest.java      | 129 -----
 log/pom.xml                                     |  97 +++-
 .../org/apache/karaf/log/command/ClearLog.java  |  41 ++
 .../karaf/log/command/DisplayException.java     |  49 ++
 .../apache/karaf/log/command/DisplayLog.java    |  83 +++
 .../apache/karaf/log/command/GetLogLevel.java   |  63 +++
 .../org/apache/karaf/log/command/LogEntry.java  |  69 +++
 .../org/apache/karaf/log/command/LogTail.java   | 129 +++++
 .../apache/karaf/log/command/SetLogLevel.java   |  52 ++
 .../java/org/apache/karaf/log/core/Level.java   |  54 ++
 .../karaf/log/core/LogEventFormatter.java       |  25 +
 .../org/apache/karaf/log/core/LogMBean.java     |  32 ++
 .../org/apache/karaf/log/core/LogService.java   |  38 ++
 .../core/internal/LogEventFormatterImpl.java    | 157 ++++++
 .../karaf/log/core/internal/LogMBeanImpl.java   |  59 ++
 .../karaf/log/core/internal/LogServiceImpl.java | 261 +++++++++
 .../apache/karaf/log/core/internal/LruList.java | 124 ++++
 .../internal/layout/AbsoluteTimeDateFormat.java | 142 +++++
 .../internal/layout/DateTimeDateFormat.java     |  85 +++
 .../core/internal/layout/FormattingInfo.java    |  44 ++
 .../core/internal/layout/ISO8601DateFormat.java | 152 +++++
 .../core/internal/layout/PatternConverter.java  | 106 ++++
 .../log/core/internal/layout/PatternParser.java | 560 +++++++++++++++++++
 .../karaf/log/core/internal/osgi/Activator.java |  77 +++
 log/src/main/resources/OSGI-INF/bundle.info     |  24 +
 .../OSGI-INF/metatype/metatype.properties       |  31 +
 .../resources/OSGI-INF/metatype/metatype.xml    |  30 +
 .../log/core/internal/SetLogLevelTest.java      | 129 +++++
 60 files changed, 2776 insertions(+), 3016 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/karaf/blob/7f1463c5/assemblies/features/standard/src/main/feature/feature.xml
----------------------------------------------------------------------
diff --git a/assemblies/features/standard/src/main/feature/feature.xml b/assemblies/features/standard/src/main/feature/feature.xml
index 99554c2..6fa3319 100644
--- a/assemblies/features/standard/src/main/feature/feature.xml
+++ b/assemblies/features/standard/src/main/feature/feature.xml
@@ -147,7 +147,6 @@
 
     <feature name="log" description="Provide Log support" version="${project.version}">
         <bundle start-level="30" start="true">mvn:org.apache.karaf.log/org.apache.karaf.log.core/${project.version}</bundle>
-        <bundle start-level="30" start="true">mvn:org.apache.karaf.log/org.apache.karaf.log.command/${project.version}</bundle>
     </feature>
 
     <feature name="region" description="Provide Region Support" version="${project.version}">

http://git-wip-us.apache.org/repos/asf/karaf/blob/7f1463c5/log/NOTICE
----------------------------------------------------------------------
diff --git a/log/NOTICE b/log/NOTICE
new file mode 100644
index 0000000..b70f1f9
--- /dev/null
+++ b/log/NOTICE
@@ -0,0 +1,71 @@
+Apache Karaf
+Copyright 2010-2014 The Apache Software Foundation
+
+
+I. Included Software
+
+This product includes software developed at
+The Apache Software Foundation (http://www.apache.org/).
+Licensed under the Apache License 2.0.
+
+This product uses software developed at
+The OSGi Alliance (http://www.osgi.org/).
+Copyright (c) OSGi Alliance (2000, 2010).
+Licensed under the Apache License 2.0.
+
+This product includes software developed at
+OW2 (http://www.ow2.org/).
+Licensed under the BSD License.
+
+This product includes software developed at
+OPS4J (http://www.ops4j.org/).
+Licensed under the Apache License 2.0.
+
+This product includes software developed at
+Eclipse Foundation (http://www.eclipse.org/).
+Licensed under the EPL.
+
+This product includes software written by
+Antony Lesuisse.
+Licensed under Public Domain.
+
+
+II. Used Software
+
+This product uses software developed at
+FUSE Source (http://www.fusesource.org/).
+Licensed under the Apache License 2.0.
+
+This product uses software developed at
+AOP Alliance (http://aopalliance.sourceforge.net/).
+Licensed under the Public Domain.
+
+This product uses software developed at
+Tanuki Software (http://www.tanukisoftware.com/).
+Licensed under the Apache License 2.0.
+
+This product uses software developed at
+Jasypt (http://jasypt.sourceforge.net/).
+Licensed under the Apache License 2.0.
+
+This product uses software developed at
+JLine (http://jline.sourceforge.net).
+Licensed under the BSD License.
+
+This product uses software developed at
+SLF4J (http://www.slf4j.org/).
+Licensed under the MIT License.
+
+This product uses software developed at
+SpringSource (http://www.springsource.org/).
+Licensed under the Apache License 2.0.
+
+This product includes software from http://www.json.org.
+Copyright (c) 2002 JSON.org
+
+
+III. License Summary
+- Apache License 2.0
+- BSD License
+- EPL License
+- MIT License

http://git-wip-us.apache.org/repos/asf/karaf/blob/7f1463c5/log/command/NOTICE
----------------------------------------------------------------------
diff --git a/log/command/NOTICE b/log/command/NOTICE
deleted file mode 100644
index b70f1f9..0000000
--- a/log/command/NOTICE
+++ /dev/null
@@ -1,71 +0,0 @@
-Apache Karaf
-Copyright 2010-2014 The Apache Software Foundation
-
-
-I. Included Software
-
-This product includes software developed at
-The Apache Software Foundation (http://www.apache.org/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-The OSGi Alliance (http://www.osgi.org/).
-Copyright (c) OSGi Alliance (2000, 2010).
-Licensed under the Apache License 2.0.
-
-This product includes software developed at
-OW2 (http://www.ow2.org/).
-Licensed under the BSD License.
-
-This product includes software developed at
-OPS4J (http://www.ops4j.org/).
-Licensed under the Apache License 2.0.
-
-This product includes software developed at
-Eclipse Foundation (http://www.eclipse.org/).
-Licensed under the EPL.
-
-This product includes software written by
-Antony Lesuisse.
-Licensed under Public Domain.
-
-
-II. Used Software
-
-This product uses software developed at
-FUSE Source (http://www.fusesource.org/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-AOP Alliance (http://aopalliance.sourceforge.net/).
-Licensed under the Public Domain.
-
-This product uses software developed at
-Tanuki Software (http://www.tanukisoftware.com/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-Jasypt (http://jasypt.sourceforge.net/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-JLine (http://jline.sourceforge.net).
-Licensed under the BSD License.
-
-This product uses software developed at
-SLF4J (http://www.slf4j.org/).
-Licensed under the MIT License.
-
-This product uses software developed at
-SpringSource (http://www.springsource.org/).
-Licensed under the Apache License 2.0.
-
-This product includes software from http://www.json.org.
-Copyright (c) 2002 JSON.org
-
-
-III. License Summary
-- Apache License 2.0
-- BSD License
-- EPL License
-- MIT License

http://git-wip-us.apache.org/repos/asf/karaf/blob/7f1463c5/log/command/pom.xml
----------------------------------------------------------------------
diff --git a/log/command/pom.xml b/log/command/pom.xml
deleted file mode 100644
index b0b3791..0000000
--- a/log/command/pom.xml
+++ /dev/null
@@ -1,113 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-
-    <!--
-
-        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.
-    -->
-
-    <modelVersion>4.0.0</modelVersion>
-
-    <parent>
-        <groupId>org.apache.karaf.log</groupId>
-        <artifactId>log</artifactId>
-        <version>4.0.0-SNAPSHOT</version>
-        <relativePath>../pom.xml</relativePath>
-    </parent>
-
-    <artifactId>org.apache.karaf.log.command</artifactId>
-    <packaging>bundle</packaging>
-    <name>Apache Karaf :: Log :: Command</name>
-    <description>Shell commands to manipulate Log service</description>
-
-    <properties>
-        <appendedResourcesDirectory>${basedir}/../../etc/appended-resources</appendedResourcesDirectory>
-    </properties>
-
-    <dependencies>
-        <dependency>
-            <groupId>org.apache.karaf.log</groupId>
-            <artifactId>org.apache.karaf.log.core</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.karaf.shell</groupId>
-            <artifactId>org.apache.karaf.shell.core</artifactId>
-        </dependency>
-
-        <dependency>
-            <groupId>org.osgi</groupId>
-            <artifactId>org.osgi.core</artifactId>
-            <scope>provided</scope>
-        </dependency>
-
-        <dependency>
-            <groupId>org.osgi</groupId>
-            <artifactId>org.osgi.compendium</artifactId>
-            <scope>provided</scope>
-        </dependency>
-
-        <dependency>
-            <groupId>org.ops4j.pax.logging</groupId>
-            <artifactId>pax-logging-service</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.ops4j.pax.logging</groupId>
-            <artifactId>pax-logging-api</artifactId>
-        </dependency>
-
-    </dependencies>
-
-    <build>
-        <resources>
-            <resource>
-                <directory>${project.basedir}/src/main/resources</directory>
-                <includes>
-                    <include>**/*</include>
-                </includes>
-            </resource>
-            <resource>
-                <directory>${project.basedir}/src/main/resources</directory>
-                <filtering>true</filtering>
-                <includes>
-                    <include>**/*.info</include>
-                </includes>
-            </resource>
-        </resources>
-        <plugins>
-            <plugin>
-                <groupId>org.apache.felix</groupId>
-                <artifactId>maven-bundle-plugin</artifactId>
-                <configuration>
-                    <instructions>
-                        <Import-Package>
-                            *
-                        </Import-Package>
-                        <Export-Package>
-                            !*
-                        </Export-Package>
-                        <Private-Package>
-                            org.apache.karaf.log.command*
-                        </Private-Package>
-                        <Karaf-Commands>
-                            org.apache.karaf.log.command*
-                        </Karaf-Commands>
-                    </instructions>
-                </configuration>
-            </plugin>
-        </plugins>
-    </build>
-
-</project>

http://git-wip-us.apache.org/repos/asf/karaf/blob/7f1463c5/log/command/src/main/java/org/apache/karaf/log/command/ClearLog.java
----------------------------------------------------------------------
diff --git a/log/command/src/main/java/org/apache/karaf/log/command/ClearLog.java b/log/command/src/main/java/org/apache/karaf/log/command/ClearLog.java
deleted file mode 100644
index 75a48d6..0000000
--- a/log/command/src/main/java/org/apache/karaf/log/command/ClearLog.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * 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.karaf.log.command;
-
-import org.apache.karaf.log.core.LogService;
-import org.apache.karaf.shell.api.action.Action;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.lifecycle.Reference;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-
-/**
- * Clear the last log entries.
- */
-@Command(scope = "log", name = "clear", description = "Clear log entries.")
-@Service
-public class ClearLog implements Action {
-
-    @Reference
-    LogService logService;
-
-    @Override
-    public Object execute() throws Exception {
-        logService.clearEvents();
-        return null;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/7f1463c5/log/command/src/main/java/org/apache/karaf/log/command/DisplayException.java
----------------------------------------------------------------------
diff --git a/log/command/src/main/java/org/apache/karaf/log/command/DisplayException.java b/log/command/src/main/java/org/apache/karaf/log/command/DisplayException.java
deleted file mode 100644
index 52a2661..0000000
--- a/log/command/src/main/java/org/apache/karaf/log/command/DisplayException.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * 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.karaf.log.command;
-
-import org.apache.karaf.log.core.LogService;
-import org.apache.karaf.shell.api.action.Action;
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.lifecycle.Reference;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.ops4j.pax.logging.spi.PaxLoggingEvent;
-
-@Command(scope = "log", name = "exception-display", description = "Displays the last occurred exception from the log.")
-@Service
-public class DisplayException implements Action {
-
-    @Argument(index = 0, name = "logger", description = "The name of the logger. This can be ROOT, ALL, or the name of a logger specified in the org.ops4j.pax.logger.cfg file.", required = false, multiValued = false)
-    String logger;
-
-    @Reference
-    LogService logService;
-
-    @Override
-    public Object execute() throws Exception {
-        PaxLoggingEvent throwableEvent = logService.getLastException(logger);
-        if (throwableEvent != null) {
-            for (String r : throwableEvent.getThrowableStrRep()) {
-                System.out.println(r);
-            }
-            System.out.println();
-        }
-        return null;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/7f1463c5/log/command/src/main/java/org/apache/karaf/log/command/DisplayLog.java
----------------------------------------------------------------------
diff --git a/log/command/src/main/java/org/apache/karaf/log/command/DisplayLog.java b/log/command/src/main/java/org/apache/karaf/log/command/DisplayLog.java
deleted file mode 100644
index 813eea5..0000000
--- a/log/command/src/main/java/org/apache/karaf/log/command/DisplayLog.java
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * 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.karaf.log.command;
-
-import java.io.PrintStream;
-
-import org.apache.karaf.log.core.LogEventFormatter;
-import org.apache.karaf.log.core.LogService;
-import org.apache.karaf.shell.api.action.Action;
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Option;
-import org.apache.karaf.shell.api.action.lifecycle.Reference;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.ops4j.pax.logging.spi.PaxLoggingEvent;
-
-/**
- * Displays the last log entries
- */
-@Command(scope = "log", name = "display", description = "Displays log entries.")
-@Service
-public class DisplayLog implements Action {
-
-    @Option(name = "-n", aliases = {}, description="Number of entries to display", required = false, multiValued = false)
-    int entries;
-
-    @Option(name = "-p", aliases = {}, description="Pattern for formatting the output", required = false, multiValued = false)
-    String overridenPattern;
-
-    @Option(name = "--no-color", description="Disable syntax coloring of log events", required = false, multiValued = false)
-    boolean noColor;
-
-    @Argument(index = 0, name = "logger", description = "The name of the logger. This can be ROOT, ALL, or the name of a logger specified in the org.ops4j.pax.logger.cfg file.", required = false, multiValued = false)
-    String logger;
-
-    @Reference
-    LogService logService;
-
-    @Reference
-    LogEventFormatter formatter;
-
-    @Override
-    public Object execute() throws Exception {
-        
-        final PrintStream out = System.out;
-
-        Iterable<PaxLoggingEvent> le = logService.getEvents(entries == 0 ? Integer.MAX_VALUE : entries);
-        for (PaxLoggingEvent event : le) {
-            printEvent(out, event);
-        }
-        out.println();
-        return null;
-    }
-        
-    protected boolean checkIfFromRequestedLog(PaxLoggingEvent event) {
-    	return (event.getLoggerName().lastIndexOf(logger)>=0) ? true : false;
-    }
-
-    protected void printEvent(final PrintStream out, PaxLoggingEvent event) {
-        if ((logger != null) && 
-            (event != null)&&
-            (checkIfFromRequestedLog(event))) {
-                out.append(formatter.format(event, overridenPattern, noColor));
-            }
-            else if ((event != null)&&(logger == null)){
-                out.append(formatter.format(event, overridenPattern, noColor));
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/7f1463c5/log/command/src/main/java/org/apache/karaf/log/command/GetLogLevel.java
----------------------------------------------------------------------
diff --git a/log/command/src/main/java/org/apache/karaf/log/command/GetLogLevel.java b/log/command/src/main/java/org/apache/karaf/log/command/GetLogLevel.java
deleted file mode 100644
index 83e5003..0000000
--- a/log/command/src/main/java/org/apache/karaf/log/command/GetLogLevel.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * 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.karaf.log.command;
-
-import java.util.Map;
-
-import org.apache.karaf.log.core.LogService;
-import org.apache.karaf.shell.api.action.Action;
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Option;
-import org.apache.karaf.shell.api.action.lifecycle.Reference;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.apache.karaf.shell.support.table.ShellTable;
-
-/**
- * Get the log level
- */
-@Command(scope = "log", name = "get", description = "Shows the currently set log level.")
-@Service
-public class GetLogLevel implements Action {
-
-    @Argument(index = 0, name = "logger", description = "The name of the logger, ALL or ROOT (default)", required = false, multiValued = false)
-    String logger;
-
-    @Option(name = "--no-format", description = "Disable table rendered output", required = false, multiValued = false)
-    boolean noFormat;
-
-    @Reference
-    LogService logService;
-
-    @Override
-    public Object execute() throws Exception {
-        Map<String, String> loggers = logService.getLevel(logger);
-
-        ShellTable table = new ShellTable();
-        table.column("Logger");
-        table.column("Level");
-
-        for (String logger : loggers.keySet()) {
-            table.addRow().addContent(logger, loggers.get(logger));
-        }
-
-        table.print(System.out, !noFormat);
-
-        return null;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/7f1463c5/log/command/src/main/java/org/apache/karaf/log/command/LogEntry.java
----------------------------------------------------------------------
diff --git a/log/command/src/main/java/org/apache/karaf/log/command/LogEntry.java b/log/command/src/main/java/org/apache/karaf/log/command/LogEntry.java
deleted file mode 100644
index d7c17a9..0000000
--- a/log/command/src/main/java/org/apache/karaf/log/command/LogEntry.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * 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.karaf.log.command;
-
-import org.apache.karaf.shell.api.action.Action;
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Completion;
-import org.apache.karaf.shell.api.action.Option;
-import org.apache.karaf.shell.api.action.lifecycle.Reference;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.apache.karaf.shell.support.completers.StringsCompleter;
-import org.osgi.service.log.LogService;
-
-import java.util.HashMap;
-import java.util.Map;
-
-@Command(scope = "log", name = "log", description = "Log a message.")
-@Service
-public class LogEntry implements Action {
-
-    @Argument(index = 0, name = "message", description = "The message to log", required = true, multiValued = false)
-    private String message;
-
-    @Option(name = "--level", aliases = {"-l"}, description = "The level the message will be logged at", required = false, multiValued = false)
-    @Completion(value = StringsCompleter.class, values = { "DEBUG", "INFO", "WARNING", "ERROR" })
-    private String level = "INFO";
-
-    @Reference
-    LogService logService;
-
-    private final Map<String,Integer> mappings = new HashMap<String,Integer>();
-
-    public LogEntry() {
-        mappings.put("ERROR", 1);
-        mappings.put("WARNING", 2);
-        mappings.put("INFO", 3);
-        mappings.put("DEBUG", 4);
-    }
-
-    @Override
-    public Object execute() throws Exception {
-        logService.log(toLevel(level.toUpperCase()), message);
-        return null;
-    }
-
-    private int toLevel(String logLevel) {
-        Integer level =  mappings.get(logLevel);
-        if(level == null) {
-            level = 3;
-        }
-        return level;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/7f1463c5/log/command/src/main/java/org/apache/karaf/log/command/LogTail.java
----------------------------------------------------------------------
diff --git a/log/command/src/main/java/org/apache/karaf/log/command/LogTail.java b/log/command/src/main/java/org/apache/karaf/log/command/LogTail.java
deleted file mode 100644
index bf2801e..0000000
--- a/log/command/src/main/java/org/apache/karaf/log/command/LogTail.java
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * 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.karaf.log.command;
-
-import java.io.IOException;
-import java.io.PrintStream;
-import java.util.concurrent.BlockingQueue;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.LinkedBlockingQueue;
-
-import org.apache.karaf.log.core.LogService;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.lifecycle.Reference;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.apache.karaf.shell.api.console.Session;
-import org.ops4j.pax.logging.spi.PaxAppender;
-import org.ops4j.pax.logging.spi.PaxLoggingEvent;
-
-@Command(scope = "log", name = "tail", description = "Continuously display log entries. Use ctrl-c to quit this command")
-@Service
-public class LogTail extends DisplayLog {
-
-    @Reference
-    Session session;
-
-    @Reference
-    LogService logService;
-
-    private ExecutorService executorService = Executors.newSingleThreadExecutor();
-
-    @Override
-    public Object execute() throws Exception {
-        PrintEventThread printThread = new PrintEventThread();
-        executorService.execute(printThread);
-        new Thread(new ReadKeyBoardThread(this, Thread.currentThread())).start();
-        while (!Thread.currentThread().isInterrupted()) {
-            try {
-                Thread.sleep(200);
-            } catch (java.lang.InterruptedException e) {
-                break;
-            }
-        }
-        printThread.abort();
-        executorService.shutdownNow();  
-        return null;      
-    }
-   
-    class ReadKeyBoardThread implements Runnable {
-        private LogTail logTail;
-        private Thread sessionThread;
-        public ReadKeyBoardThread(LogTail logtail, Thread thread) {
-            this.logTail = logtail;
-            this.sessionThread = thread;
-        }
-        public void run() {
-            for (;;) {
-                try {
-                    int c = this.logTail.session.getKeyboard().read();
-                    if (c < 0) {
-                        this.sessionThread.interrupt();
-                        break;
-                    }
-                } catch (IOException e) {
-                    break;
-                }
-                
-            }
-        }
-    } 
-    
-    class PrintEventThread implements Runnable {
-
-        PrintStream out = System.out;
-        boolean doDisplay = true;
-
-        public void run() {
-            Iterable<PaxLoggingEvent> le = logService.getEvents(entries == 0 ? Integer.MAX_VALUE : entries);
-            for (PaxLoggingEvent event : le) {
-                if (event != null) {
-                    printEvent(out, event);
-                }
-            }
-            // Tail
-            final BlockingQueue<PaxLoggingEvent> queue = new LinkedBlockingQueue<PaxLoggingEvent>();
-            PaxAppender appender = new PaxAppender() {
-                public void doAppend(PaxLoggingEvent event) {
-                        queue.add(event);
-                }
-            };
-            try {
-                logService.addAppender(appender);
-                
-                while (doDisplay) {
-                    PaxLoggingEvent event = queue.take();
-                    if (event != null) {
-                        printEvent(out, event);
-                    }
-                }
-            } catch (InterruptedException e) {
-                // Ignore
-            } finally {
-                logService.removeAppender(appender);
-            }
-            out.println();
-            
-        }
-
-        public void abort() {
-            doDisplay = false;
-        }
-
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/7f1463c5/log/command/src/main/java/org/apache/karaf/log/command/SetLogLevel.java
----------------------------------------------------------------------
diff --git a/log/command/src/main/java/org/apache/karaf/log/command/SetLogLevel.java b/log/command/src/main/java/org/apache/karaf/log/command/SetLogLevel.java
deleted file mode 100644
index b1145b4..0000000
--- a/log/command/src/main/java/org/apache/karaf/log/command/SetLogLevel.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * 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.karaf.log.command;
-
-
-import org.apache.karaf.log.core.LogService;
-import org.apache.karaf.shell.api.action.Action;
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Completion;
-import org.apache.karaf.shell.api.action.lifecycle.Reference;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.apache.karaf.shell.support.completers.StringsCompleter;
-
-/**
- * Set the log level for a given logger
- */
-@Command(scope = "log", name = "set", description = "Sets the log level.")
-@Service
-public class SetLogLevel implements Action {
-    
-    @Argument(index = 0, name = "level", description = "The log level to set (TRACE, DEBUG, INFO, WARN, ERROR) or DEFAULT to unset", required = true, multiValued = false)
-    @Completion(value = StringsCompleter.class, values = { "TRACE", "DEBUG", "INFO", "WARN", "ERROR", "DEFAULT" })
-    String level;
-
-    @Argument(index = 1, name = "logger", description = "Logger name or ROOT (default)", required = false, multiValued = false)
-    String logger;
-
-    @Reference
-    LogService logService;
-
-    @Override
-    public Object execute() throws Exception {
-        logService.setLevel(logger, level);
-        return null;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/7f1463c5/log/command/src/main/resources/OSGI-INF/bundle.info
----------------------------------------------------------------------
diff --git a/log/command/src/main/resources/OSGI-INF/bundle.info b/log/command/src/main/resources/OSGI-INF/bundle.info
deleted file mode 100644
index b7aa758..0000000
--- a/log/command/src/main/resources/OSGI-INF/bundle.info
+++ /dev/null
@@ -1,24 +0,0 @@
-h1. Synopsis
-
-${project.name}
-
-${project.description}
-
-Maven URL:
-[mvn:${project.groupId}/${project.artifactId}/${project.version}]
-
-h1. Description
-
-This bundle provides Karaf shell commands to manipulate the Log service.
-
-The following commands are available:
-* log:clear - Clear log entries.
-* log:display-exception - Displays the last occurred exception from the log.
-* log:display - Displays log entries.
-* log:get - Shows the currently set log level.
-* log:tail - Continuously display log entries.
-* log:set - Sets the log level.
-
-h1. See also
-
-Commands - and Logging system - sections of the Karaf User Guide.
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/karaf/blob/7f1463c5/log/command/src/main/resources/OSGI-INF/metatype/metatype.properties
----------------------------------------------------------------------
diff --git a/log/command/src/main/resources/OSGI-INF/metatype/metatype.properties b/log/command/src/main/resources/OSGI-INF/metatype/metatype.properties
deleted file mode 100644
index 713283f..0000000
--- a/log/command/src/main/resources/OSGI-INF/metatype/metatype.properties
+++ /dev/null
@@ -1,31 +0,0 @@
-#
-#  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.
-#
-
-#
-# This file contains localization strings for configuration labels and
-# descriptions as used in the metatype.xml descriptor
-
-log.name = Apache Karaf Log
-log.description = Configuration of Apache Karaf Log
-
-size.name = Size
-size.description = size of the log to keep in memory
-
-pattern.name = Pattern
-pattern.description = Pattern used to display log entries

http://git-wip-us.apache.org/repos/asf/karaf/blob/7f1463c5/log/command/src/main/resources/OSGI-INF/metatype/metatype.xml
----------------------------------------------------------------------
diff --git a/log/command/src/main/resources/OSGI-INF/metatype/metatype.xml b/log/command/src/main/resources/OSGI-INF/metatype/metatype.xml
deleted file mode 100644
index 147cb82..0000000
--- a/log/command/src/main/resources/OSGI-INF/metatype/metatype.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-
-    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.
-
--->
-<metatype:MetaData xmlns:metatype="http://www.osgi.org/xmlns/metatype/v1.0.0" localization="OSGI-INF/metatype/metatype">
-    <OCD id="org.apache.karaf.log" name="%log.name" description="%log.description">
-        <AD id="size" type="Integer" default="500" name="%size.name"
-            description="%size.description"/>
-        <AD id="pattern" type="String" default="%d{ABSOLUTE} | %-5.5p | %-16.16t | %-32.32c{1} | %-32.32C %4L | %m%n" name="%pattern.name"
-            description="%pattern.description"/>
-    </OCD>
-    <Designate pid="org.apache.karaf.log">
-        <Object ocdref="org.apache.karaf.log"/>
-    </Designate>
-</metatype:MetaData>

http://git-wip-us.apache.org/repos/asf/karaf/blob/7f1463c5/log/core/NOTICE
----------------------------------------------------------------------
diff --git a/log/core/NOTICE b/log/core/NOTICE
deleted file mode 100644
index b70f1f9..0000000
--- a/log/core/NOTICE
+++ /dev/null
@@ -1,71 +0,0 @@
-Apache Karaf
-Copyright 2010-2014 The Apache Software Foundation
-
-
-I. Included Software
-
-This product includes software developed at
-The Apache Software Foundation (http://www.apache.org/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-The OSGi Alliance (http://www.osgi.org/).
-Copyright (c) OSGi Alliance (2000, 2010).
-Licensed under the Apache License 2.0.
-
-This product includes software developed at
-OW2 (http://www.ow2.org/).
-Licensed under the BSD License.
-
-This product includes software developed at
-OPS4J (http://www.ops4j.org/).
-Licensed under the Apache License 2.0.
-
-This product includes software developed at
-Eclipse Foundation (http://www.eclipse.org/).
-Licensed under the EPL.
-
-This product includes software written by
-Antony Lesuisse.
-Licensed under Public Domain.
-
-
-II. Used Software
-
-This product uses software developed at
-FUSE Source (http://www.fusesource.org/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-AOP Alliance (http://aopalliance.sourceforge.net/).
-Licensed under the Public Domain.
-
-This product uses software developed at
-Tanuki Software (http://www.tanukisoftware.com/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-Jasypt (http://jasypt.sourceforge.net/).
-Licensed under the Apache License 2.0.
-
-This product uses software developed at
-JLine (http://jline.sourceforge.net).
-Licensed under the BSD License.
-
-This product uses software developed at
-SLF4J (http://www.slf4j.org/).
-Licensed under the MIT License.
-
-This product uses software developed at
-SpringSource (http://www.springsource.org/).
-Licensed under the Apache License 2.0.
-
-This product includes software from http://www.json.org.
-Copyright (c) 2002 JSON.org
-
-
-III. License Summary
-- Apache License 2.0
-- BSD License
-- EPL License
-- MIT License

http://git-wip-us.apache.org/repos/asf/karaf/blob/7f1463c5/log/core/pom.xml
----------------------------------------------------------------------
diff --git a/log/core/pom.xml b/log/core/pom.xml
deleted file mode 100644
index 98f7637..0000000
--- a/log/core/pom.xml
+++ /dev/null
@@ -1,112 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-
-    <!--
-
-        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.
-    -->
-
-    <modelVersion>4.0.0</modelVersion>
-
-    <parent>
-        <groupId>org.apache.karaf.log</groupId>
-        <artifactId>log</artifactId>
-        <version>4.0.0-SNAPSHOT</version>
-        <relativePath>../pom.xml</relativePath>
-    </parent>
-
-    <artifactId>org.apache.karaf.log.core</artifactId>
-    <packaging>bundle</packaging>
-    <name>Apache Karaf :: Log :: Core</name>
-    <description>Core Seervices and JMX MBean to manipulate the Karaf log layer</description>
-
-    <properties>
-        <appendedResourcesDirectory>${basedir}/../../../etc/appended-resources/</appendedResourcesDirectory>
-    </properties>
-
-    <dependencies>
-        <dependency>
-            <groupId>org.osgi</groupId>
-            <artifactId>org.osgi.core</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.osgi</groupId>
-            <artifactId>org.osgi.compendium</artifactId>
-            <scope>provided</scope>
-        </dependency>
-
-        <dependency>
-            <groupId>org.ops4j.pax.logging</groupId>
-            <artifactId>pax-logging-service</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.ops4j.pax.logging</groupId>
-            <artifactId>pax-logging-api</artifactId>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.karaf</groupId>
-            <artifactId>org.apache.karaf.util</artifactId>
-            <scope>provided</scope>
-        </dependency>
-    </dependencies>
-
-    <build>
-        <resources>
-            <resource>
-                <directory>src/main/resources</directory>
-                <includes>
-                    <include>**/*</include>
-                </includes>
-            </resource>
-            <resource>
-                <directory>src/main/resources</directory>
-                <filtering>true</filtering>
-                <includes>
-                    <include>**/*.info</include>
-                </includes>
-            </resource>
-        </resources>
-        <plugins>
-            <plugin>
-                <groupId>org.apache.felix</groupId>
-                <artifactId>maven-bundle-plugin</artifactId>
-                <configuration>
-                    <instructions>
-                        <Export-Package>
-                            org.apache.karaf.log.core
-                        </Export-Package>
-                        <Import-Package>
-                            *
-                        </Import-Package>
-                        <Private-Package>
-                            org.apache.karaf.log.core.internal,
-                            org.apache.karaf.log.core.internal.layout,
-                            org.apache.karaf.log.core.internal.osgi,
-                            org.apache.karaf.util.tracker
-                        </Private-Package>
-                        <Bundle-Activator>
-                            org.apache.karaf.log.core.internal.osgi.Activator
-                        </Bundle-Activator>
-                    </instructions>
-                </configuration>
-            </plugin>
-        </plugins>
-    </build>
-
-</project>

http://git-wip-us.apache.org/repos/asf/karaf/blob/7f1463c5/log/core/src/main/java/org/apache/karaf/log/core/Level.java
----------------------------------------------------------------------
diff --git a/log/core/src/main/java/org/apache/karaf/log/core/Level.java b/log/core/src/main/java/org/apache/karaf/log/core/Level.java
deleted file mode 100644
index a83396f..0000000
--- a/log/core/src/main/java/org/apache/karaf/log/core/Level.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * 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.karaf.log.core;
-
-/**
- * Enumeration of available log levels for the log:set command and
- * the command completer
- */
-public enum Level {
-
-    TRACE,
-    DEBUG,
-    INFO,
-    WARN,
-    ERROR,
-    DEFAULT;
-    
-    /**
-     * Convert the list of values into a String array
-     * 
-     * @return all the values as a String array
-     */
-    public static String[] strings() {
-        String[] values = new String[values().length];
-        for (int i = 0 ; i < values.length ; i++) {
-            values[i] = values()[i].name();
-        }
-        return values;
-    }
-    
-    /**
-     * Check if the string value represents the default level
-     * 
-     * @param level the level value
-     * @return <code>true</code> if the value represents the {@link #DEFAULT} level
-     */
-    public static boolean isDefault(String level) {
-        return valueOf(level).equals(DEFAULT);
-    }
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/7f1463c5/log/core/src/main/java/org/apache/karaf/log/core/LogEventFormatter.java
----------------------------------------------------------------------
diff --git a/log/core/src/main/java/org/apache/karaf/log/core/LogEventFormatter.java b/log/core/src/main/java/org/apache/karaf/log/core/LogEventFormatter.java
deleted file mode 100644
index 71fe275..0000000
--- a/log/core/src/main/java/org/apache/karaf/log/core/LogEventFormatter.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * 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.karaf.log.core;
-
-import org.ops4j.pax.logging.spi.PaxLoggingEvent;
-
-public interface LogEventFormatter {
-
-    public abstract String format(PaxLoggingEvent event, String overridenPattern, boolean noColor);
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/7f1463c5/log/core/src/main/java/org/apache/karaf/log/core/LogMBean.java
----------------------------------------------------------------------
diff --git a/log/core/src/main/java/org/apache/karaf/log/core/LogMBean.java b/log/core/src/main/java/org/apache/karaf/log/core/LogMBean.java
deleted file mode 100644
index ad5006f..0000000
--- a/log/core/src/main/java/org/apache/karaf/log/core/LogMBean.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * 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.karaf.log.core;
-
-import java.util.Map;
-
-/**
- * Log MBean.
- */
-public interface LogMBean {
-
-    String getLevel();
-    Map<String, String> getLevel(String logger);
-
-    void setLevel(String level);
-    void setLevel(String logger, String level);
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/7f1463c5/log/core/src/main/java/org/apache/karaf/log/core/LogService.java
----------------------------------------------------------------------
diff --git a/log/core/src/main/java/org/apache/karaf/log/core/LogService.java b/log/core/src/main/java/org/apache/karaf/log/core/LogService.java
deleted file mode 100644
index ae9f678..0000000
--- a/log/core/src/main/java/org/apache/karaf/log/core/LogService.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * 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.karaf.log.core;
-
-import org.ops4j.pax.logging.spi.PaxAppender;
-import org.ops4j.pax.logging.spi.PaxLoggingEvent;
-
-import java.util.Map;
-
-public interface LogService {
-
-    String getLevel();
-    void setLevel(String level);
-
-    Map<String, String> getLevel(String logger);
-    void setLevel(String logger, String level);
-    
-    void clearEvents();
-    Iterable<PaxLoggingEvent> getEvents();
-    Iterable<PaxLoggingEvent> getEvents(int maxNum);
-    PaxLoggingEvent getLastException(String logger);
-    void addAppender(PaxAppender appender);
-    void removeAppender(PaxAppender appender);
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/7f1463c5/log/core/src/main/java/org/apache/karaf/log/core/internal/LogEventFormatterImpl.java
----------------------------------------------------------------------
diff --git a/log/core/src/main/java/org/apache/karaf/log/core/internal/LogEventFormatterImpl.java b/log/core/src/main/java/org/apache/karaf/log/core/internal/LogEventFormatterImpl.java
deleted file mode 100644
index 0ba1f3e..0000000
--- a/log/core/src/main/java/org/apache/karaf/log/core/internal/LogEventFormatterImpl.java
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- * 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.karaf.log.core.internal;
-
-import org.apache.karaf.log.core.LogEventFormatter;
-import org.apache.karaf.log.core.internal.layout.PatternConverter;
-import org.apache.karaf.log.core.internal.layout.PatternParser;
-import org.ops4j.pax.logging.spi.PaxLoggingEvent;
-
-public class LogEventFormatterImpl implements LogEventFormatter {
-
-    protected String pattern;
-    protected String fatalColor;
-    protected String errorColor;
-    protected String warnColor;
-    protected String infoColor;
-    protected String debugColor;
-    protected String traceColor;
-
-    private static final String FATAL = "fatal";
-    private static final String ERROR = "error";
-    private static final String WARN = "warn";
-    private static final String INFO = "info";
-    private static final String DEBUG = "debug";
-    private static final String TRACE = "trace";
-
-    private static final char FIRST_ESC_CHAR = 27;
-    private static final char SECOND_ESC_CHAR = '[';
-    private static final char COMMAND_CHAR = 'm';
-
-    public String getPattern() {
-        return pattern;
-    }
-
-    public void setPattern(String pattern) {
-        this.pattern = pattern;
-    }
-
-    public String getFatalColor() {
-        return fatalColor;
-    }
-
-    public void setFatalColor(String fatalColor) {
-        this.fatalColor = fatalColor;
-    }
-
-    public String getErrorColor() {
-        return errorColor;
-    }
-
-    public void setErrorColor(String errorColor) {
-        this.errorColor = errorColor;
-    }
-
-    public String getWarnColor() {
-        return warnColor;
-    }
-
-    public void setWarnColor(String warnColor) {
-        this.warnColor = warnColor;
-    }
-
-    public String getInfoColor() {
-        return infoColor;
-    }
-
-    public void setInfoColor(String infoColor) {
-        this.infoColor = infoColor;
-    }
-
-    public String getDebugColor() {
-        return debugColor;
-    }
-
-    public void setDebugColor(String debugColor) {
-        this.debugColor = debugColor;
-    }
-
-    public String getTraceColor() {
-        return traceColor;
-    }
-
-    public void setTraceColor(String traceColor) {
-        this.traceColor = traceColor;
-    }
-
-    /* (non-Javadoc)
-     * @see org.apache.karaf.log.core.internal.LogEventFormatter#format(org.ops4j.pax.logging.spi.PaxLoggingEvent, java.lang.String, boolean)
-     */
-    @Override
-    public String format(PaxLoggingEvent event, String overridenPattern, boolean noColor) {
-        final PatternConverter cnv = new PatternParser(overridenPattern != null ? overridenPattern : pattern).parse();
-        String color = getColor(event, noColor);
-        StringBuffer sb = new StringBuffer();
-        sb.setLength(0);
-        if (color != null) {
-            sb.append(FIRST_ESC_CHAR);
-            sb.append(SECOND_ESC_CHAR);
-            sb.append(color);
-            sb.append(COMMAND_CHAR);
-        }
-        for (PatternConverter pc = cnv; pc != null; pc = pc.next) {
-            pc.format(sb, event);
-        }
-        if (event.getThrowableStrRep() != null) {
-            for (String r : event.getThrowableStrRep()) {
-                sb.append(r).append('\n');
-            }
-        }
-        if (color != null) {
-            sb.append(FIRST_ESC_CHAR);
-            sb.append(SECOND_ESC_CHAR);
-            sb.append("0");
-            sb.append(COMMAND_CHAR);
-        }
-        return sb.toString();
-    }
-
-    private String getColor(PaxLoggingEvent event, boolean noColor) {
-        String color = null;
-        if (!noColor && event != null && event.getLevel() != null && event.getLevel().toString() != null) {
-            String lvl = event.getLevel().toString().toLowerCase();
-            if (FATAL.equals(lvl)) {
-                color = fatalColor;
-            } else if (ERROR.equals(lvl)) {
-                color = errorColor;
-            } else if (WARN.equals(lvl)) {
-                color = warnColor;
-            } else if (INFO.equals(lvl)) {
-                color = infoColor;
-            } else if (DEBUG.equals(lvl)) {
-                color = debugColor;
-            } else if (TRACE.equals(lvl)) {
-                color = traceColor;
-            }
-            if (color != null && color.length() == 0) {
-                color = null;
-            }
-        }
-        return color;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/7f1463c5/log/core/src/main/java/org/apache/karaf/log/core/internal/LogMBeanImpl.java
----------------------------------------------------------------------
diff --git a/log/core/src/main/java/org/apache/karaf/log/core/internal/LogMBeanImpl.java b/log/core/src/main/java/org/apache/karaf/log/core/internal/LogMBeanImpl.java
deleted file mode 100644
index 49ccbf6..0000000
--- a/log/core/src/main/java/org/apache/karaf/log/core/internal/LogMBeanImpl.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * 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.karaf.log.core.internal;
-
-import javax.management.NotCompliantMBeanException;
-import javax.management.StandardMBean;
-
-import org.apache.karaf.log.core.LogMBean;
-import org.apache.karaf.log.core.LogService;
-
-import java.util.Map;
-
-/**
- * Implementation of the LogMBean.
- */
-public class LogMBeanImpl extends StandardMBean implements LogMBean {
-
-    private final LogService logService;
-
-    public LogMBeanImpl(LogService logService) throws NotCompliantMBeanException {
-        super(LogMBean.class);
-        this.logService = logService;
-    }
-
-    @Override
-    public String getLevel() {
-        return logService.getLevel();
-    }
-
-    @Override
-    public Map<String, String> getLevel(String logger) {
-        return logService.getLevel(logger);
-    }
-
-    @Override
-    public void setLevel(String level) {
-        this.logService.setLevel(level);
-    }
-
-    @Override
-    public void setLevel(String logger, String level) {
-        this.logService.setLevel(logger, level);
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/7f1463c5/log/core/src/main/java/org/apache/karaf/log/core/internal/LogServiceImpl.java
----------------------------------------------------------------------
diff --git a/log/core/src/main/java/org/apache/karaf/log/core/internal/LogServiceImpl.java b/log/core/src/main/java/org/apache/karaf/log/core/internal/LogServiceImpl.java
deleted file mode 100644
index 4751873..0000000
--- a/log/core/src/main/java/org/apache/karaf/log/core/internal/LogServiceImpl.java
+++ /dev/null
@@ -1,261 +0,0 @@
-/*
- * 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.karaf.log.core.internal;
-
-import java.io.IOException;
-import java.util.Dictionary;
-import java.util.Enumeration;
-import java.util.Map;
-import java.util.TreeMap;
-
-import org.apache.karaf.log.core.Level;
-import org.apache.karaf.log.core.LogService;
-import org.ops4j.pax.logging.spi.PaxAppender;
-import org.ops4j.pax.logging.spi.PaxLoggingEvent;
-import org.osgi.service.cm.Configuration;
-import org.osgi.service.cm.ConfigurationAdmin;
-
-public class LogServiceImpl implements LogService {
-
-    static final String CONFIGURATION_PID = "org.ops4j.pax.logging";
-    static final String ROOT_LOGGER_PREFIX = "log4j.rootLogger";
-    static final String LOGGER_PREFIX = "log4j.logger.";
-    static final String ALL_LOGGER = "ALL";
-    static final String ROOT_LOGGER = "ROOT";
-    
-    private final ConfigurationAdmin configAdmin;
-    private final LruList events;
-
-    public LogServiceImpl(ConfigurationAdmin configAdmin, LruList events) {
-        this.configAdmin = configAdmin;
-        this.events = events;
-    }
-
-    public String getLevel() {
-        return getLevel(null).get(ROOT_LOGGER);
-    }
-
-    public Map<String, String> getLevel(String logger) {
-        Configuration cfg;
-        try {
-            cfg = configAdmin.getConfiguration(CONFIGURATION_PID, null);
-        } catch (IOException e) {
-            throw new RuntimeException("Error retrieving Log information from config admin", e);
-        }
-        @SuppressWarnings("rawtypes")
-        Dictionary props = cfg.getProperties();
-
-        if (ROOT_LOGGER.equalsIgnoreCase(logger)) {
-            logger = null;
-        }
-
-        Map<String, String> loggers = new TreeMap<String, String>();
-
-        if (ALL_LOGGER.equalsIgnoreCase(logger)) {
-            String root = getLevelFromProperty((String) props.get(ROOT_LOGGER_PREFIX));
-            loggers.put("ROOT", root);
-            for (Enumeration e = props.keys(); e.hasMoreElements(); ) {
-                String prop = (String) e.nextElement();
-                if (prop.startsWith(LOGGER_PREFIX)) {
-                    String val = getLevelFromProperty((String) props.get(prop));
-                    loggers.put(prop.substring(LOGGER_PREFIX.length()), val);
-                }
-            }
-            return loggers;
-        }
-
-        String l = logger;
-        String val;
-        for (;;) {
-            String prop;
-            if (l == null) {
-                prop = ROOT_LOGGER_PREFIX;
-            } else {
-                prop = LOGGER_PREFIX + l;
-            }
-            val = (String) props.get(prop);
-            val = getLevelFromProperty(val);
-            if (val != null || l == null) {
-                break;
-            }
-            int idx = l.lastIndexOf('.');
-            if (idx < 0) {
-                l = null;
-            } else {
-                l = l.substring(0, idx);
-            }
-        }
-
-        if (logger == null)
-            logger = ROOT_LOGGER;
-
-        loggers.put(logger, val);
-
-        return loggers;
-    }
-
-    public void setLevel(String level) {
-        setLevel(null, level);
-    }
-
-    @SuppressWarnings("unchecked")
-    public void setLevel(String logger, String level) {
-        if (ROOT_LOGGER.equalsIgnoreCase(logger)) {
-            logger = null;
-        }
-
-        // make sure both uppercase and lowercase levels are supported
-        level = level.toUpperCase();
-
-        // check if the level is valid
-        Level.valueOf(level);
-
-        if (Level.isDefault(level) && logger == null) {
-            throw new IllegalStateException("Can not unset the ROOT logger");
-        }
-
-        Configuration cfg = getConfiguration();
-        Dictionary props = cfg.getProperties();
-
-        String val;
-        String prop;
-        if (logger == null) {
-            prop = ROOT_LOGGER_PREFIX;
-        } else {
-            prop = LOGGER_PREFIX + logger;
-        }
-
-        val = (String) props.get(prop);
-        if (Level.isDefault(level)) {
-            if (val != null) {
-                val = val.trim();
-                int idx = val.indexOf(",");
-                if (idx < 0) {
-                    val = null;
-                } else {
-                    val = val.substring(idx);
-                }
-            }
-        } else {
-            if (val == null) {
-                val = level;
-            } else {
-                val = val.trim();
-                int idx = val.indexOf(",");
-                if (idx < 0) {
-                    val = level;
-                } else {
-                    val = level + val.substring(idx);
-                }
-            }
-        }
-        if (val == null) {
-            props.remove(prop);
-        } else {
-            props.put(prop, val);
-        }
-        try {
-            cfg.update(props);
-        } catch (IOException e) {
-            throw new RuntimeException("Error writing log config to config admin", e);
-        }
-    }
-
-    private boolean checkIfFromRequestedLog(PaxLoggingEvent event, String logger) {
-        return (event.getLoggerName().lastIndexOf(logger) >= 0) ? true : false;
-    }
-
-    private String getLevelFromProperty(String prop) {
-        if (prop == null) {
-            return null;
-        } else {
-            String val = prop.trim();
-            int idx = val.indexOf(",");
-            if (idx == 0) {
-                val = null;
-            } else if (idx > 0) {
-                val = val.substring(0, idx);
-            }
-            return val;
-        }
-    }
-
-    private Configuration getConfiguration() {
-        try {
-            return configAdmin.getConfiguration(CONFIGURATION_PID, null);
-        } catch (IOException e) {
-            throw new RuntimeException("Error retrieving Log information from config admin", e);
-        }
-    }
-
-    @Override
-    public Iterable<PaxLoggingEvent> getEvents() {
-        return events.getElements();
-    }
-
-    @Override
-    public Iterable<PaxLoggingEvent> getEvents(int maxNum) {
-        return events.getElements(maxNum);
-    }
-
-    @Override
-    public void clearEvents() {
-        events.clear();
-    }
-    
-    @Override
-    public PaxLoggingEvent getLastException(String logger) {
-        PaxLoggingEvent throwableEvent = null;
-        Iterable<PaxLoggingEvent> le = getEvents();
-        for (PaxLoggingEvent event : le) {
-            // if this is an exception, and the log is the same as the requested log,
-            // then save this exception and continue iterating from oldest to newest
-            if ((event.getThrowableStrRep() != null)
-                    &&(logger != null)
-                    &&(checkIfFromRequestedLog(event, logger))) {
-                throwableEvent = event;
-              // Do not break, as we iterate from the oldest to the newest event
-            } else if ((event.getThrowableStrRep() != null)&&(logger == null)) {
-                // now check if there has been no log passed in, and if this is an exception
-                // then save this exception and continue iterating from oldest to newest
-                throwableEvent = event;             
-            }
-        }
-
-        return throwableEvent;
-    }
-
-    @Override
-    public void addAppender(PaxAppender appender) {
-        events.addAppender(appender);
-    }
-
-    @Override
-    public void removeAppender(PaxAppender appender) {
-        events.removeAppender(appender);
-    }
-
-    public Level convertToLevel(String level) {
-        level = level.toUpperCase();
-        Level res = Level.valueOf(level);
-        if (res == null) {
-            throw new IllegalArgumentException("level must be set to TRACE, DEBUG, INFO, WARN or ERROR (or DEFAULT to unset it)");
-        }
-        return res;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/7f1463c5/log/core/src/main/java/org/apache/karaf/log/core/internal/LruList.java
----------------------------------------------------------------------
diff --git a/log/core/src/main/java/org/apache/karaf/log/core/internal/LruList.java b/log/core/src/main/java/org/apache/karaf/log/core/internal/LruList.java
deleted file mode 100644
index ea51b34..0000000
--- a/log/core/src/main/java/org/apache/karaf/log/core/internal/LruList.java
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * 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.karaf.log.core.internal;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-
-import org.ops4j.pax.logging.spi.PaxAppender;
-import org.ops4j.pax.logging.spi.PaxLoggingEvent;
-
-/**
- * A list that only keep the last N elements added
- */
-public class LruList implements PaxAppender {
-
-    private PaxLoggingEvent[] elements;
-    private transient int start = 0;
-    private transient int end = 0;
-    private transient boolean full = false;
-    private final int maxElements;
-    private final List<PaxAppender> appenders;
-
-    public LruList(int size) {
-        if (size <= 0) {
-            throw new IllegalArgumentException("The size must be greater than 0");
-        }
-        elements = new PaxLoggingEvent[size];
-        maxElements = elements.length;
-        appenders = new ArrayList<PaxAppender>();
-    }
-
-    public synchronized int size() {
-        int size = 0;
-        if (end < start) {
-            size = maxElements - start + end;
-        } else if (end == start) {
-            size = (full ? maxElements : 0);
-        } else {
-            size = end - start;
-        }
-        return size;
-    }
-
-    public synchronized void clear() {
-        start = 0;
-        end = 0;
-        elements = new PaxLoggingEvent[maxElements];
-    }
-
-    public synchronized void add(PaxLoggingEvent element) {
-        if (null == element) {
-             throw new NullPointerException("Attempted to add null object to buffer");
-        }
-        if (size() == maxElements) {
-            Object e = elements[start];
-            if (null != e) {
-                elements[start++] = null;
-                if (start >= maxElements) {
-                    start = 0;
-                }
-                full = false;
-            }
-        }
-        elements[end++] = element;
-        if (end >= maxElements) {
-            end = 0;
-        }
-        if (end == start) {
-            full = true;
-        }
-        for (PaxAppender appender : appenders) {
-            try {
-                appender.doAppend(element);
-            } catch (Throwable t) {
-                // Ignore
-            }
-        }
-    }
-
-    public synchronized Iterable<PaxLoggingEvent> getElements() {
-        return getElements(size());
-    }
-
-    public synchronized Iterable<PaxLoggingEvent> getElements(int nb) {
-        int s = size();
-        nb = Math.min(Math.max(0, nb), s);
-        PaxLoggingEvent[] e = new PaxLoggingEvent[nb];
-        for (int i = 0; i < nb; i++) {
-            e[i] = elements[(i + s - nb + start) % maxElements];
-        }
-        return Arrays.asList(e);
-    }
-
-    public synchronized void addAppender(PaxAppender appender) {
-        this.appenders.add(appender);
-    }
-
-    public synchronized void removeAppender(PaxAppender appender) {
-        this.appenders.remove(appender);
-    }
-    
-    public void doAppend(PaxLoggingEvent event) {
-        event.getProperties(); // ensure MDC properties are copied
-        add(event);
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/7f1463c5/log/core/src/main/java/org/apache/karaf/log/core/internal/layout/AbsoluteTimeDateFormat.java
----------------------------------------------------------------------
diff --git a/log/core/src/main/java/org/apache/karaf/log/core/internal/layout/AbsoluteTimeDateFormat.java b/log/core/src/main/java/org/apache/karaf/log/core/internal/layout/AbsoluteTimeDateFormat.java
deleted file mode 100644
index 8bb3ff3..0000000
--- a/log/core/src/main/java/org/apache/karaf/log/core/internal/layout/AbsoluteTimeDateFormat.java
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * 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.karaf.log.core.internal.layout;
-
-import java.text.DateFormat;
-import java.text.FieldPosition;
-import java.text.ParsePosition;
-import java.util.Calendar;
-import java.util.Date;
-import java.util.TimeZone;
-
-/**
- * Copied from log4j
- */
-/**
-   Formats a {@link Date} in the format "HH:mm:ss,SSS" for example,
-   "15:49:37,459".
-
-   @since 0.7.5
-*/
-public class AbsoluteTimeDateFormat extends DateFormat {
-
-  /**
-     String constant used to specify {@link
-     org.apache.log4j.helpers.AbsoluteTimeDateFormat} in layouts. Current
-     value is <b>ABSOLUTE</b>.  */
-  public final static String ABS_TIME_DATE_FORMAT = "ABSOLUTE";
-
-  /**
-     String constant used to specify {@link
-     org.apache.log4j.helpers.DateTimeDateFormat} in layouts.  Current
-     value is <b>DATE</b>.
-  */
-  public final static String DATE_AND_TIME_DATE_FORMAT = "DATE";
-
-  /**
-     String constant used to specify {@link
-     org.apache.log4j.helpers.ISO8601DateFormat} in layouts. Current
-     value is <b>ISO8601</b>.
-  */
-  public final static String ISO8601_DATE_FORMAT = "ISO8601";
-
-  public
-  AbsoluteTimeDateFormat() {
-    setCalendar(Calendar.getInstance());
-  }
-
-  public
-  AbsoluteTimeDateFormat(TimeZone timeZone) {
-    setCalendar(Calendar.getInstance(timeZone));
-  }
-
-  private static long   previousTime;
-  private static char[] previousTimeWithoutMillis = new char[9]; // "HH:mm:ss."
-
-  /**
-     Appends to <code>sbuf</code> the time in the format
-     "HH:mm:ss,SSS" for example, "15:49:37,459"
-
-     @param date the date to format
-     @param sbuf the string buffer to write to
-     @param fieldPosition remains untouched
-    */
-  public
-  StringBuffer format(Date date, StringBuffer sbuf,
-		      FieldPosition fieldPosition) {
-
-    long now = date.getTime();
-    int millis = (int)(now % 1000);
-
-    if ((now - millis) != previousTime) {
-      // We reach this point at most once per second
-      // across all threads instead of each time format()
-      // is called. This saves considerable CPU time.
-
-      calendar.setTime(date);
-
-      int start = sbuf.length();
-
-      int hour = calendar.get(Calendar.HOUR_OF_DAY);
-      if(hour < 10) {
-	sbuf.append('0');
-      }
-      sbuf.append(hour);
-      sbuf.append(':');
-
-      int mins = calendar.get(Calendar.MINUTE);
-      if(mins < 10) {
-	sbuf.append('0');
-      }
-      sbuf.append(mins);
-      sbuf.append(':');
-
-      int secs = calendar.get(Calendar.SECOND);
-      if(secs < 10) {
-	sbuf.append('0');
-      }
-      sbuf.append(secs);
-      sbuf.append(',');
-
-      // store the time string for next time to avoid recomputation
-      sbuf.getChars(start, sbuf.length(), previousTimeWithoutMillis, 0);
-
-      previousTime = now - millis;
-    }
-    else {
-      sbuf.append(previousTimeWithoutMillis);
-    }
-
-
-
-    if(millis < 100)
-      sbuf.append('0');
-    if(millis < 10)
-      sbuf.append('0');
-
-    sbuf.append(millis);
-    return sbuf;
-  }
-
-  /**
-     This method does not do anything but return <code>null</code>.
-   */
-  public
-  Date parse(String s, ParsePosition pos) {
-    return null;
-  }
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/7f1463c5/log/core/src/main/java/org/apache/karaf/log/core/internal/layout/DateTimeDateFormat.java
----------------------------------------------------------------------
diff --git a/log/core/src/main/java/org/apache/karaf/log/core/internal/layout/DateTimeDateFormat.java b/log/core/src/main/java/org/apache/karaf/log/core/internal/layout/DateTimeDateFormat.java
deleted file mode 100644
index 1aa884d..0000000
--- a/log/core/src/main/java/org/apache/karaf/log/core/internal/layout/DateTimeDateFormat.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * 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.karaf.log.core.internal.layout;
-
-import java.text.DateFormatSymbols;
-import java.text.FieldPosition;
-import java.text.ParsePosition;
-import java.util.Calendar;
-import java.util.Date;
-import java.util.TimeZone;
-
-/**
- * Copied from log4j
- */
-/**
-   Formats a {@link Date} in the format "dd MMM yyyy HH:mm:ss,SSS" for example,
-   "06 Nov 1994 15:49:37,459".
-
-   @since 0.7.5
-*/
-public class DateTimeDateFormat extends AbsoluteTimeDateFormat {
-
-  String[] shortMonths;
-
-  public
-  DateTimeDateFormat() {
-    super();
-    shortMonths = new DateFormatSymbols().getShortMonths();
-  }
-
-  public
-  DateTimeDateFormat(TimeZone timeZone) {
-    this();
-    setCalendar(Calendar.getInstance(timeZone));
-  }
-
-  /**
-     Appends to <code>sbuf</code> the date in the format "dd MMM yyyy
-     HH:mm:ss,SSS" for example, "06 Nov 1994 08:49:37,459".
-
-     @param sbuf the string buffer to write to
-  */
-  public
-  StringBuffer format(Date date, StringBuffer sbuf,
-		      FieldPosition fieldPosition) {
-
-    calendar.setTime(date);
-
-    int day = calendar.get(Calendar.DAY_OF_MONTH);
-    if(day < 10)
-      sbuf.append('0');
-    sbuf.append(day);
-    sbuf.append(' ');
-    sbuf.append(shortMonths[calendar.get(Calendar.MONTH)]);
-    sbuf.append(' ');
-
-    int year =  calendar.get(Calendar.YEAR);
-    sbuf.append(year);
-    sbuf.append(' ');
-
-    return super.format(date, sbuf, fieldPosition);
-  }
-
-  /**
-     This method does not do anything but return <code>null</code>.
-   */
-  public
-  Date parse(java.lang.String s, ParsePosition pos) {
-    return null;
-  }
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/7f1463c5/log/core/src/main/java/org/apache/karaf/log/core/internal/layout/FormattingInfo.java
----------------------------------------------------------------------
diff --git a/log/core/src/main/java/org/apache/karaf/log/core/internal/layout/FormattingInfo.java b/log/core/src/main/java/org/apache/karaf/log/core/internal/layout/FormattingInfo.java
deleted file mode 100644
index 6fd728f..0000000
--- a/log/core/src/main/java/org/apache/karaf/log/core/internal/layout/FormattingInfo.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * 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.karaf.log.core.internal.layout;
-
-
-/**
- * Copied from log4j
- */
-/**
-   FormattingInfo instances contain the information obtained when parsing
-   formatting modifiers in conversion modifiers.
-
-   @since 0.8.2
- */
-public class FormattingInfo {
-  int min = -1;
-  int max = 0x7FFFFFFF;
-  boolean leftAlign = false;
-
-  void reset() {
-    min = -1;
-    max = 0x7FFFFFFF;
-    leftAlign = false;
-  }
-
-  void dump() {
-    //LogLog.debug("min="+min+", max="+max+", leftAlign="+leftAlign);
-  }
-}
-