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