You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@karaf.apache.org by cs...@apache.org on 2017/08/14 16:46:20 UTC

karaf git commit: Change Blacklist into an ordinary class

Repository: karaf
Updated Branches:
  refs/heads/master e442a1b8a -> eb95bce7d


Change Blacklist into an ordinary class


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

Branch: refs/heads/master
Commit: eb95bce7d5a1bcf23a5bda919209394ffcf3c01a
Parents: e442a1b
Author: Christian Schneider <ch...@die-schneider.net>
Authored: Mon Aug 14 18:46:07 2017 +0200
Committer: Christian Schneider <ch...@die-schneider.net>
Committed: Mon Aug 14 18:46:07 2017 +0200

----------------------------------------------------------------------
 .../features/internal/service/Blacklist.java    |  90 +++++++---------
 .../internal/service/FeaturesServiceImpl.java   |  28 +----
 .../internal/service/RepositoryCache.java       |  19 +---
 .../internal/service/RepositoryImpl.java        |  23 ++--
 .../internal/service/BlacklistTest.java         |  67 ++++--------
 .../profile/assembly/ArtifactInstaller.java     |  84 +++++++++++++++
 .../assembly/AssemblyDeployCallback.java        |  11 +-
 .../apache/karaf/profile/assembly/Builder.java  | 104 +++----------------
 8 files changed, 185 insertions(+), 241 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/karaf/blob/eb95bce7/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
index 0d804a7..f7f4aab 100644
--- 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
@@ -16,12 +16,18 @@
  */
 package org.apache.karaf.features.internal.service;
 
+import static java.util.stream.Collectors.toSet;
+
 import java.io.BufferedReader;
 import java.io.FileNotFoundException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.net.URL;
