karaf-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From gno...@apache.org
Subject karaf git commit: [KARAF-4827] Cannot install feature depending on other 2+ levels of features with prerequisite="true"
Date Tue, 22 Nov 2016 16:28:47 GMT
Repository: karaf
Updated Branches:
  refs/heads/master 46b26566f -> c4aa24843


[KARAF-4827] Cannot install feature depending on other 2+ levels of features with prerequisite="true"

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

Branch: refs/heads/master
Commit: c4aa24843b656004af2a336a8cf7b03b5d09389c
Parents: 46b2656
Author: Guillaume Nodet <gnodet@apache.org>
Authored: Tue Nov 22 15:42:24 2016 +0100
Committer: Guillaume Nodet <gnodet@apache.org>
Committed: Tue Nov 22 17:15:03 2016 +0100

----------------------------------------------------------------------
 .../features/internal/region/Subsystem.java     |  19 ++-
 .../features/internal/service/DeployerTest.java | 154 ++++++++++++++++++-
 .../features/internal/service/data3/a100.mf     |   5 +
 .../features/internal/service/data3/b100.mf     |   5 +
 .../features/internal/service/data3/c100.mf     |   5 +
 .../internal/service/data3/features.xml         |  67 ++++++++
 6 files changed, 247 insertions(+), 8 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/karaf/blob/c4aa2484/features/core/src/main/java/org/apache/karaf/features/internal/region/Subsystem.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/region/Subsystem.java
