karaf-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From gno...@apache.org
Subject [5/6] karaf git commit: [KARAF-5272] Enhance the features deployer so that it performs a real upgrade
Date Tue, 25 Jul 2017 19:42:03 GMT
[KARAF-5272] Enhance the features deployer so that it performs a real upgrade

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

Branch: refs/heads/master
Commit: eb9960695d978b0d6c817202e688a4e4a0f6da45
Parents: bc9adda
Author: Guillaume Nodet <gnodet@apache.org>
Authored: Tue Jul 25 15:34:43 2017 +0200
Committer: Guillaume Nodet <gnodet@apache.org>
Committed: Tue Jul 25 21:40:14 2017 +0200

----------------------------------------------------------------------
 deployer/features/pom.xml                       |   1 +
 .../features/FeatureDeploymentListener.java     | 216 ++++++++-----------
 .../apache/karaf/features/FeaturesService.java  |   6 +
 .../internal/service/FeaturesServiceImpl.java   |  99 +++++++--
 .../internal/service/RepositoryCache.java       |   6 +-
 .../karaf/kar/internal/KarServiceImpl.java      |   4 +-
 6 files changed, 186 insertions(+), 146 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/karaf/blob/eb996069/deployer/features/pom.xml
----------------------------------------------------------------------
diff --git a/deployer/features/pom.xml b/deployer/features/pom.xml
index 0ff151a..d0c00bb 100644
--- a/deployer/features/pom.xml
+++ b/deployer/features/pom.xml
@@ -105,6 +105,7 @@
                             org.apache.karaf.deployer.features,
                             org.apache.karaf.deployer.features.osgi,
                             org.apache.karaf.util,
+                            org.apache.felix.utils.version
                         </Private-Package>
                     </instructions>
                 </configuration>

http://git-wip-us.apache.org/repos/asf/karaf/blob/eb996069/deployer/features/src/main/java/org/apache/karaf/deployer/features/FeatureDeploymentListener.java
----------------------------------------------------------------------
diff --git a/deployer/features/src/main/java/org/apache/karaf/deployer/features/FeatureDeploymentListener.java
b/deployer/features/src/main/java/org/apache/karaf/deployer/features/FeatureDeploymentListener.java
index ab954fa..58bfc2b 100644
--- a/deployer/features/src/main/java/org/apache/karaf/deployer/features/FeatureDeploymentListener.java
+++ b/deployer/features/src/main/java/org/apache/karaf/deployer/features/FeatureDeploymentListener.java
@@ -23,25 +23,27 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.net.URI;
-import java.net.URISyntaxException;
 import java.net.URL;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.EnumSet;
 import java.util.Enumeration;
-import java.util.HashSet;
 import java.util.List;
+import java.util.Map;
 import java.util.Properties;
 import java.util.Set;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
-import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.namespace.QName;
+import javax.xml.stream.XMLInputFactory;
+import javax.xml.stream.XMLStreamReader;
 
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-import org.w3c.dom.Document;
 
 import org.apache.felix.fileinstall.ArtifactUrlTransformer;
+import org.apache.felix.utils.version.VersionRange;
 import org.apache.karaf.features.Feature;
 import org.apache.karaf.features.FeaturesNamespaces;
 import org.apache.karaf.features.FeaturesService;
@@ -50,9 +52,8 @@ import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.BundleEvent;
 import org.osgi.framework.BundleListener;