-import java.util.*;
+import java.util.Collections;
+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;
@@ -47,25 +53,38 @@ public class Blacklist {
     public static final String TYPE_REPOSITORY = "repository";
 
     private static final Logger LOGGER = LoggerFactory.getLogger(Blacklist.class);
-
-    private Blacklist() {
+    private Clause[] clauses;
+    
+    public Blacklist() {
+        this(Collections.emptyList());
     }
 
-    public static void blacklist(Features features, String blacklisted) {
-        Set<String> blacklist = loadBlacklist(blacklisted);
-        blacklist(features, blacklist);
+    public Blacklist(List<String> blacklist) {
+        this.clauses = org.apache.felix.utils.manifest.Parser.parseClauses(blacklist.toArray(new String[blacklist.size()]));
     }
-
-    public static void blacklist(Features features, Collection<String> blacklist) {
-        Clause[] clauses = Parser.parseClauses(blacklist.toArray(new String[blacklist.size()]));
-        blacklist(features, clauses);
+    
+    public Blacklist(String blacklistUrl) {
+        Set<String> blacklist = new HashSet<>();
+        if (blacklistUrl != null) {
+            try (InputStream is = new URL(blacklistUrl).openStream();
+                BufferedReader reader = new BufferedReader(new InputStreamReader(is))) {
+                reader.lines() //
+                    .map(line -> line.trim()) //
+                    .filter(line -> line.isEmpty() || line.startsWith("#")).collect(toSet());
+            } catch (FileNotFoundException e) {
+                LOGGER.debug("Unable to load blacklist bundles list", e.toString());
+            } catch (Exception e) {
+                LOGGER.debug("Unable to load blacklist bundles list", e);
+            }
+        }
+        this.clauses = Parser.parseClauses(blacklist.toArray(new String[blacklist.size()]));
     }
 
-    public static void blacklist(Features features, Clause[] clauses) {
-        features.getFeature().removeIf(feature -> blacklist(feature, clauses));
+    public void blacklist(Features features) {
+        features.getFeature().removeIf(feature -> blacklist(feature));
     }
 
-    public static boolean blacklist(Feature feature, Clause[] clauses) {
+    public boolean blacklist(Feature feature) {
         for (Clause clause : clauses) {
             // Check feature name
             if (clause.getName().equals(feature.getName())) {
@@ -83,16 +102,16 @@ public class Blacklist {
                 }
             }
             // Check bundles
-            blacklist(feature.getBundle(), clauses);
+            blacklist(feature.getBundle());
             // Check conditional bundles
             for (Conditional cond : feature.getConditional()) {
-                blacklist(cond.getBundle(), clauses);
+                blacklist(cond.getBundle());
             }
         }
         return false;
     }
 
-    private static void blacklist(List<Bundle> bundles, Clause[] clauses) {
+    private void blacklist(List<Bundle> bundles) {
         for (Iterator<Bundle> iterator = bundles.iterator(); iterator.hasNext();) {
             Bundle info = iterator.next();
             for (Clause clause : clauses) {
@@ -111,33 +130,7 @@ public class Blacklist {
         }
     }
 
-    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 (FileNotFoundException e) {
-            LOGGER.debug("Unable to load blacklist bundles list", e.toString());
-        } catch (Exception e) {
-            LOGGER.debug("Unable to load blacklist 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()]));
+    public boolean isFeatureBlacklisted(String name, String version) {
         for (Clause clause : clauses) {
             if (clause.getName().equals(name)) {
                 // Check feature version
@@ -157,16 +150,11 @@ public class Blacklist {
         return false;
     }
 
-    public static boolean isBundleBlacklisted(List<String> blacklist, String uri) {
-        return isBlacklisted(blacklist, uri, TYPE_BUNDLE);
-    }
-
-    public static boolean isBlacklisted(List<String> blacklist, String uri, String btype) {
-        Clause[] clauses = Parser.parseClauses(blacklist.toArray(new String[blacklist.size()]));
-        return isBlacklisted(clauses, uri, btype);
+    public boolean isBundleBlacklisted(String uri) {
+        return isBlacklisted(uri, TYPE_BUNDLE);
     }
 
-    public static boolean isBlacklisted(Clause[] clauses, String uri, String btype) {
+    public boolean isBlacklisted(String uri, String btype) {
         for (Clause clause : clauses) {
             String url = clause.getName();
             if (clause.getAttribute(BLACKLIST_URL) != null) {

http://git-wip-us.apache.org/repos/asf/karaf/blob/eb95bce7/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 6a000cd..90f4969 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
@@ -49,7 +49,6 @@ import java.util.regex.Pattern;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
 
-import org.apache.felix.utils.manifest.Clause;
 import org.apache.felix.utils.version.VersionCleaner;
 import org.apache.felix.utils.version.VersionRange;
 import org.apache.felix.utils.version.VersionTable;
@@ -145,7 +144,8 @@ public class FeaturesServiceImpl implements FeaturesService, Deployer.DeployCall
         this.resolver = resolver;
         this.installSupport = installSupport;
         this.globalRepository = globalRepository;
-        this.repositories = new RepositoryCache(cfg.blacklisted);
+        Blacklist blacklist = new Blacklist(cfg.blacklisted);
+        this.repositories = new RepositoryCache(blacklist);
         this.cfg = cfg;
         this.executor = Executors.newSingleThreadExecutor(ThreadUtils.namedThreadFactory("features"));
         loadState();
@@ -260,8 +260,9 @@ public class FeaturesServiceImpl implements FeaturesService, Deployer.DeployCall
                 repositories.addAll(state.repositories);
                 installedFeatures.putAll(copy(state.installedFeatures));
             }
+            Blacklist blacklist = new Blacklist(cfg.blacklisted);
             for (String uri : repositories) {
-                Repository repository = new RepositoryImpl(URI.create(uri), cfg.blacklisted);
+                Repository repository = new RepositoryImpl(URI.create(uri), blacklist);
                 listener.repositoryEvent(new RepositoryEvent(repository, RepositoryEvent.EventType.RepositoryAdded, true));
             }
             for (Map.Entry<String, Set<String>> entry : installedFeatures.entrySet()) {
@@ -981,27 +982,6 @@ public class FeaturesServiceImpl implements FeaturesService, Deployer.DeployCall
         return repositories.create(uri, true, true);
     }
 
-    private Map<String, Feature> loadAllFeatures(Set<URI> uris) throws Exception {
-        //the outer map's key is feature name, the inner map's key is feature version
-        Map<String, Feature> map = new HashMap<>();
-        // Two phase load:
-        // * first load dependent repositories
-        Set<URI> loaded = new HashSet<>();
-        List<URI> toLoad = new ArrayList<>(uris);
-        Clause[] blacklisted = repositories.getBlacklisted();
-        while (!toLoad.isEmpty()) {
-            URI uri = toLoad.remove(0);
-            if (loaded.add(uri)) {
-                Repository repo = new RepositoryImpl(uri, blacklisted);
-                Collections.addAll(toLoad, repo.getRepositories());
-                for (Feature f : repo.getFeatures()) {
-                    map.put(f.getId(), f);
-                }
-            }
-        }
-        return map;
-    }
-
     @Override
     public Map<String, Set<String>> listRequirements() {
         synchronized (lock) {

http://git-wip-us.apache.org/repos/asf/karaf/blob/eb95bce7/features/core/src/main/java/org/apache/karaf/features/internal/service/RepositoryCache.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/service/RepositoryCache.java b/features/core/src/main/java/org/apache/karaf/features/internal/service/RepositoryCache.java
index f92b0bc..4898566 100644
--- a/features/core/src/main/java/org/apache/karaf/features/internal/service/RepositoryCache.java
+++ b/features/core/src/main/java/org/apache/karaf/features/internal/service/RepositoryCache.java
@@ -27,30 +27,19 @@ 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.Repository;
 
 public class RepositoryCache {
 
     private final Map<String, Repository> repositoryCache = new HashMap<>();
-    private final Clause[] blacklisted;
+    private final Blacklist blacklist;
     
-    public RepositoryCache(String blacklisted) {
-        this.blacklisted = loadBlacklist(blacklisted);
+    public RepositoryCache(Blacklist blacklist) {
+        this.blacklist = blacklist;
     }
 
-    public Clause[] getBlacklisted() {
-        return blacklisted;
-    }
-
-    private static Clause[] loadBlacklist(String blacklisted) {
-        Set<String> blacklistStrings = Blacklist.loadBlacklist(blacklisted);
-        return Parser.parseClauses(blacklistStrings.toArray(new String[blacklistStrings.size()]));
-    }
-    
     public Repository create(URI uri, boolean load, boolean validate) throws Exception {
-        RepositoryImpl repo = new RepositoryImpl(uri, blacklisted);
+        RepositoryImpl repo = new RepositoryImpl(uri, blacklist);
         if (load)
             repo.load(validate);
         return repo;

http://git-wip-us.apache.org/repos/asf/karaf/blob/eb95bce7/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 a839a50..0bdc174 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
@@ -22,10 +22,7 @@ import java.io.InputStream;
 import java.io.InterruptedIOException;
 import java.net.URI;
 import java.util.Objects;
-import java.util.Set;
 
-import org.apache.felix.utils.manifest.Clause;
-import org.apache.felix.utils.manifest.Parser;
 import org.apache.karaf.features.Feature;
 import org.apache.karaf.features.Repository;
 import org.apache.karaf.features.internal.model.Features;
@@ -37,22 +34,16 @@ import org.apache.karaf.features.internal.model.JaxbUtil;
 public class RepositoryImpl implements Repository {
 
     private final URI uri;
-    private final Clause[] blacklisted;
+    private final Blacklist blacklist;
     private Features features;
-
+    
     public RepositoryImpl(URI uri) {
-        this(uri, (Clause[]) null);
-    }
-
-    public RepositoryImpl(URI uri, String blacklisted) {
-        this.uri = uri;
-        Set<String> blacklistStrings = Blacklist.loadBlacklist(blacklisted);
-        this.blacklisted = Parser.parseClauses(blacklistStrings.toArray(new String[blacklistStrings.size()]));
+        this(uri, null);
     }
 
-    public RepositoryImpl(URI uri, Clause[] blacklisted) {
+    public RepositoryImpl(URI uri, Blacklist blacklist) {
         this.uri = uri;
-        this.blacklisted = blacklisted != null ? blacklisted : new Clause[0];
+        this.blacklist = blacklist;
     }
 
     public URI getURI() {
@@ -97,7 +88,9 @@ public class RepositoryImpl implements Repository {
                     InputStream inputStream = new InterruptibleInputStream(uri.toURL().openStream())
             ) {
                 features = JaxbUtil.unmarshal(uri.toASCIIString(), inputStream, validate);
-                Blacklist.blacklist(features, blacklisted);
+                if (blacklist != null) {
+                    blacklist.blacklist(features);
+                }
             } catch (Exception e) {
                 throw new IOException(e.getMessage() + " : " + uri, e);
             }

http://git-wip-us.apache.org/repos/asf/karaf/blob/eb95bce7/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
index e2d0a49..9d09e56 100644
--- 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
@@ -16,77 +16,52 @@
  */
 package org.apache.karaf.features.internal.service;
 
+import static org.junit.Assert.assertTrue;
+
 import java.net.URL;
-import java.util.ArrayList;
-import java.util.List;
+import java.util.Collections;
+import java.util.stream.Stream;
 
-import org.apache.karaf.features.internal.model.Bundle;
+import org.apache.karaf.features.BundleInfo;
 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());
-        }
+        Stream<Feature> features = blacklistWith("spring;range=\"[2,3)\"");
+        assertTrue(features.noneMatch(f -> f.getId().equals("spring/2.5.6.SEC02")));
     }
 
     @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());
-        }
+        Stream<Feature> features = blacklistWith("spring;range=2.5.6.SEC02");
+        assertTrue(features.noneMatch(f -> f.getId().equals("spring/2.5.6.SEC02")));
     }
 
     @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/"));
-        }
+        Stream<Feature> features = blacklistWith("spring");
+        assertTrue(features.noneMatch(f -> f.getId().startsWith("spring/")));
     }
 
     @Test
     public void testBlacklistBundle() {
+        String blacklisted = "mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.jasypt/1.7_1";
+        Stream<Feature> features = blacklistWith(blacklisted);
+        Stream<BundleInfo> bundles = features.flatMap(f -> f.getBundles().stream());
+        assertTrue(bundles.noneMatch(b -> b.getLocation().equals(blacklisted)));
+    }
+
+    private Stream<Feature> blacklistWith(String blacklistClause) {
         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());
-            }
-        }
+        Blacklist blacklist = new Blacklist(Collections.singletonList(blacklistClause));
+        blacklist.blacklist(features);
+        return features.getFeature().stream();
     }
 }

http://git-wip-us.apache.org/repos/asf/karaf/blob/eb95bce7/profile/src/main/java/org/apache/karaf/profile/assembly/ArtifactInstaller.java
----------------------------------------------------------------------
diff --git a/profile/src/main/java/org/apache/karaf/profile/assembly/ArtifactInstaller.java b/profile/src/main/java/org/apache/karaf/profile/assembly/ArtifactInstaller.java
new file mode 100644
index 0000000..2dcf2be
--- /dev/null
+++ b/profile/src/main/java/org/apache/karaf/profile/assembly/ArtifactInstaller.java
@@ -0,0 +1,84 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.karaf.profile.assembly;
+
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.StandardCopyOption;
+import java.util.List;
+
+import org.apache.karaf.features.internal.download.Downloader;
+import org.apache.karaf.features.internal.download.impl.DownloadManagerHelper;
+import org.apache.karaf.features.internal.service.Blacklist;
+import org.apache.karaf.util.maven.Parser;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class ArtifactInstaller {
+    private static final Logger LOGGER = LoggerFactory.getLogger(ArtifactInstaller.class);
+
+    private Path systemDirectory;
+    private Downloader downloader;
+    private Blacklist blacklist;
+
+    public ArtifactInstaller(Path systemDirectory, Downloader downloader, List<String> blacklisted) {
+        this.systemDirectory = systemDirectory;
+        this.downloader = downloader;
+        this.blacklist = new Blacklist(blacklisted);
+    }
+    
+    public void installArtifact(String location) throws Exception {
+        LOGGER.info("      adding maven artifact: " + location);
+        location = DownloadManagerHelper.stripUrl(location);
+        if (location.startsWith("mvn:")) {
+            if (location.endsWith("/")) {
+                // for bad formed URL (like in Camel for mustache-compiler), we remove the trailing /
+                location = location.substring(0, location.length() - 1);
+            }
+            downloader.download(location, provider -> {
+                String uri = provider.getUrl();
+                if (blacklist.isBundleBlacklisted(uri)) {
+                    throw new RuntimeException("Bundle " + uri + " is blacklisted");
+                }
+                Path path = pathFromProviderUrl(systemDirectory, uri);
+                synchronized (provider) {
+                    Files.createDirectories(path.getParent());
+                    Files.copy(provider.getFile().toPath(), path, StandardCopyOption.REPLACE_EXISTING);
+                }
+            });
+        } else {
+            LOGGER.warn("Ignoring non maven artifact " + location);
+        }
+    }
+    
+    public static Path pathFromProviderUrl(Path systemDirectory, String url) throws MalformedURLException {
+        String pathString;
+        if (url.startsWith("file:")) {
+            return Paths.get(URI.create(url));
+        }
+        else if (url.startsWith("mvn:")) {
+            pathString = Parser.pathFromMaven(url);
+        }
+        else {
+            pathString = url;
+        }
+        return systemDirectory.resolve(pathString);
+    }
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/eb95bce7/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 b87410f..2be1d6f 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
@@ -36,13 +36,13 @@ import org.apache.felix.utils.properties.Properties;
 import org.apache.karaf.features.DeploymentEvent;
 import org.apache.karaf.features.FeatureEvent;
 import org.apache.karaf.features.FeaturesService;
-import org.apache.karaf.features.internal.model.Library;
 import org.apache.karaf.features.internal.download.DownloadManager;
 import org.apache.karaf.features.internal.download.Downloader;
 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.model.Library;
 import org.apache.karaf.features.internal.service.Blacklist;
 import org.apache.karaf.features.internal.service.Deployer;
 import org.apache.karaf.features.internal.service.State;
@@ -63,6 +63,8 @@ public class AssemblyDeployCallback extends StaticInstallSupport implements Depl
 
     private final DownloadManager manager;
     private final Builder builder;
+    private Blacklist featureBlacklist;
+    private Blacklist bundleBlacklist;
     private final Path homeDirectory;
     private final int defaultStartLevel;
     private final Path etcDirectory;
@@ -72,9 +74,12 @@ public class AssemblyDeployCallback extends StaticInstallSupport implements Depl
 
     private final Map<String, Bundle> bundles = new HashMap<>();
 
+
     public AssemblyDeployCallback(DownloadManager manager, Builder builder, BundleRevision systemBundle, Collection<Features> repositories) throws Exception {
         this.manager = manager;
         this.builder = builder;
+        this.featureBlacklist = new Blacklist(builder.getBlacklistedFeatures());
+        this.bundleBlacklist = new Blacklist(builder.getBlacklistedBundles());
         this.homeDirectory = builder.homeDirectory;
         this.etcDirectory = homeDirectory.resolve("etc");
         this.systemDirectory = homeDirectory.resolve("system");
@@ -190,7 +195,7 @@ public class AssemblyDeployCallback extends StaticInstallSupport implements Depl
     }
     
     private void assertNotBlacklisted(org.apache.karaf.features.Feature feature) {
-        if (Blacklist.isFeatureBlacklisted(builder.getBlacklistedFeatures(), feature.getName(), feature.getVersion())) {
+        if (featureBlacklist.isFeatureBlacklisted(feature.getName(), feature.getVersion())) {
             if (builder.getBlacklistPolicy() == Builder.BlacklistPolicy.Fail) {
                 throw new RuntimeException("Feature " + feature.getId() + " is blacklisted");
             }
@@ -208,7 +213,7 @@ public class AssemblyDeployCallback extends StaticInstallSupport implements Depl
     @Override
     public Bundle installBundle(String region, String uri, InputStream is) throws BundleException {
         // Check blacklist
-        if (Blacklist.isBundleBlacklisted(builder.getBlacklistedBundles(), uri)) {
+        if (bundleBlacklist.isBundleBlacklisted(uri)) {
             if (builder.getBlacklistPolicy() == Builder.BlacklistPolicy.Fail) {
                 throw new RuntimeException("Bundle " + uri + " is blacklisted");
             }

http://git-wip-us.apache.org/repos/asf/karaf/blob/eb95bce7/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 e20080c..27b83a6 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
@@ -64,7 +64,6 @@ import org.apache.karaf.features.internal.download.DownloadCallback;
 import org.apache.karaf.features.internal.download.DownloadManager;
 import org.apache.karaf.features.internal.download.Downloader;
 import org.apache.karaf.features.internal.download.StreamProvider;
-import org.apache.karaf.features.internal.download.impl.DownloadManagerHelper;
 import org.apache.karaf.features.internal.model.Bundle;
 import org.apache.karaf.features.internal.model.Conditional;
 import org.apache.karaf.features.internal.model.Config;
@@ -85,7 +84,6 @@ import org.apache.karaf.profile.ProfileBuilder;
 import org.apache.karaf.profile.impl.Profiles;
 import org.apache.karaf.tools.utils.KarafPropertiesEditor;
 import org.apache.karaf.tools.utils.model.KarafPropertyEdits;
-import org.apache.karaf.profile.versioning.VersionUtils;
 import org.apache.karaf.util.config.PropertiesLoader;
 import org.apache.karaf.util.maven.Parser;
 import org.ops4j.pax.url.mvn.MavenResolver;
@@ -812,27 +810,28 @@ public class Builder {
         for (String feature : installedEffective.getFeatures()) {
             addFeatures(allInstalledFeatures, feature, installedFeatures, true);
         }
+        ArtifactInstaller installer = new ArtifactInstaller(systemDirectory, downloader, blacklistedBundles);
         for (Feature feature : installedFeatures) {
             LOGGER.info("   Feature {} is defined as an installed feature", feature.getId());
             for (Bundle bundle : feature.getBundle()) {
                 if (!ignoreDependencyFlag || !bundle.isDependency()) {
-                    installArtifact(downloader, bundle.getLocation().trim());
+                    installer.installArtifact(bundle.getLocation().trim());
                 }
             }
             // Install config files
             for (ConfigFile configFile : feature.getConfigfile()) {
-                installArtifact(downloader, configFile.getLocation().trim());
+                installer.installArtifact(configFile.getLocation().trim());
             }
             for (Conditional cond : feature.getConditional()) {
                 for (Bundle bundle : cond.getBundle()) {
                     if (!ignoreDependencyFlag || !bundle.isDependency()) {
-                        installArtifact(downloader, bundle.getLocation().trim());
+                        installer.installArtifact(bundle.getLocation().trim());
                     }
                 }
             }
         }
         for (String location : installedEffective.getBundles()) {
-            installArtifact(downloader, location);
+            installer.installArtifact(location);
         }
         downloader.await();
     }
@@ -908,8 +907,9 @@ public class Builder {
             prereqs.put("spring:", Arrays.asList("deployer", "spring"));
             prereqs.put("wrap:", Arrays.asList("wrap"));
             prereqs.put("war:", Arrays.asList("war"));
+            ArtifactInstaller installer = new ArtifactInstaller(systemDirectory, downloader, blacklistedBundles);
             for (String location : locations) {
-                installArtifact(downloader, location);
+                installer.installArtifact(location);
                 for (Map.Entry<String, List<String>> entry : prereqs.entrySet()) {
                     if (location.startsWith(entry.getKey())) {
                         for (String prereq : entry.getValue()) {
@@ -932,11 +932,11 @@ public class Builder {
                 // Install config files
                 for (Config config : content.getConfig()) {
                     if (config.isExternal()) {
-                        installArtifact(downloader, config.getValue().trim());
+                        installer.installArtifact(config.getValue().trim());
                     }
                 }
                 for (ConfigFile configFile : content.getConfigfile()) {
-                    installArtifact(downloader, configFile.getLocation().trim());
+                    installer.installArtifact(configFile.getLocation().trim());
                 }
                 // Extract configs
                 for (Config config : content.getConfig()) {
@@ -1239,30 +1239,6 @@ public class Builder {
         return startupEffective;
     }
 
-    private void installArtifact(Downloader downloader, String location) throws Exception {
-        LOGGER.info("      adding maven artifact: " + location);
-        location = DownloadManagerHelper.stripUrl(location);
-        if (location.startsWith("mvn:")) {
-            if (location.endsWith("/")) {
-                // for bad formed URL (like in Camel for mustache-compiler), we remove the trailing /
-                location = location.substring(0, location.length() - 1);
-            }
-            downloader.download(location, provider -> {
-                String uri = provider.getUrl();
-                if (Blacklist.isBundleBlacklisted(blacklistedBundles, uri)) {
-                    throw new RuntimeException("Bundle " + uri + " is blacklisted");
-                }
-                Path path = pathFromProviderUrl(uri);
-                synchronized (provider) {
-                    Files.createDirectories(path.getParent());
-                    Files.copy(provider.getFile().toPath(), path, StandardCopyOption.REPLACE_EXISTING);
-                }
-            });
-        } else {
-            LOGGER.warn("Ignoring non maven artifact " + location);
-        }
-    }
-
     private void addFeatures(Set<Feature> allFeatures, String feature, Set<Feature> features, boolean mandatory) {
         String name;
         VersionRange range;
@@ -1294,42 +1270,6 @@ public class Builder {
         }
     }
 
-    private String getFeatureSt(Dependency dep) {
-        String version = dep.getVersion() == null || "0.0.0".equals(dep.getVersion()) ? "" : "/" + dep.getVersion();
-        return dep.getName() + version;
-    }
-
-    /**
-     * Checks if a given feature f matches the featureRef.
-     * TODO Need to also check for version ranges. Currently ranges are ignored and all features matching the name
-     * are copied in that case.
-     *  
-     * @param f
-     * @param featureRef
-     * @return
-     */
-    private boolean matches(Feature f, Dependency featureRef) {
-        if (!f.getName().equals(featureRef.getName())) {
-            return false;
-        }
-
-        final String featureRefVersion = featureRef.getVersion();
-
-        if (featureRefVersion == null) {
-            return true;
-        }
-
-        if (featureRefVersion.equals("0.0.0")) {
-            return true;
-        }
-
-        if (featureRefVersion.startsWith("[")) {
-            return true;
-        }
-
-        return VersionUtils.versionEquals(f.getVersion(), featureRefVersion);
-    }
-
     private List<String> getStaged(Stage stage, Map<String, Stage> data) {
         List<String> staged = new ArrayList<>();
         for (String s : data.keySet()) {
@@ -1360,14 +1300,14 @@ public class Builder {
         blacklist.addAll(blacklistedFeatures);
         final List<String> blacklistRepos = new ArrayList<>();
         blacklistRepos.addAll(blacklistedRepositories);
-        final Clause[] clauses = org.apache.felix.utils.manifest.Parser.parseClauses(blacklist.toArray(new String[blacklist.size()]));
-        final Clause[] clausesRepos = org.apache.felix.utils.manifest.Parser.parseClauses(blacklistRepos.toArray(new String[blacklistRepos.size()]));
+        final Blacklist blacklistOther = new Blacklist(blacklist);
+        final Blacklist repoBlacklist = new Blacklist(blacklistRepos);
         for (String repository : repositories) {
             downloader.download(repository, new DownloadCallback() {
                 @Override
                 public void downloaded(final StreamProvider provider) throws Exception {
                     String url = provider.getUrl();
-                    if (Blacklist.isBlacklisted(clausesRepos, url, TYPE_REPOSITORY)) {
+                    if (repoBlacklist.isBlacklisted(url, TYPE_REPOSITORY)) {
                         LOGGER.info("      feature repository " + url + " is blacklisted");
                         return;
                     }
@@ -1375,7 +1315,7 @@ public class Builder {
                         if (!loaded.containsKey(provider.getUrl())) {
                             if (install) {
                                 synchronized (provider) {
-                                    Path path = pathFromProviderUrl(url);
+                                    Path path = ArtifactInstaller.pathFromProviderUrl(systemDirectory, url);
                                     Files.createDirectories(path.getParent());
                                     LOGGER.info("      adding feature repository: " + url);
                                     Files.copy(provider.getFile().toPath(), path, StandardCopyOption.REPLACE_EXISTING);
@@ -1384,7 +1324,7 @@ public class Builder {
                             try (InputStream is = provider.open()) {
                                 Features featuresModel = JaxbUtil.unmarshal(url, is, false);
                                 if (blacklistPolicy == BlacklistPolicy.Discard) {
-                                    Blacklist.blacklist(featuresModel, clauses);
+                                    blacklistOther.blacklist(featuresModel);
                                 }
                                 loaded.put(provider.getUrl(), featuresModel);
                                 for (String innerRepository : featuresModel.getRepository()) {
@@ -1476,6 +1416,7 @@ public class Builder {
         return request;
     }
 
+    @SuppressWarnings("rawtypes")
     private BundleRevision getSystemBundle() throws Exception {
         Path configPropPath = etcDirectory.resolve("config.properties");
         Properties configProps = PropertiesLoader.loadPropertiesOrFail(configPropPath.toFile());
@@ -1505,6 +1446,7 @@ public class Builder {
         return new FakeBundleRevision(headers, "system-bundle", 0L);
     }
 
+    @SuppressWarnings("rawtypes")
     private Map<String, String> getHeaders(StreamProvider provider) throws IOException {
         try (
                 ZipInputStream zis = new ZipInputStream(provider.open())
@@ -1524,18 +1466,6 @@ public class Builder {
         throw new IllegalArgumentException("Resource " + provider.getUrl() + " does not contain a manifest");
     }
 
-    private Path pathFromProviderUrl(String url) throws MalformedURLException {
-        String pathString;
-        if (url.startsWith("file:")) {
-            return Paths.get(URI.create(url));
-        }
-        else if (url.startsWith("mvn:")) {
-            pathString = Parser.pathFromMaven(url);
-        }
-        else {
-            pathString = url;
-        }
-        return systemDirectory.resolve(pathString);
-    }
+
 
 }