b/features/core/src/main/java/org/apache/karaf/features/internal/region/Subsystem.java
index 65f6dea..4a4a48b 100644
--- a/features/core/src/main/java/org/apache/karaf/features/internal/region/Subsystem.java
+++ b/features/core/src/main/java/org/apache/karaf/features/internal/region/Subsystem.java
@@ -342,10 +342,21 @@ public class Subsystem extends ResourceImpl {
         for (Subsystem child : children) {
             child.doCollectPrerequisites(prereqs);
         }
-        if (feature != null && !prereqs.contains(feature.getId())) {
-            for (Dependency dep : feature.getDependencies()) {
-                if (dep.isPrerequisite()) {
-                    prereqs.add(dep.toString());
+        if (feature != null) {
+            boolean match = false;
+            for (String prereq : prereqs) {
+                String[] p = prereq.split("/");
+                if (feature.getName().equals(p[0])
+                        && VersionRange.parseVersionRange(p[1]).contains(Version.parseVersion(feature.getVersion())))
{
+                    match = true;
+                    break;
+                }
+            }
+            if (!match) {
+                for (Dependency dep : feature.getDependencies()) {
+                    if (dep.isPrerequisite()) {
+                        prereqs.add(dep.toString());
+                    }
                 }
             }
         }

http://git-wip-us.apache.org/repos/asf/karaf/blob/c4aa2484/features/core/src/test/java/org/apache/karaf/features/internal/service/DeployerTest.java
----------------------------------------------------------------------
diff --git a/features/core/src/test/java/org/apache/karaf/features/internal/service/DeployerTest.java
b/features/core/src/test/java/org/apache/karaf/features/internal/service/DeployerTest.java
index 88913c4..4f5584c 100644
--- a/features/core/src/test/java/org/apache/karaf/features/internal/service/DeployerTest.java
+++ b/features/core/src/test/java/org/apache/karaf/features/internal/service/DeployerTest.java
@@ -19,9 +19,11 @@ package org.apache.karaf.features.internal.service;
 import java.io.IOException;
 import java.io.InputStream;
 import java.net.URL;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.EnumSet;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.Hashtable;
 import java.util.List;
 import java.util.Map;
@@ -39,9 +41,11 @@ import org.apache.karaf.features.internal.support.TestDownloadManager;
 import org.easymock.EasyMock;
 import org.easymock.IAnswer;
 import org.easymock.IArgumentMatcher;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleException;
+import org.osgi.framework.InvalidSyntaxException;
 import org.osgi.resource.Resource;
 import org.osgi.resource.Wire;
 import org.osgi.service.resolver.Resolver;
@@ -306,8 +310,8 @@ public class DeployerTest {
         callback.installFeature(f1);
         EasyMock.expectLastCall();
         callback.resolveBundles(EasyMock.<Set<Bundle>>anyObject(),
-                                EasyMock.<Map<Resource, List<Wire>>>anyObject(),
-                                EasyMock.<Map<Resource, Bundle>>anyObject());
+                EasyMock.<Map<Resource, List<Wire>>>anyObject(),
+                EasyMock.<Map<Resource, Bundle>>anyObject());
         EasyMock.expectLastCall();
         callback.callListeners(EasyMock.<FeatureEvent>anyObject());
         EasyMock.expectLastCall();
@@ -358,8 +362,8 @@ public class DeployerTest {
         callback.installFeature(f2);
         EasyMock.expectLastCall();
         callback.resolveBundles(EasyMock.<Set<Bundle>>anyObject(),
-                                EasyMock.<Map<Resource, List<Wire>>>anyObject(),
-                                EasyMock.<Map<Resource, Bundle>>anyObject());
+                EasyMock.<Map<Resource, List<Wire>>>anyObject(),
+                EasyMock.<Map<Resource, Bundle>>anyObject());
         EasyMock.expectLastCall();
         callback.callListeners(EasyMock.<FeatureEvent>anyObject());
         EasyMock.expectLastCall();
@@ -397,6 +401,81 @@ public class DeployerTest {
         EasyMock.verify(callback);
     }
 
+    @Test
+    public void testPrereqOnPrereq1() throws Exception {
+        doTestPrereqOnPrereq(1);
+    }
+
+    @Test
+    public void testPrereqOnPrereq2() throws Exception {
+        doTestPrereqOnPrereq(2);
+    }
+
+    @Test
+    public void testPrereqOnPrereq3() throws Exception {
+        doTestPrereqOnPrereq(3);
+    }
+
+    @Test
+    public void testPrereqOnPrereq4() throws Exception {
+        doTestPrereqOnPrereq(4);
+    }
+
+    private void doTestPrereqOnPrereq(int scenario) throws Exception {
+        String dataDir = "data3";
+
+        TestDownloadManager manager = new TestDownloadManager(getClass(), dataDir);
+
+        RepositoryImpl repo = new RepositoryImpl(getClass().getResource(dataDir + "/features.xml").toURI());
+        repo.load(true);
+
+        Map<String, Bundle> bundles = new HashMap<>();
+        bundles.put("a100", createTestBundle(1, Bundle.ACTIVE, dataDir, "a100"));
+        bundles.put("b100", createTestBundle(2, Bundle.ACTIVE, dataDir, "b100"));
+        bundles.put("c100", createTestBundle(3, Bundle.ACTIVE, dataDir, "c100"));
+
+        Deployer.DeploymentState dstate = new Deployer.DeploymentState();
+        dstate.state = new State();
+        dstate.bundles = new HashMap<>();
+        dstate.bundlesPerRegion = new HashMap<>();
+        dstate.features = new HashMap<>();
+        for (Feature f : repo.getFeatures()) {
+            dstate.features.put(f.getId(), f);
+        }
+        dstate.filtersPerRegion = new HashMap<>();
+        dstate.filtersPerRegion.put(ROOT_REGION, new HashMap<>());
+
+        Deployer.DeploymentRequest request = new Deployer.DeploymentRequest();
+        request.bundleUpdateRange = DEFAULT_BUNDLE_UPDATE_RANGE;
+        request.featureResolutionRange = DEFAULT_FEATURE_RESOLUTION_RANGE;
+        request.globalRepository = null;
+        request.options = EnumSet.noneOf(Option.class);
+        request.overrides = Collections.emptySet();
+        request.stateChanges = Collections.emptyMap();
+        request.updateSnaphots = UPDATE_SNAPSHOTS_NONE;
+
+        MyDeployCallback callback = new MyDeployCallback(dstate, bundles);
+        Deployer deployer = new Deployer(manager, resolver, callback);
+
+        for (int i = 1; i <= 4; i++) {
+            request.requirements = new HashMap<>();
+            addToMapSet(request.requirements, ROOT_REGION, "demo-" + scenario + "-c");
+            Set<String> prereqs = new HashSet<>();
+            while (true) {
+                try {
+                    deployer.deploy(callback.dstate, request);
+                    break;
+                } catch (Deployer.PartialDeploymentException e) {
+                    if (!prereqs.containsAll(e.getMissing())) {
+                        prereqs.addAll(e.getMissing());
+                    } else {
+                        throw new Exception("Deployment aborted due to loop in missing prerequisites:
" + e.getMissing());
+                    }
+                }
+            }
+        }
+    }
+
     private TestBundle createTestBundle(long bundleId, int state, String dir, String name)
throws IOException, BundleException {
         URL loc = getClass().getResource(dir + "/" + name + ".mf");
         Manifest man = new Manifest(loc.openStream());
@@ -434,4 +513,71 @@ public class DeployerTest {
         }
     }
 
+    private static class MyDeployCallback implements Deployer.DeployCallback {
+        final Deployer.DeploymentState dstate;
+        final Map<String, Bundle> bundles;
+
+        public MyDeployCallback(Deployer.DeploymentState dstate, Map<String, Bundle>
bundles) {
+            this.dstate = dstate;
+            this.bundles = bundles;
+        }
+
+        @Override
+        public void print(String message, boolean verbose) {
+        }
+
+        @Override
+        public void saveState(State state) {
+            this.dstate.state.replace(state);
+        }
+
+        @Override
+        public void persistResolveRequest(Deployer.DeploymentRequest request) throws IOException
{
+        }
+
+        @Override
+        public void installFeature(Feature feature) throws IOException, InvalidSyntaxException
{
+        }
+
+        @Override
+        public void callListeners(FeatureEvent featureEvent) {
+        }
+
+        @Override
+        public Bundle installBundle(String region, String uri, InputStream is) throws BundleException
{
+            return bundles.get(uri);
+        }
+
+        @Override
+        public void updateBundle(Bundle bundle, String uri, InputStream is) throws BundleException
{
+        }
+
+        @Override
+        public void uninstall(Bundle bundle) throws BundleException {
+        }
+
+        @Override
+        public void startBundle(Bundle bundle) throws BundleException {
+        }
+
+        @Override
+        public void stopBundle(Bundle bundle, int options) throws BundleException {
+        }
+
+        @Override
+        public void setBundleStartLevel(Bundle bundle, int startLevel) {
+        }
+
+        @Override
+        public void refreshPackages(Collection<Bundle> bundles) throws InterruptedException
{
+        }
+
+        @Override
+        public void resolveBundles(Set<Bundle> bundles, Map<Resource, List<Wire>>
wiring, Map<Resource, Bundle> resToBnd) {
+        }
+
+        @Override
+        public void replaceDigraph(Map<String, Map<String, Map<String, Set<String>>>>
policies, Map<String, Set<Long>> bundles) throws BundleException, InvalidSyntaxException
{
+        }
+    }
 }

http://git-wip-us.apache.org/repos/asf/karaf/blob/c4aa2484/features/core/src/test/resources/org/apache/karaf/features/internal/service/data3/a100.mf
----------------------------------------------------------------------
diff --git a/features/core/src/test/resources/org/apache/karaf/features/internal/service/data3/a100.mf
b/features/core/src/test/resources/org/apache/karaf/features/internal/service/data3/a100.mf
new file mode 100644
index 0000000..20a7811
--- /dev/null
+++ b/features/core/src/test/resources/org/apache/karaf/features/internal/service/data3/a100.mf
@@ -0,0 +1,5 @@
+Manifest-Version: 1
+Bundle-ManifestVersion: 2
+Bundle-SymbolicName: a
+Bundle-Version: 1.0.0
+

http://git-wip-us.apache.org/repos/asf/karaf/blob/c4aa2484/features/core/src/test/resources/org/apache/karaf/features/internal/service/data3/b100.mf
----------------------------------------------------------------------
diff --git a/features/core/src/test/resources/org/apache/karaf/features/internal/service/data3/b100.mf
b/features/core/src/test/resources/org/apache/karaf/features/internal/service/data3/b100.mf
new file mode 100644
index 0000000..dc96158
--- /dev/null
+++ b/features/core/src/test/resources/org/apache/karaf/features/internal/service/data3/b100.mf
@@ -0,0 +1,5 @@
+Manifest-Version: 1
+Bundle-ManifestVersion: 2
+Bundle-SymbolicName: b
+Bundle-Version: 1.0.0
+

http://git-wip-us.apache.org/repos/asf/karaf/blob/c4aa2484/features/core/src/test/resources/org/apache/karaf/features/internal/service/data3/c100.mf
----------------------------------------------------------------------
diff --git a/features/core/src/test/resources/org/apache/karaf/features/internal/service/data3/c100.mf
b/features/core/src/test/resources/org/apache/karaf/features/internal/service/data3/c100.mf
new file mode 100644
index 0000000..8535efa
--- /dev/null
+++ b/features/core/src/test/resources/org/apache/karaf/features/internal/service/data3/c100.mf
@@ -0,0 +1,5 @@
+Manifest-Version: 1
+Bundle-ManifestVersion: 2
+Bundle-SymbolicName: c
+Bundle-Version: 1.0.0
+

http://git-wip-us.apache.org/repos/asf/karaf/blob/c4aa2484/features/core/src/test/resources/org/apache/karaf/features/internal/service/data3/features.xml
----------------------------------------------------------------------
diff --git a/features/core/src/test/resources/org/apache/karaf/features/internal/service/data3/features.xml
b/features/core/src/test/resources/org/apache/karaf/features/internal/service/data3/features.xml
new file mode 100644
index 0000000..68aec92
--- /dev/null
+++ b/features/core/src/test/resources/org/apache/karaf/features/internal/service/data3/features.xml
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<features name="karaf" xmlns="http://karaf.apache.org/xmlns/features/v1.3.0">
+    <feature name="demo-1-a">
+        <bundle>a100</bundle>
+    </feature>
+    <feature name="demo-1-b">
+        <feature prerequisite="true">demo-1-a</feature>
+        <bundle>b100</bundle>
+    </feature>
+    <feature name="demo-1-c">
+        <feature prerequisite="true">demo-1-b</feature>
+        <bundle>c100</bundle>
+    </feature>
+
+    <feature name="demo-2-a" version="2.1.0">
+        <bundle>a100</bundle>
+    </feature>
+    <feature name="demo-2-b" version="2.1.0">
+        <feature prerequisite="true">demo-2-a</feature>
+        <bundle>b100</bundle>
+    </feature>
+    <feature name="demo-2-c" version="2.1.0">
+        <feature prerequisite="true" version="2.1.0">demo-2-b</feature>
+        <bundle>c100</bundle>
+    </feature>
+
+    <feature name="demo-3-a" version="2.1.0">
+        <bundle>a100</bundle>
+    </feature>
+    <feature name="demo-3-b" version="2.1.0">
+        <feature prerequisite="true">demo-3-a</feature>
+        <bundle>b100</bundle>
+    </feature>
+    <feature name="demo-3-c" version="2.1.0">
+        <feature prerequisite="true">demo-3-b</feature>
+        <bundle>c100</bundle>
+    </feature>
+
+    <feature name="demo-4-a" version="2.1.0">
+        <bundle>a100</bundle>
+    </feature>
+    <feature name="demo-4-b" version="2.1.0-SNAPSHOT">
+        <feature prerequisite="true">demo-4-a</feature>
+        <bundle>b100</bundle>
+    </feature>
+    <feature name="demo-4-c" version="2.1.0">
+        <feature prerequisite="true" version="2.1.0-SNAPSHOT">demo-4-b</feature>
+        <bundle>c100</bundle>
+    </feature>
+</features>
+


Mime
View raw message