in features/core/src/main/java/org/apache/karaf/features/internal/service/Deployer.java [1173:1296]
private static void computeBundlesToRefresh(Map<Bundle, String> toRefresh, Collection<Bundle> bundles, Map<Resource, Bundle> resources, Map<Resource, List<Wire>> resolution) {
// Compute the new list of fragments
Map<Bundle, Set<Resource>> newFragments = new HashMap<>();
for (Bundle bundle : bundles) {
newFragments.put(bundle, new HashSet<>());
}
if (resolution != null) {
for (Resource res : resolution.keySet()) {
for (Wire wire : resolution.get(res)) {
if (HOST_NAMESPACE.equals(wire.getCapability().getNamespace())) {
Bundle bundle;
if (wire.getProvider() instanceof BundleRevision) {
bundle = ((BundleRevision) wire.getProvider()).getBundle();
} else {
bundle = resources.get(wire.getProvider());
}
if (bundle != null) {
Bundle b = resources.get(wire.getRequirer());
Resource r = b != null ? b.adapt(BundleRevision.class) : wire.getRequirer();
newFragments.get(bundle).add(r);
}
}
}
}
}
// Main loop
int size;
Map<Bundle, Resource> bndToRes = new HashMap<>();
for (Map.Entry<Resource, Bundle> entry : resources.entrySet()) {
bndToRes.put(entry.getValue(), entry.getKey());
}
do {
size = toRefresh.size();
main: for (Bundle bundle : bundles) {
Resource resource = bndToRes.get(bundle);
// This bundle is not managed
if (resource == null) {
resource = bundle.adapt(BundleRevision.class);
}
// Continue if we already know about this bundle
if (toRefresh.containsKey(bundle)) {
continue;
}
// Ignore non resolved bundle
BundleWiring wiring = bundle.adapt(BundleWiring.class);
if (wiring == null) {
continue;
}
// Ignore bundles that won't be wired
List<Wire> newWires = resolution != null ? resolution.get(resource) : null;
if (newWires == null) {
continue;
}
// Check if this bundle is a host and its fragments changed
Set<Resource> oldFragments = new HashSet<>();
for (BundleWire wire : wiring.getProvidedWires(null)) {
if (HOST_NAMESPACE.equals(wire.getCapability().getNamespace())) {
oldFragments.add(wire.getRequirer());
}
}
if (!oldFragments.containsAll(newFragments.get(bundle))) {
toRefresh.put(bundle, "Attached fragments changed: " + new ArrayList<>(newFragments.get(bundle)));
break;
}
// Compare the old and new resolutions
Set<BundleWrapper> wiredBundles = new HashSet<>();
wiredBundles.add(new BundleWrapper(bundle));
for (BundleWire wire : wiring.getRequiredWires(null)) {
BundleRevision rev = wire.getProvider();
Bundle provider = rev.getBundle();
if (toRefresh.containsKey(provider)) {
// The bundle is wired to a bundle being refreshed,
// so we need to refresh it too
toRefresh.put(bundle, "Wired to " + provider.getSymbolicName() + "/" + provider.getVersion() + " which is being refreshed");
continue main;
}
wiredBundles.add(new BundleWrapper(provider));
}
Map<BundleWrapper, Requirement> wiredResources = new HashMap<>();
for (Wire wire : newWires) {
// Handle only packages, hosts, and required bundles
String namespace = wire.getRequirement().getNamespace();
if (!namespace.equals(BundleNamespace.BUNDLE_NAMESPACE)
&& !namespace.equals(PackageNamespace.PACKAGE_NAMESPACE)
&& !namespace.equals(HostNamespace.HOST_NAMESPACE)) {
continue;
}
// Ignore non-resolution time requirements
String effective = wire.getRequirement().getDirectives().get(Namespace.CAPABILITY_EFFECTIVE_DIRECTIVE);
if (effective != null && !Namespace.EFFECTIVE_RESOLVE.equals(effective)) {
continue;
}
// Ignore non bundle resources
if (!isBundle(wire.getProvider())) {
continue;
}
BundleWrapper bw = new BundleWrapper(wire.getProvider());
if (!wiredResources.containsKey(bw)) {
wiredResources.put(bw, wire.getRequirement());
}
}
if (!wiredBundles.containsAll(wiredResources.keySet())) {
Map<BundleWrapper, Requirement> newResources = new HashMap<>(wiredResources);
newResources.keySet().removeAll(wiredBundles);
StringBuilder sb = new StringBuilder();
sb.append("Should be wired to: ");
boolean first = true;
for (Map.Entry<BundleWrapper, Requirement> entry : newResources.entrySet()) {
if (!first) {
sb.append(", ");
} else {
first = false;
}
Requirement req = entry.getValue();
sb.append(entry.getKey());
sb.append(" (through ");
sb.append(req);
sb.append(")");
}
toRefresh.put(bundle, sb.toString());
}
}
} while (toRefresh.size() > size);
}