-import org.xml.sax.ErrorHandler;
-import org.xml.sax.SAXException;
-import org.xml.sax.SAXParseException;
+
+import static org.apache.karaf.features.FeaturesService.ROOT_REGION;
 
 /**
  * A deployment listener able to hot deploy a feature descriptor
@@ -63,7 +64,7 @@ public class FeatureDeploymentListener implements ArtifactUrlTransformer,
Bundle
 
     private final Logger logger = LoggerFactory.getLogger(FeatureDeploymentListener.class);
 
-    private DocumentBuilderFactory dbf;
+    private XMLInputFactory xif;
     private FeaturesService featuresService;
     private BundleContext bundleContext;
     private Properties properties = new Properties();
@@ -144,9 +145,9 @@ public class FeatureDeploymentListener implements ArtifactUrlTransformer,
Bundle
     public boolean canHandle(File artifact) {
         try {
             if (artifact.isFile() && artifact.getName().endsWith(".xml")) {
-                Document doc = parse(artifact);
-                String name = doc.getDocumentElement().getLocalName();
-                String uri  = doc.getDocumentElement().getNamespaceURI();
+                QName qname = getRootElementName(artifact);
+                String name = qname.getLocalPart();
+                String uri  = qname.getNamespaceURI();
                 if ("features".equals(name) ) {
                 	if(isKnownFeaturesURI(uri)){
                         return true;
@@ -176,125 +177,94 @@ public class FeatureDeploymentListener implements ArtifactUrlTransformer,
Bundle
         }
     }
 
-    public void bundleChanged(BundleEvent bundleEvent) {
-            Bundle bundle = bundleEvent.getBundle();
-            if (bundleEvent.getType() == BundleEvent.RESOLVED) {
-                try {
-                    List<URL> urls = new ArrayList<>();
-                    Enumeration featuresUrlEnumeration = bundle.findEntries("/META-INF/"
+ FEATURE_PATH + "/", "*.xml", false);
-                    while (featuresUrlEnumeration != null && featuresUrlEnumeration.hasMoreElements())
{
-                        URL url = (URL) featuresUrlEnumeration.nextElement();
-                        try {
-                            featuresService.addRepository(url.toURI());
-                            URI needRemovedRepo = null;
-                            for (Repository repo : featuresService.listRepositories()) {
-                                if (repo.getURI().equals(url.toURI())) {
-                                    Set<Feature> features = new HashSet<>(Arrays.asList(repo.getFeatures()));
-                                    Set<String> autoInstallFeatures = new HashSet<>();
-                                    for(Feature feature:features) {
-                                        if(feature.getInstall() != null && feature.getInstall().equals(Feature.DEFAULT_INSTALL_MODE)){
-                                            if (!featuresService.isInstalled(feature)) {
-                                                autoInstallFeatures.add(feature.getId());
-                                            }
-                                        }
-                                    }
-                                    if (!autoInstallFeatures.isEmpty()) {
-                                        featuresService.installFeatures(autoInstallFeatures,
EnumSet.noneOf(FeaturesService.Option.class));
-                                    }
-                                } else {
-                                    //remove older out-of-data feature repo
-                                    if (repo.getURI().toString().contains(FEATURE_PATH))
{
-                                        String featureFileName = repo.getURI().toString();
-                                        featureFileName = featureFileName.substring(featureFileName.lastIndexOf('/')
+ 1);
-                                        String newFeatureFileName = url.toURI().toString();
-                                        newFeatureFileName = newFeatureFileName.substring(newFeatureFileName.lastIndexOf('/')
+ 1);
-                                        if (featureFileName.equals(newFeatureFileName)) {
-                                            needRemovedRepo = repo.getURI();
-                                        }
-                                    }
-                                }
+    public synchronized void bundleChanged(BundleEvent bundleEvent) {
+        // Only handle resolved and uninstalled events
+        if (bundleEvent.getType() != BundleEvent.RESOLVED
+                && bundleEvent.getType() != BundleEvent.UNINSTALLED) {
+            return;
+        }
+        Bundle bundle = bundleEvent.getBundle();
+        try {
+            // Remove previous informations
+            List<URI> repsToRemove = new ArrayList<>();
+            List<String> reqsToRemove = new ArrayList<>();
+            // Remove old properties
+            String prefix = "bundle." + bundle.getBundleId();
+            String countStr = (String) properties.remove(prefix + ".reps.count");
+            if (countStr != null) {
+                int count = Integer.parseInt(countStr);
+                for (int i = 0; i < count; i++) {
+                    String rep = (String) properties.remove(prefix + ".reps.item" + i);
+                    repsToRemove.add(URI.create(rep));
+                }
+            }
+            countStr = (String) properties.remove(prefix + ".reqs.count");
+            if (countStr != null) {
+                int count = Integer.parseInt(countStr);
+                for (int i = 0; i < count; i++) {
+                    String req = (String) properties.remove(prefix + ".reqs.item" + i);
+                    reqsToRemove.add(req);
+                }
+            }
+            saveProperties();
 
-                            }
-                            urls.add(url);
-                            if (needRemovedRepo != null) {
-                                featuresService.removeRepository(needRemovedRepo);
-                            }
-                        } catch (Exception e) {
-                            logger.error("Unable to install features", e);
-                        }
-                    }
-                    synchronized (this) {
-                        String prefix = bundle.getSymbolicName() + "-" + bundle.getVersion();
-                        String old = (String) properties.get(prefix + ".count");
-                        if (old != null && urls.isEmpty()) {
-                            properties.remove(prefix + ".count");
-                            saveProperties();
-                        } else if (!urls.isEmpty()) {
-                            properties.put(prefix + ".count", Integer.toString(urls.size()));
-                            for (int i = 0; i < urls.size(); i++) {
-                                properties.put(prefix + ".url." + i, urls.get(i).toExternalForm());
-                            }
-                            saveProperties();
-                        }
-                    }
-                } catch (Exception e) {
-                    logger.error("Unable to install deployed features for bundle: " + bundle.getSymbolicName()
+ " - " + bundle.getVersion(), e);
+            // Compute new informations
+            List<URI> repsToAdd = new ArrayList<>();
+            List<String> reqsToAdd = new ArrayList<>();
+            if (bundleEvent.getType() == BundleEvent.RESOLVED) {
+                Enumeration featuresUrlEnumeration = bundle.findEntries("/META-INF/" + FEATURE_PATH
+ "/", "*.xml", false);
+                while (featuresUrlEnumeration != null && featuresUrlEnumeration.hasMoreElements())
{
+                    URL url = (URL) featuresUrlEnumeration.nextElement();
+                    URI uri = url.toURI();
+                    repsToAdd.add(uri);
+                    Repository rep = featuresService.createRepository(uri);
+                    Stream.of(rep.getFeatures())
+                            .filter(f -> f.getInstall() == null || Feature.DEFAULT_INSTALL_MODE.equals(f.getInstall()))
+                            .map(f -> "feature:" + f.getName() + "/" + new VersionRange(f.getVersion(),
true))
+                            .forEach(reqsToAdd::add);
                 }
-            } else if (bundleEvent.getType() == BundleEvent.UNINSTALLED) {
-                try {
-                    synchronized (this) {
-                        String prefix = bundle.getSymbolicName() + "-" + bundle.getVersion();
-                        String countStr = (String) properties.remove(prefix + ".count");
-                        if (countStr != null) {
-                            int count = Integer.parseInt(countStr);
-                            for (int i = 0; i < count; i++) {
-                                URL url = new URL((String) properties.remove(prefix + ".url."
+ i));
-                                for (Repository repo : featuresService.listRepositories())
{
-                                    try {
-                                        if (repo.getURI().equals(url.toURI())) {
-                                            for (Feature f : repo.getFeatures()) {
-                                                try {
-                                                    featuresService.uninstallFeature(f.getName(),
f.getVersion());
-                                                } catch (Exception e) {
-                                                    logger.error("Unable to uninstall feature:
" + f.getName(), e);
-                                                }
-                                            }
-                                        }
-                                    } catch (Exception e) {
-                                        logger.error("Unable to uninstall features: " + url,
e);
-                                    }
-                                }
-                                try {
-                                    featuresService.removeRepository(url.toURI());
-                                } catch (URISyntaxException e) {
-                                    logger.error("Unable to remove repository: " + url, e);
-                                }
-                            }
-                            saveProperties();
-                        }
+                if (!repsToAdd.isEmpty()) {
+                    properties.put(prefix + ".reps.count", Integer.toString(repsToAdd.size()));
+                    for (int i = 0; i < repsToAdd.size(); i++) {
+                        properties.put(prefix + ".reps.item" + i, repsToAdd.get(i).toASCIIString());
+                    }
+                    properties.put(prefix + ".reqs.count", Integer.toString(reqsToAdd.size()));
+                    for (int i = 0; i < reqsToAdd.size(); i++) {
+                        properties.put(prefix + ".reqs.item" + i, reqsToAdd.get(i));
                     }
-                } catch (Exception e) {
-                    logger.error("Unable to uninstall deployed features for bundle: " + bundle.getSymbolicName()
+ " - " + bundle.getVersion(), e);
                 }
             }
+            saveProperties();
+
+            // Call features service
+            List<Repository> requiredRepos = Arrays.asList(featuresService.listRequiredRepositories());
+            Set<URI> requiredReposUris = requiredRepos.stream()
+                    .map(Repository::getURI).collect(Collectors.toSet());
+            requiredReposUris.removeAll(repsToRemove);
+            requiredReposUris.addAll(repsToAdd);
+
+            Map<String, Set<String>> requirements = featuresService.listRequirements();
+            requirements.get(ROOT_REGION).removeAll(reqsToRemove);
+            requirements.get(ROOT_REGION).addAll(reqsToAdd);
+
+            if (!reqsToRemove.isEmpty() || !reqsToAdd.isEmpty()) {
+                featuresService.updateReposAndRequirements(requiredReposUris, requirements,
EnumSet.noneOf(FeaturesService.Option.class));
+            }
+        } catch (Exception e) {
+            logger.error("Unable to update deployed features for bundle: " + bundle.getSymbolicName()
+ " - " + bundle.getVersion(), e);
+        }
     }
 
-    protected Document parse(File artifact) throws Exception {
-        if (dbf == null) {
-            dbf = DocumentBuilderFactory.newInstance();
-            dbf.setNamespaceAware(true);
+    private QName getRootElementName(File artifact) throws Exception {
+        if (xif == null) {
+            xif = XMLInputFactory.newFactory();
+            xif.setProperty(XMLInputFactory.IS_NAMESPACE_AWARE, true);
+        }
+        try (InputStream is = new FileInputStream(artifact)) {
+            XMLStreamReader sr = xif.createXMLStreamReader(is);
+            sr.nextTag();
+            return sr.getName();
         }
-        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/eb996069/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
index c8cdd15..29c9093 100644
--- a/features/core/src/main/java/org/apache/karaf/features/FeaturesService.java
+++ b/features/core/src/main/java/org/apache/karaf/features/FeaturesService.java
@@ -126,6 +126,12 @@ public interface FeaturesService {
 
     void updateFeaturesState(Map<String, Map<String, FeatureState>> stateChanges,
EnumSet<Option> options) throws Exception;
 
+    void updateReposAndRequirements(Set<URI> repos,
+                                    Map<String, Set<String>> requirements,
+                                    EnumSet<Option> options) throws Exception;
+
+    Repository createRepository(URI uri) throws Exception;
+
     Feature[] listFeatures() throws Exception;
 
     Feature[] listRequiredFeatures() throws Exception;

http://git-wip-us.apache.org/repos/asf/karaf/blob/eb996069/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 353d40d..bd98364 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
@@ -42,12 +42,14 @@ import java.util.concurrent.ExecutionException;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
 import java.util.concurrent.ScheduledThreadPoolExecutor;
+import java.util.function.Function;
 import java.util.function.Predicate;
 import java.util.regex.Matcher;
 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;
@@ -178,7 +180,7 @@ public class FeaturesServiceImpl implements FeaturesService, Deployer.DeployCall
         // Resolve
         try {
             Map<String, Map<String, FeatureState>> stateChanges = Collections.emptyMap();
-            doProvisionInThread(requestedFeatures, stateChanges, copyState(), options);
+            doProvisionInThread(requestedFeatures, stateChanges, copyState(), getFeaturesById(),
options);
         } catch (Exception e) {
             LOGGER.warn("Error updating state", e);
         }
@@ -645,6 +647,11 @@ public class FeaturesServiceImpl implements FeaturesService, Deployer.DeployCall
         return map;
     }
 
+    protected Map<String, Feature> getFeaturesById() throws Exception {
+        return getFeatureCache().values().stream().flatMap(m -> m.values().stream())
+                .collect(Collectors.toMap(Feature::getId, Function.identity()));
+    }
+
    //
     // Installed features
     //
@@ -858,7 +865,7 @@ public class FeaturesServiceImpl implements FeaturesService, Deployer.DeployCall
         }
         print("Adding features: " + join(featuresToDisplay), options.contains(Option.Verbose));
         Map<String, Map<String, FeatureState>> stateChanges = Collections.emptyMap();
-        doProvisionInThread(required, stateChanges, state, options);
+        doProvisionInThread(required, stateChanges, state, getFeaturesById(), options);
     }
 
     @Override
@@ -909,13 +916,13 @@ public class FeaturesServiceImpl implements FeaturesService, Deployer.DeployCall
             required.remove(region);
         }
         Map<String, Map<String, FeatureState>> stateChanges = Collections.emptyMap();
-        doProvisionInThread(required, stateChanges, state, options);
+        doProvisionInThread(required, stateChanges, state, getFeaturesById(), options);
     }
 
     @Override
     public void updateFeaturesState(Map<String, Map<String, FeatureState>> stateChanges,
EnumSet<Option> options) throws Exception {
         State state = copyState();
-        doProvisionInThread(copy(state.requirements), stateChanges, state, options);
+        doProvisionInThread(copy(state.requirements), stateChanges, state, getFeaturesById(),
options);
     }
 
     @Override
@@ -924,7 +931,7 @@ public class FeaturesServiceImpl implements FeaturesService, Deployer.DeployCall
         Map<String, Set<String>> required = copy(state.requirements);
         add(required, requirements);
         Map<String, Map<String, FeatureState>> stateChanges = Collections.emptyMap();
-        doProvisionInThread(required, stateChanges, state, options);
+        doProvisionInThread(required, stateChanges, state, getFeaturesById(), options);
     }
 
     @Override
@@ -933,7 +940,63 @@ public class FeaturesServiceImpl implements FeaturesService, Deployer.DeployCall
         Map<String, Set<String>> required = copy(state.requirements);
         remove(required, requirements);
         Map<String, Map<String, FeatureState>> stateChanges = Collections.emptyMap();
-        doProvisionInThread(required, stateChanges, state, options);
+        doProvisionInThread(required, stateChanges, state, getFeaturesById(), options);
+    }
+
+    @Override
+    public void updateReposAndRequirements(Set<URI> repos, Map<String, Set<String>>
requirements, EnumSet<Option> options) throws Exception {
+        State stateCopy;
+        synchronized (lock) {
+            // Remove repo
+            Set<String> reps = repos.stream().map(URI::toString).collect(Collectors.toSet());
+            Set<String> toRemove = diff(state.repositories, reps);
+            Set<String> toAdd = diff(reps, state.repositories);
+            state.repositories.removeAll(toRemove);
+            state.repositories.addAll(toAdd);
+            featureCache = null;
+            for (String uri : toRemove) {
+                repositories.removeRepository(URI.create(uri));
+            }
+            for (String uri : toAdd) {
+                repositories.addRepository(createRepository(URI.create(uri)));
+            }
+            saveState();
+            stateCopy = state.copy();
+        }
+        Map<String, Map<String, FeatureState>> stateChanges = Collections.emptyMap();
+        doProvisionInThread(requirements, stateChanges, stateCopy, getFeaturesById(), options);
+    }
+
+    private <T> Set<T> diff(Set<T> s1, Set<T> s2) {
+        Set<T> s = new HashSet<>(s1);
+        s.removeAll(s2);
+        return s;
+    }
+
+    @Override
+    public Repository createRepository(URI uri) throws Exception {
+        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
@@ -974,12 +1037,13 @@ public class FeaturesServiceImpl implements FeaturesService, Deployer.DeployCall
     private void doProvisionInThread(final Map<String, Set<String>> requirements,
                                     final Map<String, Map<String, FeatureState>>
stateChanges,
                                     final State state,
+                                    final Map<String, Feature> featureById,
                                     final EnumSet<Option> options) throws Exception
{
         try {
             final String outputFile = this.outputFile.get();
             this.outputFile.set(null);
             executor.submit(() -> {
-                doProvision(requirements, stateChanges, state, options, outputFile);
+                doProvision(requirements, stateChanges, state, featureById, options, outputFile);
                 return null;
             }).get();
         } catch (ExecutionException e) {
@@ -996,7 +1060,7 @@ public class FeaturesServiceImpl implements FeaturesService, Deployer.DeployCall
         }
     }
 
-    private Deployer.DeploymentState getDeploymentState(State state) throws Exception {
+    private Deployer.DeploymentState getDeploymentState(State state, Map<String, Feature>
featuresById) throws Exception {
         Deployer.DeploymentState dstate = new Deployer.DeploymentState();
         dstate.state = state;
         FrameworkInfo info = installSupport.getInfo();
@@ -1005,13 +1069,7 @@ public class FeaturesServiceImpl implements FeaturesService, Deployer.DeployCall
         dstate.currentStartLevel = info.currentStartLevel;
         dstate.bundles = info.bundles;
         // Features
-        dstate.features = new HashMap<>();
-        for (Map<String, Feature> m : getFeatureCache().values()) {
-            for (Feature feature : m.values()) {
-                String id = feature.getId();
-                dstate.features.put(id, feature);
-            }
-        }
+        dstate.features = featuresById;
         RegionDigraph regionDigraph = installSupport.getDiGraphCopy();
         dstate.bundlesPerRegion = DigraphHelper.getBundlesPerRegion(regionDigraph);
         dstate.filtersPerRegion = DigraphHelper.getPolicies(regionDigraph);
@@ -1034,10 +1092,11 @@ public class FeaturesServiceImpl implements FeaturesService, Deployer.DeployCall
     }
 
     private void doProvision(Map<String, Set<String>> requirements,         
      // all requirements
-                            Map<String, Map<String, FeatureState>> stateChanges,
 // features state changes
-                            State state,                                          // current
state
-                            EnumSet<Option> options,                              //
installation options
-                            String outputFile                                     // file
to store the resolution or null
+                             Map<String, Map<String, FeatureState>> stateChanges,
 // features state changes
+                             State state,                                          // current
state
+                             Map<String, Feature> featuresById,                   
// features by id
+                             EnumSet<Option> options,                             
// installation options
+                             String outputFile                                     // file
to store the resolution or null
     ) throws Exception {
 
         Dictionary<String, String> props = getMavenConfig();
@@ -1049,7 +1108,7 @@ public class FeaturesServiceImpl implements FeaturesService, Deployer.DeployCall
             Set<String> prereqs = new HashSet<>();
             while (true) {
                 try {
-                    Deployer.DeploymentState dstate = getDeploymentState(state);
+                    Deployer.DeploymentState dstate = getDeploymentState(state, featuresById);
                     Deployer.DeploymentRequest request = getDeploymentRequest(requirements,
stateChanges, options, outputFile);
                     new Deployer(manager, this.resolver, this).deploy(dstate, request);
                     break;

http://git-wip-us.apache.org/repos/asf/karaf/blob/eb996069/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 54cf04f..f92b0bc 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
@@ -39,7 +39,11 @@ public class RepositoryCache {
     public RepositoryCache(String blacklisted) {
         this.blacklisted = loadBlacklist(blacklisted);
     }
-    
+
+    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()]));

http://git-wip-us.apache.org/repos/asf/karaf/blob/eb996069/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
index 743e74a..30f7279 100644
--- a/kar/src/main/java/org/apache/karaf/kar/internal/KarServiceImpl.java
+++ b/kar/src/main/java/org/apache/karaf/kar/internal/KarServiceImpl.java
@@ -274,7 +274,7 @@ public class KarServiceImpl implements KarService {
                 if (repository.getURI().equals(karFeatureRepoUri)) {
                     try {
                         for (Feature feature : repository.getFeatures()) {
-                            if (feature.getInstall() == null || !feature.getInstall().equals("manual"))
{
+                            if (feature.getInstall() == null || Feature.DEFAULT_INSTALL_MODE.equals(feature.getInstall()))
{
                                 try {
                                     LOGGER.debug("noAutoRefreshBundles is " + isNoAutoRefreshBundles());
                                     if (isNoAutoRefreshBundles()) {
@@ -430,7 +430,7 @@ public class KarServiceImpl implements KarService {
                 if (repository.getURI().equals(karFeatureRepoUri)) {
                     try {
                         for (Feature feature : repository.getFeatures()) {
-                            if (feature.getInstall() == null || !feature.getInstall().equals("manual"))
{
+                            if (feature.getInstall() == null || Feature.DEFAULT_INSTALL_MODE.equals(feature.getInstall()))
{
                                 try {
                                     featuresService.uninstallFeature(feature.getName(), feature.getVersion());
                                 } catch (Exception e) {


Mime
View raw message