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 2015/04/10 15:44:29 UTC

[5/5] karaf git commit: [KARAF-3635] Provide a black list for features

[KARAF-3635] Provide a black list for features


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

Branch: refs/heads/master
Commit: 642f4a357c3ca35d2c6b6a73a6ebf4e91673bfd4
Parents: 8992a4f
Author: Guillaume Nodet <gn...@gmail.com>
Authored: Fri Apr 10 15:43:29 2015 +0200
Committer: Guillaume Nodet <gn...@gmail.com>
Committed: Fri Apr 10 15:43:51 2015 +0200

----------------------------------------------------------------------
 .../karaf/features/internal/model/Config.java   |   2 +-
 .../karaf/features/internal/osgi/Activator.java |   4 +-
 .../features/internal/service/Blacklist.java    | 168 +++++++++++++++++++
 .../internal/service/FeaturesServiceImpl.java   |  14 +-
 .../internal/service/RepositoryImpl.java        |   7 +
 .../karaf/features/FeaturesServiceTest.java     |   8 +-
 .../internal/service/BlacklistTest.java         |  92 ++++++++++
 .../service/FeaturesServiceImplTest.java        |   8 +-
 .../assembly/AssemblyDeployCallback.java        |  15 ++
 .../apache/karaf/profile/assembly/Builder.java  | 125 ++++++++++++--
 .../karaf/tooling/features/InstallKarsMojo.java |  20 +++
 11 files changed, 432 insertions(+), 31 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/karaf/blob/642f4a35/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
index de5bc6e..a7cb405 100644
--- 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
@@ -53,7 +53,7 @@ import org.apache.karaf.features.ConfigInfo;
  */
 @XmlAccessorType(XmlAccessType.FIELD)
 @XmlType(name = "config", propOrder = {"value"})
