Return-Path: X-Original-To: apmail-aries-commits-archive@www.apache.org Delivered-To: apmail-aries-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 8DAD6E7B2 for ; Thu, 7 Mar 2013 19:28:43 +0000 (UTC) Received: (qmail 10284 invoked by uid 500); 7 Mar 2013 19:28:43 -0000 Delivered-To: apmail-aries-commits-archive@aries.apache.org Received: (qmail 10235 invoked by uid 500); 7 Mar 2013 19:28:43 -0000 Mailing-List: contact commits-help@aries.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@aries.apache.org Delivered-To: mailing list commits@aries.apache.org Received: (qmail 10219 invoked by uid 99); 7 Mar 2013 19:28:42 -0000 Received: from nike.apache.org (HELO nike.apache.org) (192.87.106.230) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 07 Mar 2013 19:28:42 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=5.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 07 Mar 2013 19:28:38 +0000 Received: from eris.apache.org (localhost [127.0.0.1]) by eris.apache.org (Postfix) with ESMTP id BA61A23888CD; Thu, 7 Mar 2013 19:28:17 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r1454035 - in /aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal: BasicSubsystem.java RegionUpdater.java Date: Thu, 07 Mar 2013 19:28:17 -0000 To: commits@aries.apache.org From: jwross@apache.org X-Mailer: svnmailer-1.0.8-patched Message-Id: <20130307192817.BA61A23888CD@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org 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 bundleIds = newRegion.getBundleIds(); - // Store the current connection info with parent for future reference. - RegionFilterBuilder parentFilter = copiedDigraph.createRegionFilterBuilder(); - for (FilteredRegion filteredRegion : newRegion.getEdges()) { - Map> sharingPolicy = filteredRegion.getFilter().getSharingPolicy(); - for (Map.Entry> 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 childFilters = new HashMap(); - for (Subsystem child : getChildren()) { - if (!((BasicSubsystem)child).isScoped()) - continue; - Region childRegion = ((BasicSubsystem)child).getRegion(); - RegionFilterBuilder childBuilder = copiedDigraph.createRegionFilterBuilder(); - for (FilteredRegion filteredRegion : childRegion.getEdges()) { - Map> sharingPolicy = filteredRegion.getFilter().getSharingPolicy(); - for (Map.Entry> 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 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 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 bundleIds = copyBundleIds(tail); + Map heads = copyHeadRegions(tail, copy); + Map 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 ids, Region region) throws BundleException { + for (Long id : ids) + region.addBundle(id); + } + + private void addHeadRegions(Map heads, Region tail, RegionDigraph digraph) throws BundleException { + for (Map.Entry entry : heads.entrySet()) + tail.connectRegion(digraph.getRegion(entry.getKey()), entry.getValue().build()); + } + + private void addTailRegions(Map tails, Region head, RegionDigraph digraph) throws BundleException { + for (Map.Entry entry : tails.entrySet()) + digraph.getRegion(entry.getKey()).connectRegion(head, entry.getValue().build()); + } + + private void addRequirements(Collection 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 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 copyHeadRegions(Region tail, RegionDigraph digraph) throws InvalidSyntaxException { + Map result = new HashMap(); + 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 copyTailRegions(Region tail, RegionDigraph digraph) throws InvalidSyntaxException { + Map result = new HashMap(); + 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> sharingPolicy, RegionDigraph digraph) throws InvalidSyntaxException { + RegionFilterBuilder result = digraph.createRegionFilterBuilder(); + for (Map.Entry> entry : sharingPolicy.entrySet()) + for (String filter : entry.getValue()) + result.allow(entry.getKey(), filter); + return result; + } +}