Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Watson2011-03-11 12:08:34 -0500
committerGlyn Normington2011-03-11 12:08:34 -0500
commitc3f2e24e84254d1aab05e803b2d78fa1c425216e (patch)
treec9048526994edcb09f2eed3c5cc69428aa12e492
parentffc74a06b046ea080223f88b502b887f9581afc6 (diff)
parent8f662da298766ba663140514fcd177af1c2098a5 (diff)
downloadorg.eclipse.virgo.kernel-c3f2e24e84254d1aab05e803b2d78fa1c425216e.tar.gz
org.eclipse.virgo.kernel-c3f2e24e84254d1aab05e803b2d78fa1c425216e.tar.xz
org.eclipse.virgo.kernel-c3f2e24e84254d1aab05e803b2d78fa1c425216e.zip
Merge branch 'master' into region_api
Conflicts: org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/hook/RegionBundleFindHook.java org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/hook/RegionResolverHook.java org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/hook/RegionServiceFindHook.java org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/internal/StandardRegionDigraph.java
-rw-r--r--org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/Region.java15
-rw-r--r--org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/RegionDigraph.java8
-rw-r--r--org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/RegionDigraphVisitor.java50
-rw-r--r--org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/RegionManager.java1
-rw-r--r--org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/hook/RegionBundleFindHook.java72
-rw-r--r--org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/hook/RegionDigraphVisitorBase.java141
-rw-r--r--org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/hook/RegionResolverHook.java73
-rw-r--r--org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/hook/RegionServiceEventHook.java1
-rw-r--r--org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/hook/RegionServiceFindHook.java65
-rw-r--r--org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/internal/BundleIdBasedRegion.java10
-rw-r--r--org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/internal/StandardRegionDigraph.java12
-rw-r--r--org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/internal/SubgraphTraverser.java63
-rw-r--r--org.eclipse.virgo.kernel.osgi/src/test/java/org/eclipse/virgo/kernel/osgi/region/hook/RegionServiceEventHookTests.java1
13 files changed, 357 insertions, 155 deletions
diff --git a/org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/Region.java b/org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/Region.java
index 0a3323bd..88fc7f51 100644
--- a/org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/Region.java
+++ b/org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/Region.java
@@ -141,8 +141,8 @@ public interface Region {
Bundle getBundle(String symbolicName, Version version);
/**
- * Connects this region to the given tail region and associates the given {@link RegionFilter} with the connection.
- * This region may then, subject to the region filter, see bundles, packages, and services visible in the tail
+ * Connects this region to the given head region and associates the given {@link RegionFilter} with the connection.
+ * This region may then, subject to the region filter, see bundles, packages, and services visible in the head
* region.
* <p>
* If the filter allows the same bundle symbolic name and version as a bundle already present in this region or a
@@ -152,11 +152,11 @@ public interface Region {
* If the given source region is already connected to the given tail region, then BundleException with exception
* type UNSUPPORTED_OPERATION is thrown.
*
- * @param tailRegion the region to connect this region to
+ * @param headRegion the region to connect this region to
* @param filter a {@link RegionFilter} which controls what is visible across the connection
* @throws BundleException if the connection was not created
*/
- void connectRegion(Region tailRegion, RegionFilter filter) throws BundleException;
+ void connectRegion(Region headRegion, RegionFilter filter) throws BundleException;
/**
* Removes the given bundle from this region. If the given bundle does not belong to this region, this is not an
@@ -181,5 +181,12 @@ public interface Region {
* @return a {@link Set} of {@link FilteredRegion FilteredRegions} of head regions and region filters
*/
Set<FilteredRegion> getEdges();
+
+ /**
+ * Visit the subgraph connected to this region.
+ *
+ * @param visitor a {@link RegionDigraphVisitor} to be called as the subgraph is navigated
+ */
+ void visitSubgraph(RegionDigraphVisitor visitor);
}
diff --git a/org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/RegionDigraph.java b/org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/RegionDigraph.java
index d0f0d562..77ccc199 100644
--- a/org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/RegionDigraph.java
+++ b/org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/RegionDigraph.java
@@ -140,5 +140,13 @@ public interface RegionDigraph extends Iterable<Region> {
* @return a {@link Set} of {@link FilteredRegion FilteredRegions} of head regions and region filters
*/
Set<FilteredRegion> getEdges(Region tailRegion);
+
+ /**
+ * Visit the subgraph connected to the given region.
+ *
+ * @param startingRegion the region at which to start
+ * @param visitor a {@link RegionDigraphVisitor} to be called as the subgraph is navigated
+ */
+ void visitSubgraph(Region startingRegion, RegionDigraphVisitor visitor);
}
diff --git a/org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/RegionDigraphVisitor.java b/org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/RegionDigraphVisitor.java
new file mode 100644
index 00000000..ae486d96
--- /dev/null
+++ b/org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/RegionDigraphVisitor.java
@@ -0,0 +1,50 @@
+/*******************************************************************************
+ * This file is part of the Virgo Web Server.
+ *
+ * Copyright (c) 2011 VMware Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * SpringSource, a division of VMware - initial API and implementation and/or initial documentation
+ *******************************************************************************/
+
+package org.eclipse.virgo.kernel.osgi.region;
+
+/**
+ * {@link RegionDigraphVisitor} is used to traverse a subgraph of a {@link RegionDigraph}.
+ * <p />
+ *
+ * <strong>Concurrent Semantics</strong><br />
+ *
+ * Implementations of this interface must be thread safe.
+ */
+public interface RegionDigraphVisitor {
+
+ /**
+ * Visits the given region and determines whether or not to continue traversing.
+ *
+ * @param region the region to visit
+ * @return <code>true</code> if the traversal is to continue and <code>false</code> otherwise
+ */
+ boolean visit(Region region);
+
+ /**
+ * Prepares to traverse an edge with the given {@link RegionFilter} and determines whether or not to traverse the
+ * edge.
+ *
+ * @param regionFilter the {@link RegionFilter} of the edge to be traversed
+ * @return <code>true</code> if the edge is to be traversed and <code>false</code> otherwise
+ */
+ boolean preEdgeTraverse(RegionFilter regionFilter);
+
+ /**
+ * This is called after traversing an edge with the given {@link RegionFilter}.
+ *
+ * @param regionFilter the {@link RegionFilter} of the edge that has just been traversed
+ */
+ void postEdgeTraverse(RegionFilter regionFilter);
+
+} \ No newline at end of file
diff --git a/org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/RegionManager.java b/org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/RegionManager.java
index 25ac96ba..52257f42 100644
--- a/org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/RegionManager.java
+++ b/org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/RegionManager.java
@@ -113,6 +113,7 @@ final class RegionManager {
this.tracker.track(this.bundleContext.registerService(org.osgi.framework.hooks.service.FindHook.class, serviceFindHook, null));
}
+ @SuppressWarnings("deprecation")
private void registerServiceEventHook(org.osgi.framework.hooks.service.EventHook serviceEventHook) {
this.tracker.track(this.bundleContext.registerService(org.osgi.framework.hooks.service.EventHook.class, serviceEventHook, null));
}
diff --git a/org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/hook/RegionBundleFindHook.java b/org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/hook/RegionBundleFindHook.java
index fcaa38a8..4f3aee4e 100644
--- a/org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/hook/RegionBundleFindHook.java
+++ b/org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/hook/RegionBundleFindHook.java
@@ -11,23 +11,14 @@
package org.eclipse.virgo.kernel.osgi.region.hook;
-import java.util.AbstractMap;
-import java.util.AbstractSet;
-import java.util.ArrayList;
import java.util.Collection;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
import java.util.Set;
import org.eclipse.virgo.kernel.osgi.region.Region;
import org.eclipse.virgo.kernel.osgi.region.RegionDigraph;
-import org.eclipse.virgo.kernel.osgi.region.RegionDigraph.FilteredRegion;
import org.eclipse.virgo.kernel.osgi.region.RegionFilter;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
-import org.osgi.framework.Version;
import org.osgi.framework.hooks.bundle.FindHook;
/**
@@ -60,61 +51,38 @@ public final class RegionBundleFindHook implements FindHook {
return;
}
- Set<Bundle> allowed = getAllowed(finderRegion, bundles, new HashSet<Region>());
+ Visitor visitor = new Visitor(bundles);
+ finderRegion.visitSubgraph(visitor);
+ Set<Bundle> allowed = visitor.getAllowed();
bundles.retainAll(allowed);
}
- private Set<Bundle> getAllowed(Region r, Collection<Bundle> bundles, Set<Region> path) {
- Set<Bundle> allowed = new HashSet<Bundle>();
-
- if (!path.contains(r)) {
- allowBundlesInRegion(allowed, r, bundles);
- allowImportedBundles(allowed, r, bundles, path);
- }
-
- return allowed;
- }
+ private class Visitor extends RegionDigraphVisitorBase<Bundle> {
- private void allowImportedBundles(Set<Bundle> allowed, Region r, Collection<Bundle> bundles, Set<Region> path) {
- for (FilteredRegion fr : this.regionDigraph.getEdges(r)) {
- Set<Bundle> a = getAllowed(fr.getRegion(), bundles, extendPath(r, path));
- filter(a, fr.getFilter());
- allowed.addAll(a);
+ private Visitor(Collection<Bundle> candidates) {
+ super(candidates);
}
- }
- private void allowBundlesInRegion(Set<Bundle> allowed, Region r, Collection<Bundle> bundles) {
- for (Bundle b : bundles) {
- if (r.contains(b)) {
- allowed.add(b);
- }
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected boolean contains(Region region, Bundle candidate) {
+ return region.contains(candidate);
}
- }
- private Set<Region> extendPath(Region r, Set<Region> path) {
- Set<Region> newPath = new HashSet<Region>(path);
- newPath.add(r);
- return newPath;
- }
-
- private void filter(Set<Bundle> bundles, RegionFilter filter) {
- Iterator<Bundle> i = bundles.iterator();
- while (i.hasNext()) {
- Bundle b = i.next();
- if (!filter.isBundleAllowed(b)) {
- i.remove();
- }
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected boolean isAllowed(Bundle candidate, RegionFilter filter) {
+ return filter.isBundleAllowed(candidate);
}
+
}
private Region getRegion(BundleContext context) {
- Bundle b = context.getBundle();
- for (Region r : this.regionDigraph) {
- if (r.contains(b)) {
- return r;
- }
- }
- return null;
+ return this.regionDigraph.getRegion(context.getBundle());
}
}
diff --git a/org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/hook/RegionDigraphVisitorBase.java b/org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/hook/RegionDigraphVisitorBase.java
new file mode 100644
index 00000000..84b8b7ff
--- /dev/null
+++ b/org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/hook/RegionDigraphVisitorBase.java
@@ -0,0 +1,141 @@
+/*******************************************************************************
+ * This file is part of the Virgo Web Server.
+ *
+ * Copyright (c) 2011 VMware Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * SpringSource, a division of VMware - initial API and implementation and/or initial documentation
+ *******************************************************************************/
+
+package org.eclipse.virgo.kernel.osgi.region.hook;
+
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+import java.util.Stack;
+
+import org.eclipse.virgo.kernel.osgi.region.Region;
+import org.eclipse.virgo.kernel.osgi.region.RegionDigraphVisitor;
+import org.eclipse.virgo.kernel.osgi.region.RegionFilter;
+
+/**
+ * {@link RegionDigraphVisitorBase} is an abstract base class for {@link RegionDigraphVisitor} implementations in the
+ * framework hooks.
+ * <p />
+ *
+ * <strong>Concurrent Semantics</strong><br />
+ * This class is thread safe.
+ */
+abstract class RegionDigraphVisitorBase<C> implements RegionDigraphVisitor {
+
+ private final Collection<C> allCandidates;
+
+ private final Stack<Set<C>> allowedStack = new Stack<Set<C>>();
+
+ private Object monitor = new Object();
+
+ private Set<C> allowed;
+
+ protected RegionDigraphVisitorBase(Collection<C> candidates) {
+ this.allCandidates = candidates;
+ synchronized (this.monitor) {
+ this.allowed = new HashSet<C>();
+ }
+ }
+
+ Set<C> getAllowed() {
+ synchronized (this.monitor) {
+ return this.allowed;
+ }
+ }
+
+ private void allow(C candidate) {
+ synchronized (this.monitor) {
+ this.allowed.add(candidate);
+ }
+ }
+
+ private void allow(Set<C> candidates) {
+ synchronized (this.monitor) {
+ this.allowed.addAll(candidates);
+ }
+ }
+
+ private void pushAllowed() {
+ synchronized (this.monitor) {
+ this.allowedStack.push(this.allowed);
+ this.allowed = new HashSet<C>();
+ }
+ }
+
+ private Set<C> popAllowed() {
+ synchronized (this.monitor) {
+ Set<C> a = this.allowed;
+ this.allowed = this.allowedStack.pop();
+ return a;
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean visit(Region region) {
+ for (C candidate : this.allCandidates) {
+ if (contains(region, candidate)) {
+ allow(candidate);
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Determines whether the given region contains the given candidate.
+ *
+ * @param region the {@link Region}
+ * @param candidate the candidate
+ * @return <code>true</code> if and only if the given region contains the given candidate
+ */
+ protected abstract boolean contains(Region region, C candidate);
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean preEdgeTraverse(RegionFilter regionFilter) {
+ pushAllowed();
+ return true;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void postEdgeTraverse(RegionFilter regionFilter) {
+ Set<C> candidates = popAllowed();
+ filter(candidates, regionFilter);
+ allow(candidates);
+ }
+
+ private void filter(Set<C> candidates, RegionFilter filter) {
+ Iterator<C> i = candidates.iterator();
+ while (i.hasNext()) {
+ C candidate = i.next();
+ if (!isAllowed(candidate, filter)) {
+ i.remove();
+ }
+ }
+ }
+
+ /**
+ * Determines whether the given candidate is allowed by the given {@link RegionFilter}.
+ *
+ * @param candidate the candidate
+ * @param filter the filter
+ * @return <code>true</code> if and only if the given candidate is allowed by the given filter
+ */
+ protected abstract boolean isAllowed(C candidate, RegionFilter filter);
+
+} \ No newline at end of file
diff --git a/org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/hook/RegionResolverHook.java b/org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/hook/RegionResolverHook.java
index c915c1d7..d868f687 100644
--- a/org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/hook/RegionResolverHook.java
+++ b/org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/hook/RegionResolverHook.java
@@ -12,14 +12,12 @@
package org.eclipse.virgo.kernel.osgi.region.hook;
import java.util.Collection;
-import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import org.eclipse.osgi.service.resolver.BundleDescription;
import org.eclipse.virgo.kernel.osgi.region.Region;
import org.eclipse.virgo.kernel.osgi.region.RegionDigraph;
-import org.eclipse.virgo.kernel.osgi.region.RegionDigraph.FilteredRegion;
import org.eclipse.virgo.kernel.osgi.region.RegionFilter;
import org.eclipse.virgo.kernel.serviceability.Assert;
import org.osgi.framework.Bundle;
@@ -65,7 +63,9 @@ final class RegionResolverHook implements ResolverHook {
return;
}
- Set<BundleCapability> allowed = getAllowed(requirerRegion, candidates, new HashSet<Region>());
+ Visitor visitor = new Visitor(candidates);
+ requirerRegion.visitSubgraph(visitor);
+ Set<BundleCapability> allowed = visitor.getAllowed();
candidates.retainAll(allowed);
} finally {
@@ -75,6 +75,24 @@ final class RegionResolverHook implements ResolverHook {
}
}
+ private class Visitor extends RegionDigraphVisitorBase<BundleCapability> {
+
+ private Visitor(Collection<BundleCapability> candidates) {
+ super(candidates);
+ }
+
+ @Override
+ protected boolean contains(Region region, BundleCapability candidate) {
+ return region.equals(getRegion(candidate.getRevision()));
+ }
+
+ @Override
+ protected boolean isAllowed(BundleCapability candidate, RegionFilter filter) {
+ return filter.isCapabilityAllowed(candidate) || filter.isBundleAllowed(candidate.getRevision());
+ }
+
+ }
+
private Region getRegion(BundleRevision bundleRevision) {
Bundle bundle = bundleRevision.getBundle();
if (bundle != null) {
@@ -102,55 +120,8 @@ final class RegionResolverHook implements ResolverHook {
return INVALID_BUNDLE_ID;
}
- private Set<BundleCapability> getAllowed(Region r, Collection<BundleCapability> candidates, Set<Region> path) {
- Set<BundleCapability> allowed = new HashSet<BundleCapability>();
-
- if (!path.contains(r)) {
- allowCapabilitiesInRegion(allowed, r, candidates);
- allowImportedCapabilities(allowed, r, candidates, path);
- }
-
- return allowed;
- }
-
- private void allowImportedCapabilities(Set<BundleCapability> allowed, Region r, Collection<BundleCapability> candidates, Set<Region> path) {
- for (FilteredRegion fr : this.regionDigraph.getEdges(r)) {
- Set<BundleCapability> a = getAllowed(fr.getRegion(), candidates, extendPath(r, path));
- filter(a, fr.getFilter());
- allowed.addAll(a);
- }
- }
-
- private void allowCapabilitiesInRegion(Set<BundleCapability> allowed, Region r, Collection<BundleCapability> candidates) {
- for (BundleCapability b : candidates) {
- if (r.equals(getRegion(b.getRevision()))) {
- allowed.add(b);
- }
- }
- }
-
- private Set<Region> extendPath(Region r, Set<Region> path) {
- Set<Region> newPath = new HashSet<Region>(path);
- newPath.add(r);
- return newPath;
- }
-
- private void filter(Set<BundleCapability> capabilities, RegionFilter filter) {
- Iterator<BundleCapability> i = capabilities.iterator();
- while (i.hasNext()) {
- BundleCapability c = i.next();
- if (!filter.isCapabilityAllowed(c) && !filter.isBundleAllowed(c.getRevision()))
- i.remove();
- }
- }
-
private Region getRegion(Bundle bundle) {
- for (Region r : this.regionDigraph) {
- if (r.contains(bundle)) {
- return r;
- }
- }
- return null;
+ return this.regionDigraph.getRegion(bundle);
}
@Override
diff --git a/org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/hook/RegionServiceEventHook.java b/org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/hook/RegionServiceEventHook.java
index 0c1e9279..56610acb 100644
--- a/org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/hook/RegionServiceEventHook.java
+++ b/org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/hook/RegionServiceEventHook.java
@@ -37,6 +37,7 @@ import org.osgi.framework.hooks.service.FindHook;
* <strong>Concurrent Semantics</strong><br />
* Thread safe.
*/
+@SuppressWarnings("deprecation")
public final class RegionServiceEventHook implements EventHook {
private final FindHook serviceFindHook;
diff --git a/org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/hook/RegionServiceFindHook.java b/org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/hook/RegionServiceFindHook.java
index d42de0db..fd561c4f 100644
--- a/org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/hook/RegionServiceFindHook.java
+++ b/org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/hook/RegionServiceFindHook.java
@@ -12,15 +12,11 @@
package org.eclipse.virgo.kernel.osgi.region.hook;
import java.util.Collection;
-import java.util.HashSet;
-import java.util.Iterator;
import java.util.Set;
import org.eclipse.virgo.kernel.osgi.region.Region;
import org.eclipse.virgo.kernel.osgi.region.RegionDigraph;
-import org.eclipse.virgo.kernel.osgi.region.RegionDigraph.FilteredRegion;
import org.eclipse.virgo.kernel.osgi.region.RegionFilter;
-import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
import org.osgi.framework.hooks.service.FindHook;
@@ -56,62 +52,39 @@ public final class RegionServiceFindHook implements FindHook {
return;
}
- Set<ServiceReference<?>> allowed = getAllowed(finderRegion, references, new HashSet<Region>());
+ Visitor visitor = new Visitor(references);
+ finderRegion.visitSubgraph(visitor);
+ Set<ServiceReference<?>> allowed = visitor.getAllowed();
references.retainAll(allowed);
}
- private Set<ServiceReference<?>> getAllowed(Region r, Collection<ServiceReference<?>> references, Set<Region> path) {
- Set<ServiceReference<?>> allowed = new HashSet<ServiceReference<?>>();
+ private class Visitor extends RegionDigraphVisitorBase<ServiceReference<?>> {
- if (!path.contains(r)) {
- allowServiceReferencesInRegion(allowed, r, references);
- allowImportedServices(allowed, r, references, path);
+ private Visitor(Collection<ServiceReference<?>> candidates) {
+ super(candidates);
}
- return allowed;
- }
-
- private void allowImportedServices(Set<ServiceReference<?>> allowed, Region r, Collection<ServiceReference<?>> references, Set<Region> path) {
- for (FilteredRegion fr : this.regionDigraph.getEdges(r)) {
- Set<ServiceReference<?>> a = getAllowed(fr.getRegion(), references, extendPath(r, path));
- filter(a, fr.getFilter());
- allowed.addAll(a);
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected boolean contains(Region region, ServiceReference<?> candidate) {
+ return region.contains(candidate.getBundle());
}
- }
- private void allowServiceReferencesInRegion(Set<ServiceReference<?>> allowed, Region r, Collection<ServiceReference<?>> references) {
- for (ServiceReference<?> b : references) {
- if (r.contains(b.getBundle())) {
- allowed.add(b);
- }
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected boolean isAllowed(ServiceReference<?> candidate, RegionFilter filter) {
+ return filter.isServiceAllowed(candidate) || filter.isBundleAllowed(candidate.getBundle());
}
- }
- private Set<Region> extendPath(Region r, Set<Region> path) {
- Set<Region> newPath = new HashSet<Region>(path);
- newPath.add(r);
- return newPath;
- }
-
- private void filter(Set<ServiceReference<?>> references, RegionFilter filter) {
- Iterator<ServiceReference<?>> i = references.iterator();
- while (i.hasNext()) {
- ServiceReference<?> sr = i.next();
- if (!filter.isServiceAllowed(sr) && !filter.isBundleAllowed(sr.getBundle())) {
- i.remove();
- }
- }
}
private Region getRegion(BundleContext context) {
- Bundle b = context.getBundle();
- for (Region r : this.regionDigraph) {
- if (r.contains(b)) {
- return r;
- }
- }
- return null;
+ return this.regionDigraph.getRegion(context.getBundle());
}
}
diff --git a/org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/internal/BundleIdBasedRegion.java b/org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/internal/BundleIdBasedRegion.java
index e4aaec86..8ebb78f9 100644
--- a/org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/internal/BundleIdBasedRegion.java
+++ b/org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/internal/BundleIdBasedRegion.java
@@ -22,6 +22,7 @@ import java.util.Set;
import org.eclipse.virgo.kernel.osgi.region.Region;
import org.eclipse.virgo.kernel.osgi.region.RegionDigraph;
import org.eclipse.virgo.kernel.osgi.region.RegionDigraph.FilteredRegion;
+import org.eclipse.virgo.kernel.osgi.region.RegionDigraphVisitor;
import org.eclipse.virgo.kernel.osgi.region.RegionFilter;
import org.eclipse.virgo.kernel.serviceability.NonNull;
import org.eclipse.virgo.util.math.ConcurrentHashSet;
@@ -184,9 +185,9 @@ final class BundleIdBasedRegion implements Region {
* {@inheritDoc}
*/
@Override
- public void connectRegion(Region tailRegion, RegionFilter filter) throws BundleException {
+ public void connectRegion(Region headRegion, RegionFilter filter) throws BundleException {
synchronized (this.updateMonitor) {
- this.regionDigraph.connect(this, filter, tailRegion);
+ this.regionDigraph.connect(this, filter, headRegion);
}
}
@@ -273,4 +274,9 @@ final class BundleIdBasedRegion implements Region {
return this.regionDigraph.getEdges(this);
}
+ @Override
+ public void visitSubgraph(RegionDigraphVisitor visitor) {
+ this.regionDigraph.visitSubgraph(this, visitor);
+ }
+
}
diff --git a/org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/internal/StandardRegionDigraph.java b/org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/internal/StandardRegionDigraph.java
index 48918485..92adc276 100644
--- a/org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/internal/StandardRegionDigraph.java
+++ b/org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/internal/StandardRegionDigraph.java
@@ -22,6 +22,7 @@ import java.util.Set;
import org.eclipse.virgo.kernel.osgi.region.Region;
import org.eclipse.virgo.kernel.osgi.region.RegionDigraph;
+import org.eclipse.virgo.kernel.osgi.region.RegionDigraphVisitor;
import org.eclipse.virgo.kernel.osgi.region.RegionFilter;
import org.eclipse.virgo.kernel.osgi.region.RegionFilterBuilder;
import org.eclipse.virgo.kernel.osgi.region.RegionLifecycleListener;
@@ -54,7 +55,10 @@ public final class StandardRegionDigraph implements RegionDigraph {
private final ThreadLocal<Region> threadLocal;
+ private SubgraphTraverser subgraphTraverser;
+
public StandardRegionDigraph(BundleContext bundleContext, ThreadLocal<Region> threadLocal) {
+ this.subgraphTraverser = new SubgraphTraverser();
this.systemBundleContext = bundleContext.getBundle(0L).getBundleContext();
this.threadLocal = threadLocal;
}
@@ -301,6 +305,14 @@ public final class StandardRegionDigraph implements RegionDigraph {
}
/**
+ * {@inheritDoc}
+ */
+ @Override
+ public void visitSubgraph(Region startingRegion, RegionDigraphVisitor visitor) {
+ this.subgraphTraverser.visitSubgraph(startingRegion, visitor);
+ }
+
+ /**
* Returns a snapshot of filtered regions
*
* @return a snapshot of filtered regions
diff --git a/org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/internal/SubgraphTraverser.java b/org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/internal/SubgraphTraverser.java
new file mode 100644
index 00000000..21f8c6f8
--- /dev/null
+++ b/org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/internal/SubgraphTraverser.java
@@ -0,0 +1,63 @@
+/*******************************************************************************
+ * This file is part of the Virgo Web Server.
+ *
+ * Copyright (c) 2011 VMware Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * SpringSource, a division of VMware - initial API and implementation and/or initial documentation
+ *******************************************************************************/
+
+package org.eclipse.virgo.kernel.osgi.region.internal;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.eclipse.virgo.kernel.osgi.region.Region;
+import org.eclipse.virgo.kernel.osgi.region.RegionDigraphVisitor;
+import org.eclipse.virgo.kernel.osgi.region.RegionDigraph.FilteredRegion;
+
+/**
+ * {@link SubgraphTraverser} is a utility for traversing a subgraph of a {@link RegionDigraph} calling a
+ * {@link RegionDigraphVisitor} on the way.
+ * <p />
+ *
+ * <strong>Concurrent Semantics</strong><br />
+ * Thread safe.
+ */
+final class SubgraphTraverser {
+
+ void visitSubgraph(Region startingRegion, RegionDigraphVisitor visitor) {
+ visitRemainingSubgraph(startingRegion, visitor, new HashSet<Region>());
+ }
+
+ private void visitRemainingSubgraph(Region r, RegionDigraphVisitor visitor, Set<Region> path) {
+ if (!path.contains(r)) {
+ if (visitor.visit(r)) {
+ traverseEdges(r, visitor, path);
+ }
+ }
+ }
+
+ private void traverseEdges(Region r, RegionDigraphVisitor visitor, Set<Region> path) {
+ for (FilteredRegion fr : r.getEdges()) {
+ if (visitor.preEdgeTraverse(fr.getFilter())) {
+ try {
+ visitRemainingSubgraph(fr.getRegion(), visitor, extendPath(r, path));
+ } finally {
+ visitor.postEdgeTraverse(fr.getFilter());
+ }
+ }
+ }
+ }
+
+ private Set<Region> extendPath(Region r, Set<Region> path) {
+ Set<Region> newPath = new HashSet<Region>(path);
+ newPath.add(r);
+ return newPath;
+ }
+
+} \ No newline at end of file
diff --git a/org.eclipse.virgo.kernel.osgi/src/test/java/org/eclipse/virgo/kernel/osgi/region/hook/RegionServiceEventHookTests.java b/org.eclipse.virgo.kernel.osgi/src/test/java/org/eclipse/virgo/kernel/osgi/region/hook/RegionServiceEventHookTests.java
index f8b0402c..40553936 100644
--- a/org.eclipse.virgo.kernel.osgi/src/test/java/org/eclipse/virgo/kernel/osgi/region/hook/RegionServiceEventHookTests.java
+++ b/org.eclipse.virgo.kernel.osgi/src/test/java/org/eclipse/virgo/kernel/osgi/region/hook/RegionServiceEventHookTests.java
@@ -34,6 +34,7 @@ import org.osgi.framework.ServiceReference;
import org.osgi.framework.hooks.service.EventHook;
import org.osgi.framework.hooks.service.FindHook;
+@SuppressWarnings("deprecation")
public class RegionServiceEventHookTests {
private FindHook mockFindHook;

Back to the top