Repository: karaf Updated Branches: refs/heads/karaf-4.1.x 777f0c6d3 -> 67e2e6c24
[KARAF-5435] BundleException when installing a bundle by API when the FeatureService install a feature Project: http://git-wip-us.apache.org/repos/asf/karaf/repo Commit: http://git-wip-us.apache.org/repos/asf/karaf/commit/67e2e6c2 Tree: http://git-wip-us.apache.org/repos/asf/karaf/tree/67e2e6c2 Diff: http://git-wip-us.apache.org/repos/asf/karaf/diff/67e2e6c2 Branch: refs/heads/karaf-4.1.x Commit: 67e2e6c2498aa44fd2270414424c048734727250 Parents: 777f0c6 Author: Guillaume Nodet <[email protected]> Authored: Fri Oct 20 16:08:14 2017 +0200 Committer: Guillaume Nodet <[email protected]> Committed: Fri Oct 20 16:08:14 2017 +0200 ---------------------------------------------------------------------- .../internal/service/FeaturesServiceImpl.java | 38 ++++++++++++++------ .../karaf/features/FeaturesServiceTest.java | 6 ++-- 2 files changed, 31 insertions(+), 13 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/karaf/blob/67e2e6c2/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 39a31d4..836b0a8 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 @@ -41,6 +41,7 @@ import java.util.Queue; import java.util.Set; import java.util.TreeMap; import java.util.TreeSet; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; @@ -193,6 +194,9 @@ public class FeaturesServiceImpl implements FeaturesService, Deployer.DeployCall private final ExecutorService executor; private Map<String, Map<String, Feature>> featureCache; + private Map<Thread, ResolverHook> hooks = new ConcurrentHashMap<>(); + private ServiceRegistration<ResolverHookFactory> hookRegistration; + public FeaturesServiceImpl(Bundle bundle, BundleContext bundleContext, BundleContext systemBundleContext, @@ -260,12 +264,25 @@ public class FeaturesServiceImpl implements FeaturesService, Deployer.DeployCall this.blacklisted = blacklisted; this.configCfgStore = configCfgStore; this.executor = Executors.newSingleThreadExecutor(ThreadUtils.namedThreadFactory("features")); + + if (systemBundleContext != null) { + hookRegistration = systemBundleContext.registerService(ResolverHookFactory.class, new ResolverHookFactory() { + @Override + public ResolverHook begin(Collection<BundleRevision> triggers) { + return hooks.get(Thread.currentThread()); + } + }, null); + } + loadState(); checkResolve(); } public void stop() { - this.executor.shutdown(); + this.executor.shutdown(); + if (hookRegistration != null) { + hookRegistration.unregister(); + } } @SuppressWarnings({"unchecked", "rawtypes"}) @@ -1382,10 +1399,16 @@ public class FeaturesServiceImpl implements FeaturesService, Deployer.DeployCall } Bundle sourceBundle = requirement.getRevision().getBundle(); Resource sourceResource = bndToRes.get(sourceBundle); + List<Wire> wires = wiring.get(sourceResource); + if (sourceBundle == null || wires == null) { + // This could be a bundle external to this resolution which + // is being resolve at the same time, so do not interfere + return; + } Set<Resource> wired = new HashSet<>(); // Get a list of allowed wired resources wired.add(sourceResource); - for (Wire wire : wiring.get(sourceResource)) { + for (Wire wire : wires) { wired.add(wire.getProvider()); if (HostNamespace.HOST_NAMESPACE.equals(wire.getRequirement().getNamespace())) { for (Wire hostWire : wiring.get(wire.getProvider())) { @@ -1411,18 +1434,13 @@ public class FeaturesServiceImpl implements FeaturesService, Deployer.DeployCall public void end() { } }; - ResolverHookFactory factory = new ResolverHookFactory() { - @Override - public ResolverHook begin(Collection<BundleRevision> triggers) { - return hook; - } - }; - ServiceRegistration<ResolverHookFactory> registration = systemBundleContext.registerService(ResolverHookFactory.class, factory, null); + + hooks.put(thread, hook); try { FrameworkWiring frameworkWiring = systemBundleContext.getBundle().adapt(FrameworkWiring.class); frameworkWiring.resolveBundles(bundles); } finally { - registration.unregister(); + hooks.remove(thread); } } http://git-wip-us.apache.org/repos/asf/karaf/blob/67e2e6c2/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 40ce483..6301660 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 @@ -39,14 +39,13 @@ import org.junit.Before; import org.junit.Test; import org.osgi.framework.Bundle; import org.osgi.framework.BundleContext; +import org.osgi.framework.hooks.resolver.ResolverHookFactory; import org.osgi.framework.startlevel.FrameworkStartLevel; import org.osgi.service.resolver.Resolver; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import static org.easymock.EasyMock.expect; -import static org.easymock.EasyMock.replay; -import static org.easymock.EasyMock.verify; +import static org.easymock.EasyMock.*; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; @@ -371,6 +370,7 @@ public class FeaturesServiceTest extends TestBase { expect(bundleContext.getBundles()).andReturn(new Bundle[0]); expect(bundleContext.getBundle()).andReturn(bundle); expect(bundle.adapt(FrameworkStartLevel.class)).andReturn(fsl); + expect(bundleContext.registerService(eq(ResolverHookFactory.class), anyObject(ResolverHookFactory.class), isNull())).andReturn(null); expect(fsl.getInitialBundleStartLevel()).andReturn(50); expect(fsl.getStartLevel()).andReturn(100); replay(bundleContext, bundle, fsl);
