You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@aries.apache.org by jw...@apache.org on 2013/03/07 20:28:17 UTC
svn commit: r1454035 - in
/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal:
BasicSubsystem.java RegionUpdater.java
Author: jwross
Date: Thu Mar 7 19:28:17 2013
New Revision: 1454035
URL: http://svn.apache.org/r1454035
Log:
[ARIES-1021] Implementation of AriesSubsystem.addRequirements must not assume the region only has edges to the parent subsystem's region.
All possible edges are now retained.
Added:
aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/RegionUpdater.java
Modified:
aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/BasicSubsystem.java
Modified: aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/BasicSubsystem.java
URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/BasicSubsystem.java?rev=1454035&r1=1454034&r2=1454035&view=diff
==============================================================================
--- aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/BasicSubsystem.java (original)
+++ aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/BasicSubsystem.java Thu Mar 7 19:28:17 2013
@@ -24,13 +24,11 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.EnumSet;
-import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
-import java.util.Set;
import org.apache.aries.subsystem.AriesSubsystem;
import org.apache.aries.subsystem.core.archive.AriesSubsystemParentsHeader;
@@ -42,17 +40,11 @@ import org.apache.aries.subsystem.core.a
import org.apache.aries.util.filesystem.FileSystem;
import org.apache.aries.util.filesystem.IDirectory;
import org.apache.aries.util.io.IOUtils;
-import org.eclipse.equinox.region.Region;
-import org.eclipse.equinox.region.RegionDigraph;
-import org.eclipse.equinox.region.RegionDigraph.FilteredRegion;
-import org.eclipse.equinox.region.RegionFilter;
-import org.eclipse.equinox.region.RegionFilterBuilder;
import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleException;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.Version;
import org.osgi.framework.namespace.IdentityNamespace;
-import org.osgi.namespace.service.ServiceNamespace;
import org.osgi.resource.Capability;
import org.osgi.resource.Requirement;
import org.osgi.resource.Resource;
@@ -551,89 +543,15 @@ public class BasicSubsystem implements R
// The root subsystem has no requirements (there is no parent to import from).
if (isRoot())
throw new UnsupportedOperationException("The root subsystem does not accept additional requirements");
- // Unscoped subsystems import everything.already.
+ // Unscoped subsystems import everything already.
if (!isScoped())
return;
- for (int i = 0; i < 10; i++) {
- try {
- Region oldRegion = getRegion();
- RegionDigraph currentDigraph = oldRegion.getRegionDigraph();
- RegionDigraph copiedDigraph = currentDigraph.copy();
- Region newRegion = copiedDigraph.getRegion(oldRegion.getName());
- // Store the bundle ids for future reference.
- Set<Long> bundleIds = newRegion.getBundleIds();
- // Store the current connection info with parent for future reference.
- RegionFilterBuilder parentFilter = copiedDigraph.createRegionFilterBuilder();
- for (FilteredRegion filteredRegion : newRegion.getEdges()) {
- Map<String, Collection<String>> sharingPolicy = filteredRegion.getFilter().getSharingPolicy();
- for (Map.Entry<String, Collection<String>> entry : sharingPolicy.entrySet())
- for (String filter : entry.getValue())
- parentFilter.allow(entry.getKey(), filter);
- }
- // Add the additional requirements to the connection info with parent.
- for (Requirement requirement : requirements) {
- String namespace = requirement.getNamespace();
- // The osgi.service namespace requires translation.
- if (ServiceNamespace.SERVICE_NAMESPACE.equals(namespace))
- namespace = RegionFilter.VISIBLE_SERVICE_NAMESPACE;
- String filter = requirement.getDirectives().get(IdentityNamespace.REQUIREMENT_FILTER_DIRECTIVE);
- // A null filter means import everything from that namespace.
- if (filter == null)
- parentFilter.allowAll(namespace);
- else
- parentFilter.allow(namespace, filter);
- }
- // Store the connection info with children for future reference.
- Map<String, RegionFilterBuilder> childFilters = new HashMap<String, RegionFilterBuilder>();
- for (Subsystem child : getChildren()) {
- if (!((BasicSubsystem)child).isScoped())
- continue;
- Region childRegion = ((BasicSubsystem)child).getRegion();
- RegionFilterBuilder childBuilder = copiedDigraph.createRegionFilterBuilder();
- for (FilteredRegion filteredRegion : childRegion.getEdges()) {
- Map<String, Collection<String>> sharingPolicy = filteredRegion.getFilter().getSharingPolicy();
- for (Map.Entry<String, Collection<String>> entry : sharingPolicy.entrySet())
- for (String filter : entry.getValue())
- childBuilder.allow(entry.getKey(), filter);
- }
- childFilters.put(childRegion.getName(), childBuilder);
- }
- // Remove the region so the parent connection can be updated.
- copiedDigraph.removeRegion(newRegion);
- // Recreate the region.
- newRegion = copiedDigraph.createRegion(newRegion.getName());
- // Copy the bundle ids.
- for (Long bundleId : bundleIds)
- newRegion.addBundle(bundleId);
- // Reconnect to the parent.
- copiedDigraph.connect(newRegion, parentFilter.build(), copiedDigraph.getRegion(((BasicSubsystem)getParents().iterator().next()).getRegion().getName()));
- // Reconnect the children.
- for (Map.Entry<String, RegionFilterBuilder> entry : childFilters.entrySet())
- copiedDigraph.connect(copiedDigraph.getRegion(entry.getKey()), entry.getValue().build(), newRegion);
- // Replace the current digraph.
- try {
- currentDigraph.replace(copiedDigraph);
- }
- catch (BundleException e) {
- // Something modified digraph since the copy was made.
- if (i < 10)
- // There are more attempts to make.
- continue;
- // Number of attempts has been exhausted.
- throw e;
- }
- // Success! No need to continue looping.
- break;
- }
- // If an exception occurs for any reason other than a replacement
- // failure, or replacement failed with no more attempts left, break
- // out of the loop and throw it.
- catch (SubsystemException e) {
- throw e;
- }
- catch (Exception e) {
- throw new SubsystemException(e);
- }
+ RegionUpdater updater = new RegionUpdater(getRegion(), ((BasicSubsystem)getParents().iterator().next()).getRegion());
+ try {
+ updater.addRequirements(requirements);
+ }
+ catch (Exception e) {
+ throw new SubsystemException(e);
}
}
Added: aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/RegionUpdater.java
URL: http://svn.apache.org/viewvc/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/RegionUpdater.java?rev=1454035&view=auto
==============================================================================
--- aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/RegionUpdater.java (added)
+++ aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/RegionUpdater.java Thu Mar 7 19:28:17 2013
@@ -0,0 +1,139 @@
+package org.apache.aries.subsystem.core.internal;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+import org.eclipse.equinox.region.Region;
+import org.eclipse.equinox.region.RegionDigraph;
+import org.eclipse.equinox.region.RegionDigraph.FilteredRegion;
+import org.eclipse.equinox.region.RegionFilter;
+import org.eclipse.equinox.region.RegionFilterBuilder;
+import org.osgi.framework.BundleException;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.namespace.IdentityNamespace;
+import org.osgi.namespace.service.ServiceNamespace;
+import org.osgi.resource.Requirement;
+
+public class RegionUpdater {
+ public static final int MAX_ATTEMPTS_DEFAULT = 10;
+
+ private final RegionDigraph digraph;
+ private final Region head;
+ private final Region tail;
+
+ public RegionUpdater(Region tail, Region head) {
+ if (tail == null)
+ throw new NullPointerException("Missing required parameter: tail");
+ if (head == null)
+ throw new NullPointerException("Missing required parameter: head");
+ this.tail = tail;
+ this.head = head;
+ digraph = tail.getRegionDigraph();
+ }
+
+ public void addRequirements(Collection<? extends Requirement> requirements) throws BundleException, InvalidSyntaxException {
+ for (int i = 0; i < MAX_ATTEMPTS_DEFAULT; i++) {
+ RegionDigraph copy = copyDigraph();
+ Region tail = copyTail(copy);
+ Region head = copyHead(copy);
+ Set<Long> bundleIds = copyBundleIds(tail);
+ Map<String, RegionFilterBuilder> heads = copyHeadRegions(tail, copy);
+ Map<String, RegionFilterBuilder> tails = copyTailRegions(tail, copy);
+ copy.removeRegion(tail);
+ tail = copy.createRegion(tail.getName());
+ addBundleIds(bundleIds, tail);
+ addRequirements(requirements, heads.get(head.getName()));
+ addHeadRegions(heads, tail, copy);
+ addTailRegions(tails, tail, copy);
+ // Replace the current digraph.
+ try {
+ digraph.replace(copy);
+ }
+ catch (BundleException e) {
+ // Something modified digraph since the copy was made.
+ if (i < MAX_ATTEMPTS_DEFAULT)
+ // There are more attempts to make.
+ continue;
+ // Number of attempts has been exhausted.
+ throw e;
+ }
+ // Success! No need to continue looping.
+ break;
+ }
+ }
+
+ private void addBundleIds(Set<Long> ids, Region region) throws BundleException {
+ for (Long id : ids)
+ region.addBundle(id);
+ }
+
+ private void addHeadRegions(Map<String, RegionFilterBuilder> heads, Region tail, RegionDigraph digraph) throws BundleException {
+ for (Map.Entry<String, RegionFilterBuilder> entry : heads.entrySet())
+ tail.connectRegion(digraph.getRegion(entry.getKey()), entry.getValue().build());
+ }
+
+ private void addTailRegions(Map<String, RegionFilterBuilder> tails, Region head, RegionDigraph digraph) throws BundleException {
+ for (Map.Entry<String, RegionFilterBuilder> entry : tails.entrySet())
+ digraph.getRegion(entry.getKey()).connectRegion(head, entry.getValue().build());
+ }
+
+ private void addRequirements(Collection<? extends Requirement> requirements, RegionFilterBuilder builder) throws InvalidSyntaxException {
+ for (Requirement requirement : requirements) {
+ String namespace = requirement.getNamespace();
+ // The osgi.service namespace requires translation.
+ if (ServiceNamespace.SERVICE_NAMESPACE.equals(namespace))
+ namespace = RegionFilter.VISIBLE_SERVICE_NAMESPACE;
+ String filter = requirement.getDirectives().get(IdentityNamespace.REQUIREMENT_FILTER_DIRECTIVE);
+ // A null filter means import everything from that namespace.
+ if (filter == null)
+ builder.allowAll(namespace);
+ else
+ builder.allow(namespace, filter);
+ }
+ }
+
+ private Set<Long> copyBundleIds(Region region) {
+ return region.getBundleIds();
+ }
+
+ private RegionDigraph copyDigraph() throws BundleException {
+ return digraph.copy();
+ }
+
+ private Region copyHead(RegionDigraph digraph) {
+ return digraph.getRegion(head.getName());
+ }
+
+ private Map<String, RegionFilterBuilder> copyHeadRegions(Region tail, RegionDigraph digraph) throws InvalidSyntaxException {
+ Map<String, RegionFilterBuilder> result = new HashMap<String, RegionFilterBuilder>();
+ for (FilteredRegion edge : tail.getEdges())
+ result.put(edge.getRegion().getName(), createRegionFilterBuilder(edge.getFilter().getSharingPolicy(), digraph));
+ return result;
+ }
+
+ private Region copyTail(RegionDigraph digraph) {
+ return digraph.getRegion(tail.getName());
+ }
+
+ private Map<String, RegionFilterBuilder> copyTailRegions(Region tail, RegionDigraph digraph) throws InvalidSyntaxException {
+ Map<String, RegionFilterBuilder> result = new HashMap<String, RegionFilterBuilder>();
+ for (Region head : digraph.getRegions()) {
+ if (head.equals(tail))
+ continue;
+ for (FilteredRegion edge : head.getEdges())
+ if (edge.getRegion().equals(tail))
+ result.put(head.getName(), createRegionFilterBuilder(edge.getFilter().getSharingPolicy(), digraph));
+ }
+ return result;
+ }
+
+ private RegionFilterBuilder createRegionFilterBuilder(Map<String, Collection<String>> sharingPolicy, RegionDigraph digraph) throws InvalidSyntaxException {
+ RegionFilterBuilder result = digraph.createRegionFilterBuilder();
+ for (Map.Entry<String, Collection<String>> entry : sharingPolicy.entrySet())
+ for (String filter : entry.getValue())
+ result.allow(entry.getKey(), filter);
+ return result;
+ }
+}