You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@karaf.apache.org by gn...@apache.org on 2014/04/22 14:32:23 UTC
[5/6] git commit: [KARAF-2923] Support for user installed bundles in
any region
[KARAF-2923] Support for user installed bundles in any region
Project: http://git-wip-us.apache.org/repos/asf/karaf/repo
Commit: http://git-wip-us.apache.org/repos/asf/karaf/commit/1b1b6760
Tree: http://git-wip-us.apache.org/repos/asf/karaf/tree/1b1b6760
Diff: http://git-wip-us.apache.org/repos/asf/karaf/diff/1b1b6760
Branch: refs/heads/master
Commit: 1b1b6760bd73f42bd77cb58fb56f05fc6aa1cc77
Parents: fabd10e
Author: Guillaume Nodet <gn...@gmail.com>
Authored: Tue Apr 22 14:30:20 2014 +0200
Committer: Guillaume Nodet <gn...@gmail.com>
Committed: Tue Apr 22 14:31:49 2014 +0200
----------------------------------------------------------------------
.../internal/region/SubsystemResolver.java | 56 ++++++-
.../internal/service/FeaturesServiceImpl.java | 155 ++++++++++++-------
2 files changed, 152 insertions(+), 59 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/karaf/blob/1b1b6760/features/core/src/main/java/org/apache/karaf/features/internal/region/SubsystemResolver.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/region/SubsystemResolver.java b/features/core/src/main/java/org/apache/karaf/features/internal/region/SubsystemResolver.java
index 6387023..190a67d 100644
--- a/features/core/src/main/java/org/apache/karaf/features/internal/region/SubsystemResolver.java
+++ b/features/core/src/main/java/org/apache/karaf/features/internal/region/SubsystemResolver.java
@@ -41,6 +41,7 @@ import org.eclipse.equinox.region.RegionDigraph;
import org.eclipse.equinox.region.RegionFilterBuilder;
import org.osgi.framework.BundleException;
import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.wiring.BundleRevision;
import org.osgi.resource.Capability;
import org.osgi.resource.Requirement;
import org.osgi.resource.Resource;
@@ -77,7 +78,7 @@ public class SubsystemResolver {
public Map<Resource, List<Wire>> resolve(
List<Repository> repositories,
Map<String, Set<String>> features,
- Collection<? extends Resource> system,
+ Map<String, Set<BundleRevision>> system,
Set<String> overrides,
String featureResolutionRange
) throws Exception {
@@ -117,8 +118,22 @@ public class SubsystemResolver {
root.preResolve(allFeatures, manager, overrides, featureResolutionRange);
// Add system resources
- for (Resource res : system) {
- root.addSystemResource(res);
+ for (Map.Entry<String, Set<BundleRevision>> entry : system.entrySet()) {
+ Subsystem ss = null;
+ String[] parts = entry.getKey().split("/");
+ String path = parts[0];
+ if (path.equals(root.getName())) {
+ ss = root;
+ }
+ for (int i = 1; ss != null && i < parts.length; i++) {
+ path += "/" + parts[i];
+ ss = ss.getChild(path);
+ }
+ if (ss != null) {
+ for (Resource res : entry.getValue()) {
+ ss.addSystemResource(res);
+ }
+ }
}
// Populate digraph and resolve
@@ -147,6 +162,41 @@ public class SubsystemResolver {
return wiring;
}
+ public RegionDigraph getFlatDigraph() throws BundleException, InvalidSyntaxException {
+ RegionDigraph clone = this.digraph.copy();
+ RegionDigraph computedDigraph = digraph;
+ for (Region r : clone.getRegions()) {
+ clone.removeRegion(r);
+ }
+ Map<String, String> flats = getFlatSubsystemsMap();
+ for (Region r : computedDigraph.getRegions()) {
+ if (r.getName().equals(flats.get(r.getName()))) {
+ clone.createRegion(r.getName());
+ }
+ }
+ for (Region r : computedDigraph.getRegions()) {
+ for (RegionDigraph.FilteredRegion fr : computedDigraph.getEdges(r)) {
+ String rt = flats.get(r.getName());
+ String rh = flats.get(fr.getRegion().getName());
+ if (!rh.equals(rt)) {
+ Region tail = clone.getRegion(rt);
+ Region head = clone.getRegion(rh);
+ RegionFilterBuilder rfb = clone.createRegionFilterBuilder();
+ for (Map.Entry<String, Collection<String>> entry : fr.getFilter().getSharingPolicy().entrySet()) {
+ // Discard osgi.identity namespace
+ if (!IDENTITY_NAMESPACE.equals(entry.getKey())) {
+ for (String f : entry.getValue()) {
+ rfb.allow(entry.getKey(), f);
+ }
+ }
+ }
+ clone.connect(tail, rfb.build(), head);
+ }
+ }
+ }
+ return clone;
+ }
+
public Map<String, String> getFlatSubsystemsMap() {
Map<String, String> toFlatten = new HashMap<String, String>();
findSubsystemsToFlatten(root, toFlatten);
http://git-wip-us.apache.org/repos/asf/karaf/blob/1b1b6760/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 b7b3d13..d228632 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
@@ -811,27 +811,49 @@ public class FeaturesServiceImpl implements FeaturesService {
boolean simulate = options.contains(Option.Simulate);
Map<String, Set<String>> installed = state.installedFeatures;
- Map<String, Set<Long>> managed = state.managedBundles;
+ Map<String, Set<Long>> managed = copyMapSet(state.managedBundles);
- // Get a list of resolved and unmanaged bundles to use as capabilities during resolution
- List<BundleRevision> systemBundles = new ArrayList<BundleRevision>();
Bundle[] bundles = systemBundleContext.getBundles();
- for (Bundle bundle : bundles) {
- if (bundle.getState() >= Bundle.RESOLVED) {
- boolean bm = false;
- for (Set<Long> m : managed.values()) {
- bm |= m.contains(bundle.getBundleId());
+
+ // Get a map of unmanaged bundles to use as capabilities during resolution
+ Map<String, Set<BundleRevision>> unmanagedBundles = new HashMap<String, Set<BundleRevision>>();
+ Map<String, Map<String, Map<String, Set<String>>>> policies = new HashMap<String, Map<String, Map<String, Set<String>>>>();
+ {
+ RegionDigraph clone = digraph.copy();
+ for (Region region : clone.getRegions()) {
+ // Get bundles
+ Set<Long> ids = new HashSet<Long>(region.getBundleIds());
+ if (managed.containsKey(region.getName())) {
+ ids.removeAll(managed.get(region.getName()));
}
- if (!bm) {
- BundleRevision res = bundle.adapt(BundleRevision.class);
- systemBundles.add(res);
+ if (!ids.isEmpty()) {
+ Set<BundleRevision> revs = new HashSet<BundleRevision>();
+ for (Bundle bundle : bundles) {
+ if (ids.contains(bundle.getBundleId())) {
+ revs.add(bundle.adapt(BundleRevision.class));
+ }
+ }
+ unmanagedBundles.put(region.getName(), revs);
+ }
+ // Get policies
+ Map<String, Map<String, Set<String>>> edges = new HashMap<String, Map<String, Set<String>>>();
+ for (RegionDigraph.FilteredRegion fr : clone.getEdges(region)) {
+ Map<String, Set<String>> policy = new HashMap<String, Set<String>>();
+ Map<String, Collection<String>> current = fr.getFilter().getSharingPolicy();
+ for (String ns : current.keySet()) {
+ for (String f : current.get(ns)) {
+ addToMapSet(policy, ns, f);
+ }
+ }
+ edges.put(fr.getRegion().getName(), policy);
}
+ policies.put(region.getName(), edges);
}
}
+
// Resolve
// TODO: requirements
// TODO: bundles
- Set<String> overrides = Overrides.loadOverrides(this.overrides);
Repository[] repositories = listRepositories();
if (!installed.containsKey(ROOT_REGION)) {
@@ -842,8 +864,8 @@ public class FeaturesServiceImpl implements FeaturesService {
Map<Resource, List<Wire>> resolution = resolver.resolve(
Arrays.asList(repositories),
features,
- systemBundles,
- overrides,
+ unmanagedBundles,
+ Overrides.loadOverrides(this.overrides),
featureResolutionRange);
Collection<Resource> allResources = resolution.keySet();
Map<String, StreamProvider> providers = resolver.getProviders();
@@ -1043,54 +1065,75 @@ public class FeaturesServiceImpl implements FeaturesService {
//
// Update regions
//
- // TODO: this replace the whole digraph with the computed one
- // TODO: we need to be smarter and allow user modifications or
- // TODO: externally managed regions such as the one managed
- // TODO: by aries subsystems
- RegionDigraph clone = this.digraph.copy();
- RegionDigraph computedDigraph = resolver.getDigraph();
- for (Region r : clone.getRegions()) {
- clone.removeRegion(r);
- }
- Map<String, String> flats = resolver.getFlatSubsystemsMap();
- for (Region r : computedDigraph.getRegions()) {
- if (r.getName().equals(flats.get(r.getName()))) {
- clone.createRegion(r.getName());
- }
- }
- for (Region r : computedDigraph.getRegions()) {
- for (RegionDigraph.FilteredRegion fr : computedDigraph.getEdges(r)) {
- String rt = flats.get(r.getName());
- String rh = flats.get(fr.getRegion().getName());
- if (!rh.equals(rt)) {
- Region tail = clone.getRegion(rt);
- Region head = clone.getRegion(rh);
- RegionFilterBuilder rfb = clone.createRegionFilterBuilder();
- for (Map.Entry<String, Collection<String>> entry : fr.getFilter().getSharingPolicy().entrySet()) {
- // Discard osgi.identity namespace
- if (!IdentityNamespace.IDENTITY_NAMESPACE.equals(entry.getKey())) {
- for (String f : entry.getValue()) {
- rfb.allow(entry.getKey(), f);
- }
+ {
+ RegionDigraph clone = digraph.copy();
+ RegionDigraph computedDigraph = resolver.getFlatDigraph();
+ // Iterate through previously managed regions and
+ // delete those that do not contain any bundles anymore
+ for (String name : state.managedBundles.keySet()) {
+ if (!managed.containsKey(name) && !unmanagedBundles.containsKey(name)) {
+ policies.remove(name);
+ }
+ }
+ // Fix broken filters
+ for (String name : policies.keySet()) {
+ policies.get(name).keySet().retainAll(policies.keySet());
+ }
+ // Update managed regions
+ for (Region computedRegion : computedDigraph.getRegions()) {
+ String name = computedRegion.getName();
+ Map<String, Map<String, Set<String>>> policy = policies.get(name);
+ if (policy == null) {
+ policy = new HashMap<String, Map<String, Set<String>>>();
+ policies.put(name, policy);
+ }
+ for (RegionDigraph.FilteredRegion fr : computedDigraph.getEdges(computedRegion)) {
+ String r2 = fr.getRegion().getName();
+ Map<String, Set<String>> filters = new HashMap<String, Set<String>>();
+ Map<String, Collection<String>> current = fr.getFilter().getSharingPolicy();
+ for (String ns : current.keySet()) {
+ for (String f : current.get(ns)) {
+ addToMapSet(filters, ns, f);
}
}
- clone.connect(tail, rfb.build(), head);
+ policy.put(r2, filters);
}
}
- }
- // Spread bundles across regions
- Region root = clone.getRegion(ROOT_REGION);
- for (BundleRevision revision : systemBundles) {
- root.addBundle(revision.getBundle());
- }
- for (Resource resource : resources.keySet()) {
- Bundle bundle = deployment.resToBnd.get(resource);
- if (bundle != null) {
- String region = resources.get(resource);
- clone.getRegion(region).addBundle(bundle);
+ // Apply all changes
+ for (Region region : clone.getRegions()) {
+ clone.removeRegion(region);
}
+ for (String name : policies.keySet()) {
+ clone.createRegion(name);
+ }
+ for (String r1Name : policies.keySet()) {
+ Region r1 = clone.getRegion(r1Name);
+ Map<String, Map<String, Set<String>>> policy = policies.get(r1Name);
+ for (String r2Name : policy.keySet()) {
+ Region r2 = clone.getRegion(r2Name);
+ RegionFilterBuilder rfb = clone.createRegionFilterBuilder();
+ for (String ns : policy.get(r2Name).keySet()) {
+ for (String f : policy.get(r2Name).get(ns)) {
+ rfb.allow(ns, f);
+ }
+ }
+ clone.connect(r1, rfb.build(), r2);
+ }
+ // Dispatch bundles
+ if (unmanagedBundles.containsKey(r1Name)) {
+ for (BundleRevision rev : unmanagedBundles.get(r1Name)) {
+ r1.addBundle(rev.getBundle());
+ }
+ }
+ if (managed.containsKey(r1Name)) {
+ for (long id : managed.get(r1Name)) {
+ r1.addBundle(id);
+ }
+ }
+ }
+ this.digraph.replace(clone);
}
- this.digraph.replace(clone);
+
//
// Update bundles