-public class Config implements ConfigInfo{
+public class Config implements ConfigInfo {
 
     @XmlValue
     protected String value;

http://git-wip-us.apache.org/repos/asf/karaf/blob/642f4a35/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
index a039aa0..2b29bf8 100644
--- 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
@@ -174,6 +174,7 @@ public class Activator extends BaseActivator {
         int downloadThreads = getInt("downloadThreads", FeaturesService.DEFAULT_DOWNLOAD_THREADS);
         long scheduleDelay = getLong("scheduleDelay", FeaturesService.DEFAULT_SCHEDULE_DELAY);
         int scheduleMaxRun = getInt("scheduleMaxRun", FeaturesService.DEFAULT_SCHEDULE_MAX_RUN);
+        String blacklisted = getString("blacklisted", new File(System.getProperty("karaf.etc"), "blacklisted.properties").toURI().toString());
         StateStorage stateStorage = new StateStorage() {
             @Override
             protected InputStream getInputStream() throws IOException {
@@ -213,7 +214,8 @@ public class Activator extends BaseActivator {
                 globalRepository,
                 downloadThreads,
                 scheduleDelay,
-                scheduleMaxRun);
+                scheduleMaxRun,
+                blacklisted);
         register(FeaturesService.class, featuresService);
 
         featuresListenerTracker = new ServiceTracker<>(

http://git-wip-us.apache.org/repos/asf/karaf/blob/642f4a35/features/core/src/main/java/org/apache/karaf/features/internal/service/Blacklist.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/service/Blacklist.java b/features/core/src/main/java/org/apache/karaf/features/internal/service/Blacklist.java
new file mode 100644
index 0000000..ae40e3a
--- /dev/null
+++ b/features/core/src/main/java/org/apache/karaf/features/internal/service/Blacklist.java
@@ -0,0 +1,168 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.karaf.features.internal.service;
+
+import java.io.BufferedReader;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.net.URL;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+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.features.internal.model.Bundle;
+import org.apache.karaf.features.internal.model.Conditional;
+import org.apache.karaf.features.internal.model.Feature;
+import org.apache.karaf.features.internal.model.Features;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Helper class to deal with blacklisted features and bundles.
+ */
+public class Blacklist {
+
+    protected static final String BLACKLIST_URL = "url";
+    protected static final String BLACKLIST_RANGE = "range";
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(Blacklist.class);
+
+    private Blacklist() {
+    }
+
+    public static void blacklist(Features features, String blacklisted) {
+        Set<String> blacklist = loadBlacklist(blacklisted);
+        blacklist(features, blacklist);
+    }
+
+    public static void blacklist(Features features, Collection<String> blacklist) {
+        if (!blacklist.isEmpty()) {
+            Clause[] clauses = Parser.parseClauses(blacklist.toArray(new String[blacklist.size()]));
+            blacklist(features, clauses);
+        }
+    }
+
+    public static void blacklist(Features features, Clause[] clauses) {
+        for (Iterator<Feature> iterator = features.getFeature().iterator(); iterator.hasNext(); ) {
+            Feature feature = iterator.next();
+            if (blacklist(feature, clauses)) {
+                iterator.remove();
+            }
+        }
+    }
+
+    public static boolean blacklist(Feature feature, Clause[] clauses) {
+        for (Clause clause : clauses) {
+            // Check feature name
+            if (clause.getName().equals(feature.getName())) {
+                // Check feature version
+                VersionRange range = VersionRange.ANY_VERSION;
+                String vr = clause.getAttribute(BLACKLIST_RANGE);
+                if (vr != null) {
+                    range = new VersionRange(vr, true);
+                }
+                if (range.contains(VersionTable.getVersion(feature.getVersion()))) {
+                    return true;
+                }
+            }
+            // Check bundles
+            blacklist(feature.getBundle(), clauses);
+            // Check conditional bundles
+            for (Conditional cond : feature.getConditional()) {
+                blacklist(cond.getBundle(), clauses);
+            }
+        }
+        return false;
+    }
+
+    private static void blacklist(List<Bundle> bundles, Clause[] clauses) {
+        for (Iterator<Bundle> iterator = bundles.iterator(); iterator.hasNext();) {
+            Bundle info = iterator.next();
+            for (Clause clause : clauses) {
+                String url = clause.getName();
+                if (clause.getAttribute(BLACKLIST_URL) != null) {
+                    url = clause.getAttribute(BLACKLIST_URL);
+                }
+                if (info.getLocation().equals(url)) {
+                    iterator.remove();
+                    break;
+                }
+            }
+        }
+    }
+
+    public static Set<String> loadBlacklist(String blacklistUrl) {
+        Set<String> blacklist = new HashSet<>();
+        try {
+            if (blacklistUrl != null) {
+                try (
+                        InputStream is = new URL(blacklistUrl).openStream()
+                ) {
+                    BufferedReader reader = new BufferedReader(new InputStreamReader(is));
+                    String line;
+                    while ((line = reader.readLine()) != null) {
+                        line = line.trim();
+                        if (!line.isEmpty() && !line.startsWith("#")) {
+                            blacklist.add(line);
+                        }
+                    }
+                }
+            }
+        } catch (Exception e) {
+            LOGGER.debug("Unable to load overrides bundles list", e);
+        }
+        return blacklist;
+    }
+
+    public static boolean isFeatureBlacklisted(List<String> blacklist, String name, String version) {
+        Clause[] clauses = Parser.parseClauses(blacklist.toArray(new String[blacklist.size()]));
+        for (Clause clause : clauses) {
+            if (clause.getName().equals(name)) {
+                // Check feature version
+                VersionRange range = VersionRange.ANY_VERSION;
+                String vr = clause.getAttribute(BLACKLIST_RANGE);
+                if (vr != null) {
+                    range = new VersionRange(vr, true);
+                }
+                if (range.contains(VersionTable.getVersion(version))) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    public static boolean isBundleBlacklisted(List<String> blacklist, String uri) {
+        Clause[] clauses = Parser.parseClauses(blacklist.toArray(new String[blacklist.size()]));
+        for (Clause clause : clauses) {
+            String url = clause.getName();
+            if (clause.getAttribute(BLACKLIST_URL) != null) {
+                url = clause.getAttribute(BLACKLIST_URL);
+            }
+            if (uri.equals(url)) {
+                return true;
+            }
+        }
+        return false;
+    }
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/642f4a35/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
index 2f83605..96aaf90 100644
--- 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
@@ -156,6 +156,8 @@ public class FeaturesServiceImpl implements FeaturesService, Deployer.DeployCall
 
     private final int scheduleMaxRun;
 
+    private final String blacklisted;
+
     /**
      * Optional global repository
      */
@@ -185,7 +187,8 @@ public class FeaturesServiceImpl implements FeaturesService, Deployer.DeployCall
                                org.osgi.service.repository.Repository globalRepository,
                                int downloadThreads,
                                long scheduleDelay,
-                               int scheduleMaxRun) {
+                               int scheduleMaxRun,
+                               String blacklisted) {
         this.bundle = bundle;
         this.systemBundleContext = systemBundleContext;
         this.storage = storage;
@@ -203,6 +206,7 @@ public class FeaturesServiceImpl implements FeaturesService, Deployer.DeployCall
         this.downloadThreads = downloadThreads > 0 ? downloadThreads : 1;
         this.scheduleDelay = scheduleDelay;
         this.scheduleMaxRun = scheduleMaxRun;
+        this.blacklisted = blacklisted;
         loadState();
         checkResolve();
 
@@ -314,7 +318,7 @@ public class FeaturesServiceImpl implements FeaturesService, Deployer.DeployCall
                 installedFeatures.putAll(copy(state.installedFeatures));
             }
             for (String uri : repositories) {
-                Repository repository = new RepositoryImpl(URI.create(uri));
+                Repository repository = new RepositoryImpl(URI.create(uri), blacklisted);
                 listener.repositoryEvent(new RepositoryEvent(repository, RepositoryEvent.EventType.RepositoryAdded, true));
             }
             for (Map.Entry<String, Set<String>> entry : installedFeatures.entrySet()) {
@@ -370,7 +374,7 @@ public class FeaturesServiceImpl implements FeaturesService, Deployer.DeployCall
     //
 
     public Repository loadRepository(URI uri) throws Exception {
-        RepositoryImpl repo = new RepositoryImpl(uri);
+        RepositoryImpl repo = new RepositoryImpl(uri, blacklisted);
         repo.load(true);
         return repo;
     }
@@ -435,7 +439,7 @@ public class FeaturesServiceImpl implements FeaturesService, Deployer.DeployCall
             saveState();
         }
         if (repo == null) {
-            repo = new RepositoryImpl(uri);
+            repo = new RepositoryImpl(uri, blacklisted);
         }
         callListeners(new RepositoryEvent(repo, RepositoryEvent.EventType.RepositoryRemoved, false));
     }
@@ -609,7 +613,7 @@ public class FeaturesServiceImpl implements FeaturesService, Deployer.DeployCall
                 repo = repositoryCache.get(uri);
             }
             if (repo == null) {
-                RepositoryImpl rep = new RepositoryImpl(URI.create(uri));
+                RepositoryImpl rep = new RepositoryImpl(URI.create(uri), blacklisted);
                 rep.load();
                 repo = rep;
                 synchronized (lock) {

http://git-wip-us.apache.org/repos/asf/karaf/blob/642f4a35/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
index d713b6c..d6256b1 100644
--- 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
@@ -32,10 +32,16 @@ import org.apache.karaf.features.internal.model.JaxbUtil;
 public class RepositoryImpl implements Repository {
 
     private final URI uri;
+    private final String blacklisted;
     private Features features;
 
     public RepositoryImpl(URI uri) {
+        this(uri, null);
+    }
+
+    public RepositoryImpl(URI uri, String blacklisted) {
         this.uri = uri;
+        this.blacklisted = blacklisted;
     }
 
     public URI getURI() {
@@ -74,6 +80,7 @@ public class RepositoryImpl implements Repository {
                     InputStream inputStream = new InterruptibleInputStream(uri.toURL().openStream())
             ) {
                 features = JaxbUtil.unmarshal(uri.toASCIIString(), inputStream, validate);
+                Blacklist.blacklist(features, blacklisted);
             } catch (Exception e) {
                 throw (IOException) new IOException(e.getMessage() + " : " + uri).initCause(e);
             }

http://git-wip-us.apache.org/repos/asf/karaf/blob/642f4a35/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
index 918ac84..71ce70c 100644
--- a/features/core/src/test/java/org/apache/karaf/features/FeaturesServiceTest.java
+++ b/features/core/src/test/java/org/apache/karaf/features/FeaturesServiceTest.java
@@ -348,7 +348,7 @@ public class FeaturesServiceTest extends TestBase {
                 + "  <feature name='f2' version='0.2'><bundle>bundle2</bundle></feature>"
                 + "</features>");
 
-        FeaturesServiceImpl svc = new FeaturesServiceImpl(null, null, new Storage(), null, null, null, resolver, null, null, null, null, null, null, 0, 0, 0);
+        FeaturesServiceImpl svc = new FeaturesServiceImpl(null, null, new Storage(), null, null, null, resolver, null, null, null, null, null, null, 0, 0, 0, null);
         svc.addRepository(uri);
 
         assertEquals(feature("f2", "0.2"), svc.getFeatures("f2", "[0.1,0.3)")[0]);
@@ -374,7 +374,7 @@ public class FeaturesServiceTest extends TestBase {
         expect(fsl.getStartLevel()).andReturn(100);
         replay(bundleContext, bundle, fsl);
 
-        FeaturesServiceImpl svc = new FeaturesServiceImpl(null, bundleContext, new Storage(), null, null, null, resolver, null, null, null, null, null, null, 0, 0, 0);
+        FeaturesServiceImpl svc = new FeaturesServiceImpl(null, bundleContext, new Storage(), null, null, null, resolver, null, null, null, null, null, null, 0, 0, 0, null);
         svc.addRepository(uri);
         try {
             List<String> features = new ArrayList<String>();
@@ -399,7 +399,7 @@ public class FeaturesServiceTest extends TestBase {
         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, resolver, null, null, null, null, null, null, 0, 0, 0);
+        FeaturesServiceImpl svc = new FeaturesServiceImpl(null, null, new Storage(), null, null, null, resolver, null, null, null, null, null, null, 0, 0, 0, null);
         try {
             svc.addRepository(uri);
             fail("exception expected");
@@ -417,7 +417,7 @@ public class FeaturesServiceTest extends TestBase {
                 + "  <feature name='f1'><bundle>file:bundle1</bundle><bundle>file:bundle2</bundle></feature>"
                 + "</features>");
 
-        FeaturesServiceImpl svc = new FeaturesServiceImpl(null, null, new Storage(), null, null, null, resolver, null, null, null, null, null, null, 0, 0, 0);
+        FeaturesServiceImpl svc = new FeaturesServiceImpl(null, null, new Storage(), null, null, null, resolver, null, null, null, null, null, null, 0, 0, 0, null);
         svc.addRepository(uri);
         Feature[] features = svc.getFeatures("f1");
         Assert.assertEquals(1, features.length);

http://git-wip-us.apache.org/repos/asf/karaf/blob/642f4a35/features/core/src/test/java/org/apache/karaf/features/internal/service/BlacklistTest.java
----------------------------------------------------------------------
diff --git a/features/core/src/test/java/org/apache/karaf/features/internal/service/BlacklistTest.java b/features/core/src/test/java/org/apache/karaf/features/internal/service/BlacklistTest.java
new file mode 100644
index 0000000..e2d0a49
--- /dev/null
+++ b/features/core/src/test/java/org/apache/karaf/features/internal/service/BlacklistTest.java
@@ -0,0 +1,92 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.karaf.features.internal.service;
+
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.karaf.features.internal.model.Bundle;
+import org.apache.karaf.features.internal.model.Feature;
+import org.apache.karaf.features.internal.model.Features;
+import org.apache.karaf.features.internal.model.JaxbUtil;
+import org.junit.Test;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
+
+public class BlacklistTest {
+
+    @Test
+    public void testBlacklistFeatureWithRange() {
+        URL url = getClass().getResource("f02.xml");
+        Features features = JaxbUtil.unmarshal(url.toExternalForm(), true);
+
+        List<String> blacklist = new ArrayList<>();
+        blacklist.add("spring;range=\"[2,3)\"");
+
+        Blacklist.blacklist(features, blacklist);
+        for (Feature feature : features.getFeature()) {
+            assertNotEquals("spring/2.5.6.SEC02", feature.getId());
+        }
+    }
+
+    @Test
+    public void testBlacklistFeatureWithVersion() {
+        URL url = getClass().getResource("f02.xml");
+        Features features = JaxbUtil.unmarshal(url.toExternalForm(), true);
+
+        List<String> blacklist = new ArrayList<>();
+        blacklist.add("spring;range=2.5.6.SEC02");
+
+        Blacklist.blacklist(features, blacklist);
+        for (Feature feature : features.getFeature()) {
+            assertNotEquals("spring/2.5.6.SEC02", feature.getId());
+        }
+    }
+
+    @Test
+    public void testBlacklistFeatureWithoutVersion() {
+        URL url = getClass().getResource("f02.xml");
+        Features features = JaxbUtil.unmarshal(url.toExternalForm(), true);
+
+        List<String> blacklist = new ArrayList<>();
+        blacklist.add("spring");
+
+        Blacklist.blacklist(features, blacklist);
+        for (Feature feature : features.getFeature()) {
+            assertFalse(feature.getId().startsWith("spring/"));
+        }
+    }
+
+    @Test
+    public void testBlacklistBundle() {
+        URL url = getClass().getResource("f02.xml");
+        Features features = JaxbUtil.unmarshal(url.toExternalForm(), true);
+
+        List<String> blacklist = new ArrayList<>();
+        blacklist.add("mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.jasypt/1.7_1");
+
+        Blacklist.blacklist(features, blacklist);
+        for (Feature feature : features.getFeature()) {
+            for (Bundle bundle : feature.getBundle()) {
+                assertNotEquals("mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.jasypt/1.7_1",
+                                bundle.getLocation());
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/642f4a35/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
index eeb742a..264cdc0 100644
--- 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
@@ -54,7 +54,7 @@ public class FeaturesServiceImplTest extends TestBase {
     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, this.resolver, null, "", null, null, null, null, 0, 0, 0) {
+        final FeaturesServiceImpl impl = new FeaturesServiceImpl(null, null, new Storage(), null, null, null, this.resolver, null, "", null, null, null, null, 0, 0, 0, null) {
             protected Map<String,Map<String,Feature>> getFeatures() throws Exception {
                 return features;
             }
@@ -65,7 +65,7 @@ public class FeaturesServiceImplTest extends TestBase {
     
     @Test
     public void testGetFeatureStripVersion() throws Exception {
-        final FeaturesServiceImpl impl = new FeaturesServiceImpl(null, null, new Storage(), null, null, null, this.resolver, null, "", null, null, null, null, 0, 0, 0) {
+        final FeaturesServiceImpl impl = new FeaturesServiceImpl(null, null, new Storage(), null, null, null, this.resolver, null, "", null, null, null, null, 0, 0, 0, null) {
             protected Map<String,Map<String,Feature>> getFeatures() throws Exception {
                 return features(feature("transaction", "1.0.0"));
             }
@@ -79,7 +79,7 @@ public class FeaturesServiceImplTest extends TestBase {
     
     @Test
     public void testGetFeatureNotAvailable() throws Exception {
-        final FeaturesServiceImpl impl = new FeaturesServiceImpl(null, null, new Storage(), null, null, null, this.resolver, null, "", null, null, null, null, 0, 0, 0) {
+        final FeaturesServiceImpl impl = new FeaturesServiceImpl(null, null, new Storage(), null, null, null, this.resolver, null, "", null, null, null, null, 0, 0, 0, null) {
             protected Map<String,Map<String,Feature>> getFeatures() throws Exception {
                 return features(feature("transaction", "1.0.0"));
             }
@@ -93,7 +93,7 @@ public class FeaturesServiceImplTest extends TestBase {
                 feature("transaction", "1.0.0"),
                 feature("transaction", "2.0.0")
         );
-        final FeaturesServiceImpl impl = new FeaturesServiceImpl(null, null, new Storage(), null, null, null, this.resolver, null, "", null, null, null, null, 0, 0, 0) {
+        final FeaturesServiceImpl impl = new FeaturesServiceImpl(null, null, new Storage(), null, null, null, this.resolver, null, "", null, null, null, null, 0, 0, 0, null) {
             protected Map<String,Map<String,Feature>> getFeatures() throws Exception {
                 return features;
             }

http://git-wip-us.apache.org/repos/asf/karaf/blob/642f4a35/profile/src/main/java/org/apache/karaf/profile/assembly/AssemblyDeployCallback.java
----------------------------------------------------------------------
diff --git a/profile/src/main/java/org/apache/karaf/profile/assembly/AssemblyDeployCallback.java b/profile/src/main/java/org/apache/karaf/profile/assembly/AssemblyDeployCallback.java
index 22e4fcc..34a23f1 100644
--- a/profile/src/main/java/org/apache/karaf/profile/assembly/AssemblyDeployCallback.java
+++ b/profile/src/main/java/org/apache/karaf/profile/assembly/AssemblyDeployCallback.java
@@ -45,6 +45,7 @@ import org.apache.karaf.features.internal.model.Config;
 import org.apache.karaf.features.internal.model.ConfigFile;
 import org.apache.karaf.features.internal.model.Feature;
 import org.apache.karaf.features.internal.model.Features;
+import org.apache.karaf.features.internal.service.Blacklist;
 import org.apache.karaf.features.internal.service.Deployer;
 import org.apache.karaf.features.internal.service.State;
 import org.apache.karaf.features.internal.util.MapUtils;
@@ -128,6 +129,13 @@ public class AssemblyDeployCallback implements Deployer.DeployCallback {
 
     @Override
     public void installFeature(org.apache.karaf.features.Feature feature) throws IOException, InvalidSyntaxException {
+        // Check blacklist
+        if (Blacklist.isFeatureBlacklisted(builder.getBlacklistedFeatures(), feature.getName(), feature.getVersion())) {
+            if (builder.getBlacklistPolicy() == Builder.BlacklistPolicy.Fail) {
+                throw new RuntimeException("Feature " + feature.getId() + " is blacklisted");
+            }
+        }
+        // Install
         LOGGER.info("Installing feature config for " + feature.getId());
         for (Config config : ((Feature) feature).getConfig()) {
             Path configFile = etcDirectory.resolve(config.getName());
@@ -178,6 +186,13 @@ public class AssemblyDeployCallback implements Deployer.DeployCallback {
 
     @Override
     public Bundle installBundle(String region, String uri, InputStream is) throws BundleException {
+        // Check blacklist
+        if (Blacklist.isBundleBlacklisted(builder.getBlacklistedBundles(), uri)) {
+            if (builder.getBlacklistPolicy() == Builder.BlacklistPolicy.Fail) {
+                throw new RuntimeException("Bundle " + uri + " is blacklisted");
+            }
+        }
+        // Install
         LOGGER.info("Installing bundle " + uri);
         try {
             String path;

http://git-wip-us.apache.org/repos/asf/karaf/blob/642f4a35/profile/src/main/java/org/apache/karaf/profile/assembly/Builder.java
----------------------------------------------------------------------
diff --git a/profile/src/main/java/org/apache/karaf/profile/assembly/Builder.java b/profile/src/main/java/org/apache/karaf/profile/assembly/Builder.java
index fc6d4a3..319d455 100644
--- a/profile/src/main/java/org/apache/karaf/profile/assembly/Builder.java
+++ b/profile/src/main/java/org/apache/karaf/profile/assembly/Builder.java
@@ -23,13 +23,16 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.net.MalformedURLException;
 import java.net.URI;
+import java.nio.charset.StandardCharsets;
 import java.nio.file.FileSystem;
 import java.nio.file.FileSystemNotFoundException;
 import java.nio.file.FileSystems;
 import java.nio.file.Files;
+import java.nio.file.OpenOption;
 import java.nio.file.Path;
 import java.nio.file.Paths;
 import java.nio.file.StandardCopyOption;
+import java.nio.file.StandardOpenOption;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
@@ -73,6 +76,7 @@ import org.apache.karaf.features.internal.model.Features;
 import org.apache.karaf.features.internal.model.JaxbUtil;
 import org.apache.karaf.features.internal.repository.BaseRepository;
 import org.apache.karaf.features.internal.resolver.ResourceBuilder;
+import org.apache.karaf.features.internal.service.Blacklist;
 import org.apache.karaf.features.internal.service.Deployer;
 import org.apache.karaf.features.internal.util.MapUtils;
 import org.apache.karaf.kar.internal.Kar;
@@ -114,6 +118,12 @@ public class Builder {
         v24, v3x, v4x
     }
 
+
+    public static enum BlacklistPolicy {
+        Discard,
+        Fail
+    }
+
     static class RepositoryInfo {
         Stage stage;
         boolean addAll;
@@ -131,6 +141,10 @@ public class Builder {
     Map<String, RepositoryInfo> repositories = new LinkedHashMap<>();
     Map<String, Stage> features = new LinkedHashMap<>();
     Map<String, Stage> bundles = new LinkedHashMap<>();
+    List<String> blacklistedProfiles = new ArrayList<>();
+    List<String> blacklistedFeatures = new ArrayList<>();
+    List<String> blacklistedBundles = new ArrayList<>();
+    BlacklistPolicy blacklistPolicy = BlacklistPolicy.Discard;
     List<String> libraries = new ArrayList<>();
     String javase = "1.7";
     KarafVersion karafVersion = KarafVersion.v4x;
@@ -299,6 +313,42 @@ public class Builder {
         return this.defaultStage(Startup).useReferenceUrls().kars(Startup, true, staticFeaturesKar);
     }
 
+    public Builder blacklistProfiles(Collection<String> profiles) {
+        this.blacklistedProfiles.addAll(profiles);
+        return this;
+    }
+
+    public Builder blacklistFeatures(Collection<String> features) {
+        this.blacklistedFeatures.addAll(features);
+        return this;
+    }
+
+    public Builder blacklistBundles(Collection<String> bundles) {
+        this.blacklistedBundles.addAll(bundles);
+        return this;
+    }
+
+    public Builder blacklistPolicy(BlacklistPolicy policy) {
+        this.blacklistPolicy = policy;
+        return this;
+    }
+
+    public List<String> getBlacklistedProfiles() {
+        return blacklistedProfiles;
+    }
+
+    public List<String> getBlacklistedFeatures() {
+        return blacklistedFeatures;
+    }
+
+    public List<String> getBlacklistedBundles() {
+        return blacklistedBundles;
+    }
+
+    public BlacklistPolicy getBlacklistPolicy() {
+        return blacklistPolicy;
+    }
+
     public void generateAssembly() throws Exception {
         if (javase == null) {
             throw new IllegalArgumentException("javase is not set");
@@ -390,6 +440,18 @@ public class Builder {
                 profilePath = fs.provider().getPath(profileURI);
             }
             allProfiles.putAll(Profiles.loadProfiles(profilePath));
+            // Handle blacklisted profiles
+            if (!blacklistedProfiles.isEmpty()) {
+                if (blacklistPolicy == BlacklistPolicy.Discard) {
+                    // Override blacklisted profiles with empty ones
+                    for (String profile : blacklistedProfiles) {
+                        allProfiles.put(profile, ProfileBuilder.Factory.create(profile).getProfile());
+                    }
+                } else {
+                    // Remove profiles completely
+                    allProfiles.keySet().removeAll(blacklistedProfiles);
+                }
+            }
         }
 
         // Generate profiles
@@ -455,6 +517,41 @@ public class Builder {
         }
 
         //
+        // Handle overrides
+        //
+        if (!overallEffective.getOverrides().isEmpty()) {
+            Path overrides = etcDirectory.resolve("override.properties");
+            List<String> lines = new ArrayList<>();
+            lines.add("#");
+            lines.add("# Generated by the karaf assembly builder");
+            lines.add("#");
+            lines.addAll(overallEffective.getOverrides());
+            Files.write(overrides, lines, StandardCharsets.UTF_8, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING);
+        }
+
+        //
+        // Handle blacklist
+        //
+        if (!blacklistedFeatures.isEmpty() || !blacklistedBundles.isEmpty()) {
+            Path blacklist = etcDirectory.resolve("blacklisted.properties");
+            List<String> lines = new ArrayList<>();
+            lines.add("#");
+            lines.add("# Generated by the karaf assembly builder");
+            lines.add("#");
+            if (!blacklistedFeatures.isEmpty()) {
+                lines.add("");
+                lines.add("# Features");
+                lines.addAll(blacklistedFeatures);
+            }
+            if (!blacklistedBundles.isEmpty()) {
+                lines.add("");
+                lines.add("# Bundles");
+                lines.addAll(blacklistedBundles);
+            }
+            Files.write(blacklist, lines, StandardCharsets.UTF_8, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING);
+        }
+
+        //
         // Startup stage
         //
         Profile startupEffective = startupStage(startupProfile);
@@ -704,7 +801,6 @@ public class Builder {
             }
             Path configPropertiesPath = etcDirectory.resolve("config.properties");
             Properties configProperties = new Properties(configPropertiesPath.toFile());
-            downloader = manager.createDownloader();
             downloadLibraries(downloader, configProperties, libraries);
             downloader.await();
             // Reformat clauses
@@ -847,7 +943,6 @@ public class Builder {
     private void installArtifact(Downloader downloader, String location) throws Exception {
         LOGGER.info("== Installing artifact " + location);
         location = DownloadManagerHelper.stripUrl(location);
-//        location = DownloadManagerHelper.removeInlinedMavenRepositoryUrl(location);
         if (location.startsWith("mvn:")) {
             if (location.endsWith("/")) {
                 // for bad formed URL (like in Camel for mustache-compiler), we remove the trailing /
@@ -856,26 +951,17 @@ public class Builder {
             downloader.download(location, new DownloadCallback() {
                 @Override
                 public void downloaded(final StreamProvider provider) throws Exception {
-                    Path path = systemDirectory.resolve(Parser.pathFromMaven(provider.getUrl()));
+                    String uri = provider.getUrl();
+                    if (Blacklist.isBundleBlacklisted(blacklistedBundles, uri)) {
+                        throw new RuntimeException("Bundle " + uri + " is blacklisted");
+                    }
+                    Path path = systemDirectory.resolve(Parser.pathFromMaven(uri));
                     synchronized (provider) {
                         Files.createDirectories(path.getParent());
                         Files.copy(provider.getFile().toPath(), path, StandardCopyOption.REPLACE_EXISTING);
                     }
                 }
             });
-            // add metadata for snapshot
-            /*
-            Artifact artifact = dependencyHelper.mvnToArtifact(location);
-            if (artifact.isSnapshot()) {
-                File metadataTarget = new File(targetFile.getParentFile(), "maven-metadata-local.xml");
-                try {
-                    MavenUtil.generateMavenMetadata(artifact, metadataTarget);
-                } catch (Exception e) {
-                    getLog().warn("Could not create maven-metadata-local.xml", e);
-                    getLog().warn("It means that this SNAPSHOT could be overwritten by an older one present on remote repositories");
-                }
-            }
-            */
         } else {
             LOGGER.warn("Ignoring artifact " + location);
         }
@@ -933,6 +1019,10 @@ public class Builder {
     private Map<String, Features> loadRepositories(DownloadManager manager, Collection<String> repositories, final boolean install) throws Exception {
         final Map<String, Features> loaded = new HashMap<>();
         final Downloader downloader = manager.createDownloader();
+        final List<String> blacklist = new ArrayList<>();
+        blacklist.addAll(blacklistedBundles);
+        blacklist.addAll(blacklistedFeatures);
+        final Clause[] clauses = org.apache.felix.utils.manifest.Parser.parseClauses(blacklist.toArray(new String[blacklist.size()]));
         for (String repository : repositories) {
             downloader.download(repository, new DownloadCallback() {
                 @Override
@@ -946,6 +1036,9 @@ public class Builder {
                     }
                     try (InputStream is = provider.open()) {
                         Features featuresModel = JaxbUtil.unmarshal(provider.getUrl(), is, false);
+                        if (blacklistPolicy == BlacklistPolicy.Discard) {
+                            Blacklist.blacklist(featuresModel, clauses);
+                        }
                         synchronized (loaded) {
                             loaded.put(provider.getUrl(), featuresModel);
                             for (String innerRepository : featuresModel.getRepository()) {

http://git-wip-us.apache.org/repos/asf/karaf/blob/642f4a35/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/features/InstallKarsMojo.java
----------------------------------------------------------------------
diff --git a/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/features/InstallKarsMojo.java b/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/features/InstallKarsMojo.java
index cce45b4..47ae0a9 100644
--- a/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/features/InstallKarsMojo.java
+++ b/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/features/InstallKarsMojo.java
@@ -97,11 +97,16 @@ public class InstallKarsMojo extends MojoSupport {
     private List<String> installedFeatures;
 
     @Parameter
+    private List<String> blacklistedFeatures;
+
+    @Parameter
     private List<String> startupBundles;
     @Parameter
     private List<String> bootBundles;
     @Parameter
     private List<String> installedBundles;
+    @Parameter
+    private List<String> blacklistedBundles;
     
     @Parameter
     private String profilesUri;
@@ -115,6 +120,12 @@ public class InstallKarsMojo extends MojoSupport {
     @Parameter
     private List<String> installedProfiles;
 
+    @Parameter
+    private List<String> blacklistedProfiles;
+
+    @Parameter
+    private Builder.BlacklistPolicy blacklistPolicy;
+
     /**
      * Ignore the dependency attribute (dependency="[true|false]") on bundle
      */
@@ -166,12 +177,15 @@ public class InstallKarsMojo extends MojoSupport {
         startupBundles = nonNullList(startupBundles);
         bootBundles = nonNullList(bootBundles);
         installedBundles = nonNullList(installedBundles);
+        blacklistedBundles = nonNullList(blacklistedBundles);
         startupFeatures = nonNullList(startupFeatures);
         bootFeatures = nonNullList(bootFeatures);
         installedFeatures = nonNullList(installedFeatures);
+        blacklistedFeatures = nonNullList(blacklistedFeatures);
         startupProfiles = nonNullList(startupProfiles);
         bootProfiles = nonNullList(bootProfiles);
         installedProfiles = nonNullList(installedProfiles);
+        blacklistedProfiles = nonNullList(blacklistedProfiles);
 
         if (!startupProfiles.isEmpty() || !bootProfiles.isEmpty() || !installedProfiles.isEmpty()) {
             if (profilesUri == null) {
@@ -188,6 +202,12 @@ public class InstallKarsMojo extends MojoSupport {
 
         Builder builder = Builder.newInstance();
 
+        // Set up blacklisted items
+        builder.blacklistBundles(blacklistedBundles);
+        builder.blacklistFeatures(blacklistedFeatures);
+        builder.blacklistProfiles(blacklistedProfiles);
+        builder.blacklistPolicy(blacklistPolicy);
+
         // creating system directory
         getLog().info("Creating work directory");
         builder.homeDirectory(workDirectory.toPath());