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 6fabb39..59ebb85 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 @@ -16,6 +16,12 @@ */ package org.apache.karaf.features.internal.service; +import static org.apache.karaf.features.internal.service.StateStorage.toStringStringSetMap; +import static org.apache.karaf.features.internal.util.MapUtils.add; +import static org.apache.karaf.features.internal.util.MapUtils.addToMapSet; +import static org.apache.karaf.features.internal.util.MapUtils.copy; +import static org.apache.karaf.features.internal.util.MapUtils.remove; + import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; @@ -41,6 +47,7 @@ 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; @@ -100,12 +107,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import static org.apache.karaf.features.internal.service.StateStorage.toStringStringSetMap; -import static org.apache.karaf.features.internal.util.MapUtils.add; -import static org.apache.karaf.features.internal.util.MapUtils.addToMapSet; -import static org.apache.karaf.features.internal.util.MapUtils.copy; -import static org.apache.karaf.features.internal.util.MapUtils.remove; - /** * */ @@ -191,6 +192,9 @@ private final ExecutorService executor; private Map> featureCache; + private Map hooks = new ConcurrentHashMap<>(); + private ServiceRegistration hookRegistration; + public FeaturesServiceImpl(Bundle bundle, BundleContext bundleContext, BundleContext systemBundleContext, @@ -258,12 +262,25 @@ 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 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"}) @@ -1385,10 +1402,21 @@ } Bundle sourceBundle = requirement.getRevision().getBundle(); Resource sourceResource = bndToRes.get(sourceBundle); + + if (sourceResource == null) { + return; + } + + List wires = wiring.get(sourceResource); + if (wires == null) { + return; + } + Set 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())) { @@ -1412,20 +1440,17 @@ } @Override public void end() { + } }; - ResolverHookFactory factory = new ResolverHookFactory() { - @Override - public ResolverHook begin(Collection triggers) { - return hook; - } - }; - ServiceRegistration 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, hook); } } 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..aa47ce5 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,12 +39,17 @@ import org.junit.Test; import org.osgi.framework.Bundle; import org.osgi.framework.BundleContext; +import org.osgi.framework.hooks.resolver.ResolverHook; +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.anyObject; +import static org.easymock.EasyMock.eq; import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.isNull; import static org.easymock.EasyMock.replay; import static org.easymock.EasyMock.verify; import static org.junit.Assert.assertEquals; @@ -373,6 +378,7 @@ expect(bundle.adapt(FrameworkStartLevel.class)).andReturn(fsl); expect(fsl.getInitialBundleStartLevel()).andReturn(50); expect(fsl.getStartLevel()).andReturn(100); + expect(bundleContext.registerService(eq(ResolverHookFactory.class), anyObject(ResolverHookFactory.class), isNull())).andReturn(null); replay(bundleContext, bundle, fsl); FeaturesServiceImpl svc = new FeaturesServiceImpl(null, null, bundleContext, new Storage(), null, null, null, resolver, null, null, null, null, null, null, null, 0, 0, 0, null);