| author | Thomas Watson | 2011-03-07 16:43:00 (EST) |
|---|---|---|
| committer | Glyn Normington | 2011-03-07 16:43:00 (EST) |
| commit | d205e10a1bff8922ba9ab389aeb89bf27fb7e02c (patch) (side-by-side diff) | |
| tree | 103afb2b7543ad6cfe320cf86c9029959d441689 | |
| parent | 6d28bd05f7fff4b56d2373176db3078ff5d4199f (diff) | |
| download | org.eclipse.virgo.kernel-d205e10a1bff8922ba9ab389aeb89bf27fb7e02c.zip org.eclipse.virgo.kernel-d205e10a1bff8922ba9ab389aeb89bf27fb7e02c.tar.gz org.eclipse.virgo.kernel-d205e10a1bff8922ba9ab389aeb89bf27fb7e02c.tar.bz2 | |
Initial attempt at generalizing RegionFilter
16 files changed, 481 insertions, 530 deletions
diff --git a/org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/RegionFilter.java b/org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/RegionFilter.java index 994dac1..5449c0d 100644 --- a/org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/RegionFilter.java +++ b/org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/RegionFilter.java @@ -13,13 +13,18 @@ package org.eclipse.virgo.kernel.osgi.region; -import java.util.Dictionary; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; import java.util.Map; -import org.eclipse.virgo.util.osgi.VersionRange; +import org.osgi.framework.Bundle; import org.osgi.framework.Filter; +import org.osgi.framework.FrameworkUtil; +import org.osgi.framework.InvalidSyntaxException; import org.osgi.framework.ServiceReference; -import org.osgi.framework.Version; +import org.osgi.framework.wiring.BundleCapability; +import org.osgi.framework.wiring.BundleRevision; /** * A {@link RegionFilter} is associated with a connection from one region to another and determines the bundles, @@ -28,122 +33,258 @@ import org.osgi.framework.Version; * * <strong>Concurrent Semantics</strong><br /> * - * Implementations must be thread safe. + * This implementations is thread safe. * */ -public interface RegionFilter { +public class RegionFilter { - public static final RegionPackageImportPolicy ALL_PACKAGES = new RegionPackageImportPolicy() { + public static final String VISIBLE_PACKAGE_NAMESPACE = BundleRevision.PACKAGE_NAMESPACE; + public static final String VISIBLE_REQUIRE_NAMESPACE = BundleRevision.BUNDLE_NAMESPACE; + public static final String VISIBLE_HOST_NAMESPACE = BundleRevision.HOST_NAMESPACE; + public static final String VISIBLE_SERVICE_NAMESPACE = "org.eclipse.equinox.allow.service"; + public static final String VISIBLE_BUNDLE_NAMESPACE = "org.eclipse.equinox.allow.bundle"; + public static final String VISIBLE_ALL_NAMESPACE = "org.eclipse.equinox.allow.all"; - @Override - public boolean isImported(String packageName, Map<String, Object> attributes, Map<String, String> directives) { - return true; - } - }; + public static final String ALL_PACKAGES = '(' + VISIBLE_PACKAGE_NAMESPACE + "=*)"; + public static final String ALL_REQUIRES = '(' + VISIBLE_REQUIRE_NAMESPACE + "=*)"; + public static final String ALL_HOSTS = '(' + VISIBLE_HOST_NAMESPACE + "=*)"; + public static final String ALL_SERVICES = '(' + org.osgi.framework.Constants.SERVICE_ID + "=*)"; + public static final String ALL_BUNDLES = '(' + org.osgi.framework.Constants.BUNDLE_SYMBOLICNAME_ATTRIBUTE + "=*)"; + // pretty much a hack to make Filter always return true + public static final String ALL = "(|(x=*)(!(x=*)))"; - public static final Filter ALL_SERVICES = new Filter() { + public static final RegionFilter TOP = new RegionFilter() { - @Override - public boolean match(ServiceReference<?> reference) { - return true; - } + @Override + public boolean isBundleAllowed(Bundle bundle) { + return true; + } - @Override - public boolean match(Dictionary<String, ?> dictionary) { - return true; - } + @Override + public boolean isBundleAllowed(BundleRevision bundle) { + return true; + } - @Override - public boolean matchCase(Dictionary<String, ?> dictionary) { - return true; - } + @Override + public boolean isServiceAllowed(ServiceReference<?> service) { + return true; + } - @Override - public boolean matches(Map<String, ?> map) { - return true; - } - }; - - public static final RegionFilter TOP = new RegionFilter() { + @Override + public boolean isCapabilityAllowed(BundleCapability capability) { + return true; + } - @Override - public RegionFilter allowBundle(String bundleSymbolicName, VersionRange versionRange) { - return this; - } - - @Override - public boolean isBundleAllowed(String bundleSymbolicName, Version bundleVersion) { - return true; - } - - @Override - public RegionFilter setPackageImportPolicy(RegionPackageImportPolicy packageImportPolicy) { - throw new UnsupportedOperationException("TOP is immutable"); - } - - @Override - public RegionPackageImportPolicy getPackageImportPolicy() { - return ALL_PACKAGES; - } - - @Override - public RegionFilter setServiceFilter(Filter serviceFilter) { - throw new UnsupportedOperationException("TOP is immutable"); - } - - @Override - public Filter getServiceFilter() { - return ALL_SERVICES; - } + @Override + public RegionFilter setFilters(String namespace, Collection<String> filters) + throws InvalidSyntaxException { + throw new UnsupportedOperationException("TOP is immutable"); + } }; + private Object monitor = new Object(); + private Collection<Filter> packages = null; + private Collection<Filter> requires = null; + private Collection<Filter> hosts = null; + private Collection<Filter> services = null; + private Collection<Filter> bundles = null; + private Collection<Filter> all = null; + private Map<String, Collection<Filter>> generics = null; + /** - * Allows bundles with the given bundle symbolic name and bundle version in the given range to be imported. + * Determines whether this filter allows the given bundle * - * Note that the system bundle has the symbolic name "org.eclipse.osgi". - * - * @param bundleSymbolicName - * @param versionRange - * @return this {@link RegionFilter} for chaining purposes + * @param bundle the bundle + * @return <code>true</code> if the bundle is allowed and <code>false</code>otherwise */ - RegionFilter allowBundle(String bundleSymbolicName, VersionRange versionRange); + public boolean isBundleAllowed(Bundle bundle) { + HashMap<String, Object> attrs = new HashMap<String, Object>(3); + String bsn = bundle.getSymbolicName(); + if (bsn != null) + attrs.put(org.osgi.framework.Constants.BUNDLE_SYMBOLICNAME_ATTRIBUTE, bsn); + attrs.put(org.osgi.framework.Constants.BUNDLE_VERSION_ATTRIBUTE, bundle.getVersion()); + return isBundleAllowed(attrs); + } /** - * Determines whether this filter allows the bundle with the given symbolic name and version + * Determines whether this filter allows the given bundle * - * @param bundleSymbolicName the symbolic name of the bundle - * @param bundleVersion the {@link Version} of the bundle + * @param bundle the bundle revision * @return <code>true</code> if the bundle is allowed and <code>false</code>otherwise */ - boolean isBundleAllowed(String bundleSymbolicName, Version bundleVersion); + public boolean isBundleAllowed(BundleRevision bundle) { + HashMap<String, Object> attrs = new HashMap<String, Object>(3); + String bsn = bundle.getSymbolicName(); + if (bsn != null) + attrs.put(org.osgi.framework.Constants.BUNDLE_SYMBOLICNAME_ATTRIBUTE, bsn); + attrs.put(org.osgi.framework.Constants.BUNDLE_VERSION_ATTRIBUTE, bundle.getVersion()); + return isBundleAllowed(attrs); + } /** - * Sets the package import policy of this filter. + * Determines whether this filter allows the bundle with the given attributes * - * @param packageImportPolicy - * @return this {@link RegionFilter} for chaining purposes + * @param bundleAttributes the bundle attributes + * @return <code>true</code> if the bundle is allowed and <code>false</code>otherwise */ - RegionFilter setPackageImportPolicy(RegionPackageImportPolicy packageImportPolicy); + private boolean isBundleAllowed(Map<String, ?> bundleAttributes) { + synchronized (this.monitor) { + if (match(bundles, bundleAttributes)) + return true; + return match(all, bundleAttributes); + } + } - /** - * Gets the package import policy of this filter. - * - * @return the package import policy or <code>null</code> if this has not been set - */ - RegionPackageImportPolicy getPackageImportPolicy(); + private boolean match(Collection<Filter> filters, Map<String, ?> attrs) { + if (filters == null) + return false; + for (Filter filter : filters) { + if (filter.matches(attrs)) + return true; + } + return false; + } + + private boolean match(Collection<Filter> filters, ServiceReference<?> service) { + if (filters == null) + return false; + for (Filter filter : filters) { + if (filter.match(service)) + return true; + } + return false; + } /** - * @param serviceFilter - * @return this {@link RegionFilter} for chaining purposes - * @see org.osgi.framework.Filter more information about service filters + * Determines whether this filter allows the given service reference. + * + * @param service the service reference of the service + * @return <code>true</code> if the service is allowed and <code>false</code>otherwise */ - RegionFilter setServiceFilter(Filter serviceFilter); + public boolean isServiceAllowed(ServiceReference<?> service) { + synchronized (this.monitor) { + if (match(services, service)) + return true; + return match(all, service); + } + } /** - * Gets the service filter of this filter. + * Determines whether this filter allows the given capability. * - * @return the service filter or <code>null</code> if this has not been set + * @param capability the bundle capability + * @return <code>true</code> if the capability is allowed and <code>false</code>otherwise */ - Filter getServiceFilter(); + public boolean isCapabilityAllowed(BundleCapability capability) { + String namespace = capability.getNamespace(); + Collection<Filter> filter = null; + synchronized (this.monitor) { + if (VISIBLE_PACKAGE_NAMESPACE.equals(namespace)) + filter = packages; + else if (VISIBLE_REQUIRE_NAMESPACE.equals(namespace)) + filter = requires; + else if (VISIBLE_HOST_NAMESPACE.equals(namespace)) + filter = hosts; + else + filter = generics == null ? null : generics.get(namespace); + Map<String, ?> attrs = capability.getAttributes(); + if (match(filter, attrs)) + return true; + return match(all, attrs); + } + } + + public RegionFilter setFilters(String namespace, Collection<String> filters) throws InvalidSyntaxException { + if (namespace == null || filters == null) + throw new IllegalArgumentException("The namespace and filters must not be null."); + Collection<Filter> filterImpls = createFilters(filters); + synchronized (monitor) { + if (VISIBLE_PACKAGE_NAMESPACE.equals(namespace)) + packages = filterImpls; + else if (VISIBLE_REQUIRE_NAMESPACE.equals(namespace)) + requires = filterImpls; + else if (VISIBLE_HOST_NAMESPACE.equals(namespace)) + hosts = filterImpls; + else if (VISIBLE_SERVICE_NAMESPACE.equals(namespace)) + services = filterImpls; + else if (VISIBLE_BUNDLE_NAMESPACE.equals(namespace)) + bundles = filterImpls; + else if (VISIBLE_ALL_NAMESPACE.equals(namespace)) + all = filterImpls; + else { + if (generics == null) + generics = new HashMap<String, Collection<Filter>>(); + generics.put(namespace, filterImpls); + } + } + return this; + } + + public RegionFilter removeFilters(String namespace) { + if (namespace == null) + throw new IllegalArgumentException("The namespace must not be null."); + synchronized (monitor) { + if (VISIBLE_PACKAGE_NAMESPACE.equals(namespace)) + packages = null; + else if (VISIBLE_REQUIRE_NAMESPACE.equals(namespace)) + requires = null; + else if (VISIBLE_HOST_NAMESPACE.equals(namespace)) + hosts = null; + else if (VISIBLE_SERVICE_NAMESPACE.equals(namespace)) + services = null; + else if (VISIBLE_BUNDLE_NAMESPACE.equals(namespace)) + bundles = null; + else if (VISIBLE_ALL_NAMESPACE.equals(namespace)) + all = null; + else { + if (generics == null) + generics = new HashMap<String, Collection<Filter>>(); + generics.remove(namespace); + } + } + return this; + } + + public Collection<String> getFilters(String namespace) { + if (namespace == null) + throw new IllegalArgumentException("The namespace not be null."); + synchronized (monitor) { + if (VISIBLE_PACKAGE_NAMESPACE.equals(namespace)) + return getFilters(packages); + else if (VISIBLE_REQUIRE_NAMESPACE.equals(namespace)) + return getFilters(requires); + else if (VISIBLE_HOST_NAMESPACE.equals(namespace)) + return getFilters(hosts); + else if (VISIBLE_SERVICE_NAMESPACE.equals(namespace)) + return getFilters(services); + else if (VISIBLE_BUNDLE_NAMESPACE.equals(namespace)) + return getFilters(bundles); + else if (VISIBLE_ALL_NAMESPACE.equals(namespace)) + return getFilters(all); + else { + if (generics != null) + return getFilters(generics.get(namespace)); + } + return null; + } + } + + private static Collection<String> getFilters(Collection<Filter> filters) { + Collection<String> result = new ArrayList<String>(filters.size()); + for (Filter filter : filters) { + result.add(filter.toString()); + } + return result; + } + private static Collection<Filter> createFilters(Collection<String> filters) throws InvalidSyntaxException { + if (filters == null) + return null; + Collection<Filter> result = new ArrayList<Filter>(filters.size()); + //TODO Using FrameworkUtil for now; Should move to using BundleContext + for (String filter : filters) { + result.add(FrameworkUtil.createFilter(filter)); + } + return result; + } } 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 25ac96b..d20c19a 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 @@ -95,7 +95,7 @@ final class RegionManager { registerBundleEventHook(new RegionBundleEventHook(regionDigraph, bundleFindHook, this.threadLocal)); - RegionServiceFindHook serviceFindHook = new RegionServiceFindHook(regionDigraph); + RegionServiceFindHook serviceFindHook = new RegionServiceFindHook(regionDigraph, bundleFindHook); registerServiceFindHook(serviceFindHook); diff --git a/org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/RegionPackageImportPolicy.java b/org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/RegionPackageImportPolicy.java deleted file mode 100644 index ff1abc8..0000000 --- a/org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/RegionPackageImportPolicy.java +++ b/dev/null @@ -1,40 +0,0 @@ -/******************************************************************************* - * This file is part of the Virgo Web Server. - * - * Copyright (c) 2010 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; - -import java.util.Map; - -/** - * {@link RegionPackageImportPolicy} determines the package names that are imported into a region. - * <p /> - * - * <strong>Concurrent Semantics</strong><br /> - * - * Implementations of this interface must be thread safe. - * - */ -public interface RegionPackageImportPolicy { - - /** - * Returns <code>true</code> if and only if the package with the specified name exported with the specified - * attributes and directives is imported into the region. - * - * @param packageName the name of the package - * @param attributes the package's export attributes - * @param directives the package's export directives - * @return <code>true</code> if and only if the package is imported - */ - boolean isImported(String packageName, Map<String, Object> attributes, Map<String, String> directives); - -} diff --git a/org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/StandardRegionFilter.java b/org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/StandardRegionFilter.java deleted file mode 100644 index d18af63..0000000 --- a/org.eclipse.virgo.kernel.osgi/src/main/java/org/eclipse/virgo/kernel/osgi/region/StandardRegionFilter.java +++ b/dev/null @@ -1,102 +0,0 @@ -/******************************************************************************* - * 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: - * VMware Inc. - initial contribution - *******************************************************************************/ - -package org.eclipse.virgo.kernel.osgi.region; - -import java.util.HashSet; -import java.util.Set; - -import org.eclipse.virgo.util.math.OrderedPair; -import org.eclipse.virgo.util.osgi.VersionRange; -import org.osgi.framework.Filter; -import org.osgi.framework.Version; - -/** - * {@link StandardRegionFilter} is the default implementation of {@link RegionFilter}. - * <p /> - * - * <strong>Concurrent Semantics</strong><br /> - * Thread safe. - */ -public final class StandardRegionFilter implements RegionFilter { - - private final Object monitor = new Object(); - - private final Set<OrderedPair<String, VersionRange>> allowedBundles = new HashSet<OrderedPair<String, VersionRange>>(); - - private RegionPackageImportPolicy packageImportPolicy; - - private Filter serviceFilter; - - /** - * {@inheritDoc} - */ - @Override - public RegionFilter allowBundle(String bundleSymbolicName, VersionRange versionRange) { - synchronized (this.monitor) { - this.allowedBundles.add(createPair(bundleSymbolicName, versionRange)); - } - return this; - } - - private OrderedPair<String, VersionRange> createPair(String bundleSymbolicName, VersionRange versionRange) { - return new OrderedPair<String, VersionRange>(bundleSymbolicName, versionRange); - } - - /** - * {@inheritDoc} - */ - @Override - public RegionFilter setServiceFilter(Filter serviceFilter) { - synchronized (this.monitor) { - this.serviceFilter = serviceFilter; - } - return this; - } - - /** - * {@inheritDoc} - */ - @Override - public Filter getServiceFilter() { - synchronized (this.monitor) { - return this.serviceFilter; - } - } - - @Override - public RegionPackageImportPolicy getPackageImportPolicy() { - synchronized (this.monitor) { - return this.packageImportPolicy; - } - } - - @Override - public RegionFilter setPackageImportPolicy(RegionPackageImportPolicy packageImportPolicy) { - synchronized (this.monitor) { - this.packageImportPolicy = packageImportPolicy; - } - return this; - } - - @Override - public boolean isBundleAllowed(String bundleSymbolicName, Version bundleVersion) { - synchronized (this.monitor) { - for (OrderedPair<String, VersionRange> allowedBundle : this.allowedBundles) { - if (allowedBundle.getFirst().equals(bundleSymbolicName) && allowedBundle.getSecond().includes(bundleVersion)) { - return true; - } - } - return false; - } - } - -} 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 f126a57..fcaa38a 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,9 +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; @@ -22,6 +27,7 @@ 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; /** @@ -96,7 +102,7 @@ public final class RegionBundleFindHook implements FindHook { Iterator<Bundle> i = bundles.iterator(); while (i.hasNext()) { Bundle b = i.next(); - if (!filter.isBundleAllowed(b.getSymbolicName(), b.getVersion())) { + if (!filter.isBundleAllowed(b)) { i.remove(); } } @@ -111,5 +117,4 @@ public final class RegionBundleFindHook implements FindHook { } return null; } - } 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 f75ef50..47d884a 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 @@ -21,7 +21,6 @@ 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.osgi.region.RegionPackageImportPolicy; import org.eclipse.virgo.kernel.serviceability.Assert; import org.osgi.framework.Bundle; import org.osgi.framework.hooks.resolver.ResolverHook; @@ -107,14 +106,14 @@ final class RegionResolverHook implements ResolverHook { Set<BundleCapability> allowed = new HashSet<BundleCapability>(); if (!path.contains(r)) { - allowPackagesInRegion(allowed, r, candidates); - allowImportedPackages(allowed, r, candidates, path); + allowCapabilitiesInRegion(allowed, r, candidates); + allowImportedCapabilities(allowed, r, candidates, path); } return allowed; } - private void allowImportedPackages(Set<BundleCapability> allowed, Region r, Collection<BundleCapability> candidates, Set<Region> path) { + 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()); @@ -122,7 +121,7 @@ final class RegionResolverHook implements ResolverHook { } } - private void allowPackagesInRegion(Set<BundleCapability> allowed, Region r, Collection<BundleCapability> candidates) { + private void allowCapabilitiesInRegion(Set<BundleCapability> allowed, Region r, Collection<BundleCapability> candidates) { for (BundleCapability b : candidates) { if (r.equals(getRegion(b.getRevision()))) { allowed.add(b); @@ -137,23 +136,11 @@ final class RegionResolverHook implements ResolverHook { } private void filter(Set<BundleCapability> capabilities, RegionFilter filter) { - RegionPackageImportPolicy packageImportPolicy = filter.getPackageImportPolicy(); Iterator<BundleCapability> i = capabilities.iterator(); while (i.hasNext()) { BundleCapability c = i.next(); - String namespace = c.getNamespace(); - if (BundleRevision.PACKAGE_NAMESPACE.equals(namespace)) { - if (!packageImportPolicy.isImported((String) c.getAttributes().get(BundleRevision.PACKAGE_NAMESPACE), c.getAttributes(), - c.getDirectives())) { - i.remove(); - } - } else { - BundleRevision providerRevision = c.getRevision(); - if (!filter.isBundleAllowed(providerRevision.getSymbolicName(), providerRevision.getVersion())) { - i.remove(); - } - - } + if (!filter.isCapabilityAllowed(c)) + i.remove(); } } 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 30cf3e1..66e7bb0 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 @@ -11,6 +11,7 @@ package org.eclipse.virgo.kernel.osgi.region.hook; +import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.Iterator; @@ -37,9 +38,11 @@ import org.osgi.framework.hooks.service.FindHook; public final class RegionServiceFindHook implements FindHook { private final RegionDigraph regionDigraph; + private final org.osgi.framework.hooks.bundle.FindHook bundleFindHook; - public RegionServiceFindHook(RegionDigraph regionDigraph) { + public RegionServiceFindHook(RegionDigraph regionDigraph, org.osgi.framework.hooks.bundle.FindHook bundleFindHook) { this.regionDigraph = regionDigraph; + this.bundleFindHook = bundleFindHook; } /** @@ -58,6 +61,16 @@ public final class RegionServiceFindHook implements FindHook { } Set<ServiceReference<?>> allowed = getAllowed(finderRegion, references, new HashSet<Region>()); + Collection<Bundle> registrant = new ArrayList<Bundle>(1); + for (ServiceReference<?> reference : references) { + if (allowed.contains(reference)) + continue; + registrant.clear(); + registrant.add(reference.getBundle()); + bundleFindHook.find(context, registrant); + if (!registrant.isEmpty()) + allowed.add(reference); + } references.retainAll(allowed); } @@ -67,13 +80,13 @@ public final class RegionServiceFindHook implements FindHook { if (!path.contains(r)) { allowServiceReferencesInRegion(allowed, r, references); - allowImportedBundles(allowed, r, references, path); + allowImportedServices(allowed, r, references, path); } return allowed; } - private void allowImportedBundles(Set<ServiceReference<?>> allowed, Region r, Collection<ServiceReference<?>> references, Set<Region> path) { + 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()); @@ -96,11 +109,10 @@ public final class RegionServiceFindHook implements FindHook { } private void filter(Set<ServiceReference<?>> references, RegionFilter filter) { - Filter serviceFilter = filter.getServiceFilter(); Iterator<ServiceReference<?>> i = references.iterator(); while (i.hasNext()) { ServiceReference<?> sr = i.next(); - if (!serviceFilter.match(sr)) { + if (!filter.isServiceAllowed(sr)) { i.remove(); } } diff --git a/org.eclipse.virgo.kernel.osgi/src/test/java/org/eclipse/virgo/kernel/osgi/region/hook/RegionBundleFindHookTests.java b/org.eclipse.virgo.kernel.osgi/src/test/java/org/eclipse/virgo/kernel/osgi/region/hook/RegionBundleFindHookTests.java index 26a5071..27280cd 100644 --- a/org.eclipse.virgo.kernel.osgi/src/test/java/org/eclipse/virgo/kernel/osgi/region/hook/RegionBundleFindHookTests.java +++ b/org.eclipse.virgo.kernel.osgi/src/test/java/org/eclipse/virgo/kernel/osgi/region/hook/RegionBundleFindHookTests.java @@ -15,24 +15,26 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; +import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Map; +import junit.framework.Assert; + import org.eclipse.virgo.kernel.osgi.region.Region; import org.eclipse.virgo.kernel.osgi.region.RegionFilter; -import org.eclipse.virgo.kernel.osgi.region.StandardRegionFilter; import org.eclipse.virgo.kernel.osgi.region.internal.StandardRegionDigraph; import org.eclipse.virgo.teststubs.osgi.framework.StubBundle; import org.eclipse.virgo.teststubs.osgi.framework.StubBundleContext; -import org.eclipse.virgo.util.osgi.VersionRange; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.osgi.framework.Bundle; import org.osgi.framework.BundleContext; import org.osgi.framework.BundleException; +import org.osgi.framework.InvalidSyntaxException; import org.osgi.framework.Version; import org.osgi.framework.hooks.bundle.FindHook; @@ -233,10 +235,20 @@ public class RegionBundleFindHookTests { } private RegionFilter createFilter(String... bundleSymbolicNames) { - RegionFilter filter = new StandardRegionFilter(); + RegionFilter filter = new RegionFilter(); + if (bundleSymbolicNames.length == 0) + return filter; + Collection<String> filters = new ArrayList<String>(bundleSymbolicNames.length); for (String bundleSymbolicName : bundleSymbolicNames) { - filter.allowBundle(bundleSymbolicName, new VersionRange(BUNDLE_VERSION.toString())); + StringBuilder builder = new StringBuilder(); + builder.append('(').append(RegionFilter.VISIBLE_BUNDLE_NAMESPACE).append('=').append(bundleSymbolicName).append(')'); + filters.add(builder.toString()); } + try { + filter.setFilters(RegionFilter.VISIBLE_BUNDLE_NAMESPACE, filters); + } catch (InvalidSyntaxException e) { + Assert.fail(e.getMessage()); + } return filter; } diff --git a/org.eclipse.virgo.kernel.osgi/src/test/java/org/eclipse/virgo/kernel/osgi/region/hook/RegionResolverHookTests.java b/org.eclipse.virgo.kernel.osgi/src/test/java/org/eclipse/virgo/kernel/osgi/region/hook/RegionResolverHookTests.java index 0e1d5db..0edd1e6 100644 --- a/org.eclipse.virgo.kernel.osgi/src/test/java/org/eclipse/virgo/kernel/osgi/region/hook/RegionResolverHookTests.java +++ b/org.eclipse.virgo.kernel.osgi/src/test/java/org/eclipse/virgo/kernel/osgi/region/hook/RegionResolverHookTests.java @@ -15,25 +15,28 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; +import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; +import junit.framework.Assert; + import org.eclipse.virgo.kernel.osgi.region.Region; import org.eclipse.virgo.kernel.osgi.region.RegionFilter; -import org.eclipse.virgo.kernel.osgi.region.RegionPackageImportPolicy; -import org.eclipse.virgo.kernel.osgi.region.StandardRegionFilter; import org.eclipse.virgo.kernel.osgi.region.internal.StandardRegionDigraph; import org.eclipse.virgo.teststubs.osgi.framework.StubBundle; import org.eclipse.virgo.teststubs.osgi.framework.StubBundleContext; -import org.eclipse.virgo.util.osgi.VersionRange; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.osgi.framework.Bundle; import org.osgi.framework.BundleException; +import org.osgi.framework.Constants; +import org.osgi.framework.InvalidSyntaxException; import org.osgi.framework.Version; import org.osgi.framework.hooks.resolver.ResolverHook; import org.osgi.framework.wiring.BundleCapability; @@ -285,25 +288,34 @@ public class RegionResolverHookTests { } private RegionFilter createFilter(final String... packageNames) { - RegionFilter filter = new StandardRegionFilter(); - filter.setPackageImportPolicy(new RegionPackageImportPolicy() { - - @Override - public boolean isImported(String packageName, Map<String, Object> attributes, Map<String, String> directives) { - for (String pkg : packageNames) { - if (packageName.equals(pkg)) { - return true; - } - } - return false; - } - }); + RegionFilter filter = new RegionFilter(); + if (packageNames.length == 0) + return filter; + Collection<String> filters = new ArrayList<String>(packageNames.length); + for (String pkg : packageNames) { + StringBuilder builder = new StringBuilder(); + builder.append('(').append(RegionFilter.VISIBLE_PACKAGE_NAMESPACE).append('=').append(pkg).append(')'); + filters.add(builder.toString()); + } + + try { + filter.setFilters(RegionFilter.VISIBLE_PACKAGE_NAMESPACE, filters); + } catch (InvalidSyntaxException e) { + Assert.fail(e.getMessage()); + } return filter; } private RegionFilter createBundleFilter(String bundleSymbolicName, Version bundleVersion) { - RegionFilter filter = new StandardRegionFilter(); - filter.allowBundle(bundleSymbolicName, new VersionRange(bundleVersion.toString())); + RegionFilter filter = new RegionFilter(); + StringBuilder builder = new StringBuilder(); + builder.append("(&(").append(RegionFilter.VISIBLE_BUNDLE_NAMESPACE).append('=').append(bundleSymbolicName).append(')'); + builder.append('(').append(Constants.BUNDLE_VERSION_ATTRIBUTE).append(">=").append(bundleVersion).append("))"); + try { + filter.setFilters(RegionFilter.VISIBLE_BUNDLE_NAMESPACE, Arrays.asList(builder.toString())); + } catch (InvalidSyntaxException e) { + Assert.fail(e.getMessage()); + } return filter; } diff --git a/org.eclipse.virgo.kernel.osgi/src/test/java/org/eclipse/virgo/kernel/osgi/region/hook/RegionServiceFindHookTests.java b/org.eclipse.virgo.kernel.osgi/src/test/java/org/eclipse/virgo/kernel/osgi/region/hook/RegionServiceFindHookTests.java index c6602f8..bfdd0f5 100644 --- a/org.eclipse.virgo.kernel.osgi/src/test/java/org/eclipse/virgo/kernel/osgi/region/hook/RegionServiceFindHookTests.java +++ b/org.eclipse.virgo.kernel.osgi/src/test/java/org/eclipse/virgo/kernel/osgi/region/hook/RegionServiceFindHookTests.java @@ -15,15 +15,16 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; +import java.util.ArrayList; import java.util.Collection; -import java.util.Dictionary; import java.util.HashMap; import java.util.HashSet; import java.util.Map; +import junit.framework.Assert; + import org.eclipse.virgo.kernel.osgi.region.Region; import org.eclipse.virgo.kernel.osgi.region.RegionFilter; -import org.eclipse.virgo.kernel.osgi.region.StandardRegionFilter; import org.eclipse.virgo.kernel.osgi.region.internal.StandardRegionDigraph; import org.eclipse.virgo.teststubs.osgi.framework.StubBundle; import org.eclipse.virgo.teststubs.osgi.framework.StubBundleContext; @@ -35,7 +36,8 @@ import org.junit.Test; import org.osgi.framework.Bundle; import org.osgi.framework.BundleContext; import org.osgi.framework.BundleException; -import org.osgi.framework.Filter; +import org.osgi.framework.Constants; +import org.osgi.framework.InvalidSyntaxException; import org.osgi.framework.ServiceReference; import org.osgi.framework.Version; import org.osgi.framework.hooks.service.FindHook; @@ -93,7 +95,13 @@ public class RegionServiceFindHookTests { stubBundleContext.addInstalledBundle(stubSystemBundle); this.threadLocal = new ThreadLocal<Region>(); this.digraph = new StandardRegionDigraph(stubBundleContext, this.threadLocal); - this.bundleFindHook = new RegionServiceFindHook(this.digraph); + org.osgi.framework.hooks.bundle.FindHook mockFindHook = new org.osgi.framework.hooks.bundle.FindHook() { + @Override + public void find(BundleContext context, Collection<Bundle> bundles) { + return; + } + }; + this.bundleFindHook = new RegionServiceFindHook(this.digraph, mockFindHook); this.candidates = new HashSet<ServiceReference<?>>(); // Create regions A, B, C, D containing bundles A, B, C, D, respectively. @@ -242,38 +250,20 @@ public class RegionServiceFindHookTests { } private RegionFilter createFilter(final String... referenceNames) { - RegionFilter filter = new StandardRegionFilter(); - Filter f = new Filter() { - - @Override - public boolean match(ServiceReference<?> reference) { - for (String referenceName : referenceNames) { - if (reference.getBundle().getSymbolicName().equals(referenceName)) { - return true; - } - } - return false; - } - - @Override - public boolean match(Dictionary<String, ?> dictionary) { - // TODO Auto-generated method stub - return false; - } - - @Override - public boolean matchCase(Dictionary<String, ?> dictionary) { - // TODO Auto-generated method stub - return false; - } - - @Override - public boolean matches(Map<String, ?> map) { - // TODO Auto-generated method stub - return false; - } - }; - filter.setServiceFilter(f); + RegionFilter filter = new RegionFilter(); + if (referenceNames.length == 0) + return filter; + Collection<String> filters = new ArrayList<String>(referenceNames.length); + for (String referenceName : referenceNames) { + StringBuilder builder = new StringBuilder(); + builder.append('(').append(Constants.OBJECTCLASS).append('=').append(referenceName).append(')'); + filters.add(builder.toString()); + } + try { + filter.setFilters(RegionFilter.VISIBLE_SERVICE_NAMESPACE, filters); + } catch (InvalidSyntaxException e) { + Assert.fail(e.getMessage()); + } return filter; } @@ -286,7 +276,7 @@ public class RegionServiceFindHookTests { private StubServiceReference<Object> createServiceReference(Bundle stubBundle, String referenceName) { StubServiceRegistration<Object> stubServiceRegistration = new StubServiceRegistration<Object>( - (StubBundleContext) stubBundle.getBundleContext(), Object.class.getName()); + (StubBundleContext) stubBundle.getBundleContext(), referenceName); StubServiceReference<Object> stubServiceReference = new StubServiceReference<Object>(stubServiceRegistration); this.serviceReferences.put(referenceName, stubServiceReference); return stubServiceReference; diff --git a/org.eclipse.virgo.kernel.osgi/src/test/java/org/eclipse/virgo/kernel/osgi/region/internal/StandardRegionDigraphTests.java b/org.eclipse.virgo.kernel.osgi/src/test/java/org/eclipse/virgo/kernel/osgi/region/internal/StandardRegionDigraphTests.java index 83d9e26..cb96921 100644 --- a/org.eclipse.virgo.kernel.osgi/src/test/java/org/eclipse/virgo/kernel/osgi/region/internal/StandardRegionDigraphTests.java +++ b/org.eclipse.virgo.kernel.osgi/src/test/java/org/eclipse/virgo/kernel/osgi/region/internal/StandardRegionDigraphTests.java @@ -19,13 +19,14 @@ import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; +import java.util.Arrays; import java.util.Set; import org.easymock.EasyMock; import org.eclipse.virgo.kernel.osgi.region.Region; import org.eclipse.virgo.kernel.osgi.region.RegionDigraph; -import org.eclipse.virgo.kernel.osgi.region.RegionFilter; import org.eclipse.virgo.kernel.osgi.region.RegionDigraph.FilteredRegion; +import org.eclipse.virgo.kernel.osgi.region.RegionFilter; import org.eclipse.virgo.teststubs.osgi.framework.StubBundle; import org.eclipse.virgo.teststubs.osgi.framework.StubBundleContext; import org.eclipse.virgo.util.math.OrderedPair; @@ -34,6 +35,8 @@ import org.junit.Before; import org.junit.Test; import org.osgi.framework.Bundle; import org.osgi.framework.BundleException; +import org.osgi.framework.Constants; +import org.osgi.framework.InvalidSyntaxException; import org.osgi.framework.Version; public class StandardRegionDigraphTests { @@ -68,25 +71,22 @@ public class StandardRegionDigraphTests { this.mockRegion3 = EasyMock.createMock(Region.class); EasyMock.expect(this.mockRegion3.getName()).andReturn("mockRegion3").anyTimes(); - this.regionFilter1 = EasyMock.createMock(RegionFilter.class); - this.regionFilter2 = EasyMock.createMock(RegionFilter.class); + this.regionFilter1 = new RegionFilter(); + this.regionFilter2 = new RegionFilter(); this.mockBundle = EasyMock.createMock(Bundle.class); } - private void setDefaultMockFilters() { - setMockFilterAllowedBundles(this.regionFilter1); - setMockFilterAllowedBundles(this.regionFilter2); + private void setDefaultMockFilters() throws InvalidSyntaxException { + this.regionFilter1.removeFilters(RegionFilter.VISIBLE_BUNDLE_NAMESPACE); + this.regionFilter2.removeFilters(RegionFilter.VISIBLE_BUNDLE_NAMESPACE); } - private void setMockFilterAllowedBundles(RegionFilter regionFilter) { - EasyMock.expect(regionFilter.isBundleAllowed(EasyMock.isA(String.class), EasyMock.isA(Version.class))).andReturn(false).anyTimes(); - } - private void setMockFilterAllowedBundle(RegionFilter regionFilter, OrderedPair<String, Version> bundle) { - EasyMock.expect(regionFilter.isBundleAllowed(EasyMock.eq(bundle.getFirst()), EasyMock.eq(bundle.getSecond()))).andReturn(true).anyTimes(); - EasyMock.expect(regionFilter.isBundleAllowed(EasyMock.not(EasyMock.eq(bundle.getFirst())), EasyMock.eq(bundle.getSecond()))).andReturn(false).anyTimes(); - EasyMock.expect(regionFilter.isBundleAllowed(EasyMock.eq(bundle.getFirst()), EasyMock.not(EasyMock.eq(bundle.getSecond())))).andReturn(false).anyTimes(); - EasyMock.expect(regionFilter.isBundleAllowed(EasyMock.not(EasyMock.eq(bundle.getFirst())), EasyMock.not(EasyMock.eq(bundle.getSecond())))).andReturn(false).anyTimes(); + private void setMockFilterAllowedBundle(RegionFilter regionFilter, OrderedPair<String, Version> bundle) throws InvalidSyntaxException { + String filter = "(&(" + + RegionFilter.VISIBLE_BUNDLE_NAMESPACE + "=" + bundle.getFirst() + ")(" + + Constants.BUNDLE_VERSION_ATTRIBUTE + "=" + bundle.getSecond(); + regionFilter.setFilters(RegionFilter.VISIBLE_BUNDLE_NAMESPACE, Arrays.asList(filter)); } private void replayMocks() { @@ -99,7 +99,7 @@ public class StandardRegionDigraphTests { } @Test - public void testConnect() throws BundleException { + public void testConnect() throws BundleException, InvalidSyntaxException { setDefaultMockFilters(); replayMocks(); @@ -107,7 +107,7 @@ public class StandardRegionDigraphTests { } @Test - public void testConnectWithFilterContents() throws BundleException { + public void testConnectWithFilterContents() throws BundleException, InvalidSyntaxException { OrderedPair<String, Version> b1 = new OrderedPair<String, Version>("b1", new Version("0")); setMockFilterAllowedBundle(this.regionFilter1, b1); EasyMock.expect(this.mockRegion1.getBundle(b1.getFirst(), b1.getSecond())).andReturn(null).anyTimes(); @@ -123,7 +123,7 @@ public class StandardRegionDigraphTests { } @Test(expected = BundleException.class) - public void testConnectLoop() throws BundleException { + public void testConnectLoop() throws BundleException, InvalidSyntaxException { setDefaultMockFilters(); replayMocks(); @@ -131,7 +131,7 @@ public class StandardRegionDigraphTests { } @Test(expected = BundleException.class) - public void testDuplicateConnection() throws BundleException { + public void testDuplicateConnection() throws BundleException, InvalidSyntaxException { setDefaultMockFilters(); replayMocks(); @@ -140,7 +140,7 @@ public class StandardRegionDigraphTests { } @Test - public void testGetEdges() throws BundleException { + public void testGetEdges() throws BundleException, InvalidSyntaxException { setDefaultMockFilters(); replayMocks(); @@ -164,7 +164,7 @@ public class StandardRegionDigraphTests { } @Test - public void testRemoveRegion() throws BundleException { + public void testRemoveRegion() throws BundleException, InvalidSyntaxException { setDefaultMockFilters(); replayMocks(); @@ -178,7 +178,7 @@ public class StandardRegionDigraphTests { } @Test - public void testGetRegions() throws BundleException { + public void testGetRegions() throws BundleException, InvalidSyntaxException { setDefaultMockFilters(); replayMocks(); diff --git a/org.eclipse.virgo.kernel.osgi/src/test/java/org/eclipse/virgo/kernel/osgi/region/internal/StandardRegionFilterTests.java b/org.eclipse.virgo.kernel.osgi/src/test/java/org/eclipse/virgo/kernel/osgi/region/internal/StandardRegionFilterTests.java index 47768ab..27b1e9a 100644 --- a/org.eclipse.virgo.kernel.osgi/src/test/java/org/eclipse/virgo/kernel/osgi/region/internal/StandardRegionFilterTests.java +++ b/org.eclipse.virgo.kernel.osgi/src/test/java/org/eclipse/virgo/kernel/osgi/region/internal/StandardRegionFilterTests.java @@ -17,16 +17,18 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; -import org.easymock.EasyMock; +import java.util.Arrays; + import org.eclipse.virgo.kernel.osgi.region.RegionFilter; -import org.eclipse.virgo.kernel.osgi.region.RegionPackageImportPolicy; -import org.eclipse.virgo.kernel.osgi.region.StandardRegionFilter; -import org.eclipse.virgo.util.osgi.VersionRange; +import org.eclipse.virgo.teststubs.osgi.framework.StubBundle; import org.junit.After; +import org.junit.Assert; import org.junit.Before; import org.junit.Test; -import org.osgi.framework.Filter; +import org.osgi.framework.Constants; +import org.osgi.framework.InvalidSyntaxException; import org.osgi.framework.Version; +import org.osgi.framework.wiring.BundleRevision; public class StandardRegionFilterTests { @@ -36,49 +38,56 @@ public class StandardRegionFilterTests { private RegionFilter regionFilter; - private Filter mockFilter; - private RegionPackageImportPolicy packageImportPolicy; + private StubBundle stubBundle; + private String packageImportPolicy = "(" + BundleRevision.PACKAGE_NAMESPACE + "=*)"; + private String serviceImportPolicy = "(" + Constants.SERVICE_ID + "=*)"; @Before public void setUp() throws Exception { - this.regionFilter = new StandardRegionFilter(); - this.mockFilter = EasyMock.createMock(Filter.class); - this.packageImportPolicy = EasyMock.createMock(RegionPackageImportPolicy.class); + this.regionFilter = new RegionFilter(); + this.stubBundle = new StubBundle(BUNDLE_SYMBOLIC_NAME, BUNDLE_VERSION); } @After public void tearDown() throws Exception { } + private void addBundleFilter(String bundleSymbolicName, Version bundleVersion) throws InvalidSyntaxException { + String filter = "(&(" + + RegionFilter.VISIBLE_BUNDLE_NAMESPACE + "=" + bundleSymbolicName + ")(" + + Constants.BUNDLE_VERSION_ATTRIBUTE + ">=" + bundleVersion; + regionFilter.setFilters(RegionFilter.VISIBLE_BUNDLE_NAMESPACE, Arrays.asList(filter)); + + } + @Test - public void testAllowBundle() { - this.regionFilter.allowBundle(BUNDLE_SYMBOLIC_NAME, VersionRange.NATURAL_NUMBER_RANGE); - assertTrue(this.regionFilter.isBundleAllowed(BUNDLE_SYMBOLIC_NAME, BUNDLE_VERSION)); + public void testAllowBundle() throws InvalidSyntaxException { + addBundleFilter(BUNDLE_SYMBOLIC_NAME, BUNDLE_VERSION); + assertTrue(this.regionFilter.isBundleAllowed(stubBundle)); } - - @Test + + @Test public void testBundleNotAllowed() { - assertFalse(this.regionFilter.isBundleAllowed(BUNDLE_SYMBOLIC_NAME, BUNDLE_VERSION)); + assertFalse(this.regionFilter.isBundleAllowed(stubBundle)); } @Test - public void testBundleNotAllowedInRange() { - this.regionFilter.allowBundle(BUNDLE_SYMBOLIC_NAME, new VersionRange("1")); - - assertFalse(this.regionFilter.isBundleAllowed(BUNDLE_SYMBOLIC_NAME, BUNDLE_VERSION)); + public void testBundleNotAllowedInRange() throws InvalidSyntaxException { + addBundleFilter(BUNDLE_SYMBOLIC_NAME, new Version(1,0,0)); + assertFalse(this.regionFilter.isBundleAllowed(stubBundle)); } @Test - public void testSetPackageImportPolicy() { - this.regionFilter.setPackageImportPolicy(this.packageImportPolicy); - assertEquals(this.packageImportPolicy, this.regionFilter.getPackageImportPolicy()); + public void testSetPackageImportPolicy() throws InvalidSyntaxException { + this.regionFilter.setFilters(RegionFilter.VISIBLE_PACKAGE_NAMESPACE, Arrays.asList(packageImportPolicy)); + assertEquals(Arrays.asList(this.packageImportPolicy), this.regionFilter.getFilters(RegionFilter.VISIBLE_PACKAGE_NAMESPACE)); } @Test - public void testSetServiceFilter() { - this.regionFilter.setServiceFilter(this.mockFilter); - assertEquals(this.mockFilter, this.regionFilter.getServiceFilter()); + public void testSetServiceFilter() throws InvalidSyntaxException { + this.regionFilter.setFilters(RegionFilter.VISIBLE_SERVICE_NAMESPACE, Arrays.asList(serviceImportPolicy)); + assertEquals(Arrays.asList(this.packageImportPolicy), this.regionFilter.getFilters(RegionFilter.VISIBLE_SERVICE_NAMESPACE)); } } diff --git a/org.eclipse.virgo.kernel.userregion/src/main/java/org/eclipse/virgo/kernel/userregion/internal/quasi/DependencyCalculator.java b/org.eclipse.virgo.kernel.userregion/src/main/java/org/eclipse/virgo/kernel/userregion/internal/quasi/DependencyCalculator.java index d535649..5014a2a 100644 --- a/org.eclipse.virgo.kernel.userregion/src/main/java/org/eclipse/virgo/kernel/userregion/internal/quasi/DependencyCalculator.java +++ b/org.eclipse.virgo.kernel.userregion/src/main/java/org/eclipse/virgo/kernel/userregion/internal/quasi/DependencyCalculator.java @@ -361,7 +361,7 @@ public final class DependencyCalculator { Region userRegion = edge.getRegion(); RegionFilter filter = edge.getFilter(); long bundleId = bundleDescription.getBundleId(); - if ((bundleId == 0L || this.coregion.contains(bundleId) || (filter.isBundleAllowed(bundleSymbolicName, version) && userRegion.contains(bundleId)))) { + if ((bundleId == 0L || this.coregion.contains(bundleId) || (filter.isBundleAllowed(bundleDescription) && userRegion.contains(bundleId)))) { return true; } } diff --git a/org.eclipse.virgo.kernel.userregionfactory/src/main/java/org/eclipse/virgo/kernel/userregionfactory/Activator.java b/org.eclipse.virgo.kernel.userregionfactory/src/main/java/org/eclipse/virgo/kernel/userregionfactory/Activator.java index b902a12..5bbf0af 100644 --- a/org.eclipse.virgo.kernel.userregionfactory/src/main/java/org/eclipse/virgo/kernel/userregionfactory/Activator.java +++ b/org.eclipse.virgo.kernel.userregionfactory/src/main/java/org/eclipse/virgo/kernel/userregionfactory/Activator.java @@ -15,6 +15,8 @@ package org.eclipse.virgo.kernel.userregionfactory; import java.net.URI; import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; import java.util.Dictionary; import java.util.HashMap; import java.util.Hashtable; @@ -30,21 +32,23 @@ import org.eclipse.virgo.kernel.osgi.framework.OsgiServiceHolder; import org.eclipse.virgo.kernel.osgi.region.Region; import org.eclipse.virgo.kernel.osgi.region.RegionDigraph; import org.eclipse.virgo.kernel.osgi.region.RegionFilter; -import org.eclipse.virgo.kernel.osgi.region.StandardRegionFilter; import org.eclipse.virgo.medic.eventlog.EventLogger; import org.eclipse.virgo.osgi.launcher.parser.ArgumentParser; import org.eclipse.virgo.osgi.launcher.parser.BundleEntry; import org.eclipse.virgo.util.osgi.ServiceRegistrationTracker; +import org.eclipse.virgo.util.osgi.VersionRange; import org.eclipse.virgo.util.osgi.manifest.BundleManifest; import org.eclipse.virgo.util.osgi.manifest.BundleManifestFactory; +import org.eclipse.virgo.util.osgi.manifest.ImportedPackage; import org.eclipse.virgo.util.osgi.manifest.RequireBundle; import org.eclipse.virgo.util.osgi.manifest.RequiredBundle; import org.osgi.framework.Bundle; import org.osgi.framework.BundleActivator; import org.osgi.framework.BundleContext; import org.osgi.framework.BundleException; -import org.osgi.framework.Filter; +import org.osgi.framework.Constants; import org.osgi.framework.InvalidSyntaxException; +import org.osgi.framework.Version; import org.osgi.service.cm.Configuration; import org.osgi.service.cm.ConfigurationAdmin; import org.osgi.service.event.Event; @@ -87,6 +91,8 @@ public final class Activator implements BundleActivator { private static final String EVENT_PROPERTY_REGION_BUNDLECONTEXT = "region.bundleContext"; + private static final String WILDCARD = "*"; + private EventAdmin eventAdmin; private String regionBundles; @@ -144,7 +150,7 @@ public final class Activator implements BundleActivator { } } - private void createUserRegion(BundleContext userRegionBundleContext, RegionDigraph regionDigraph, EventLogger eventLogger) throws BundleException { + private void createUserRegion(BundleContext userRegionBundleContext, RegionDigraph regionDigraph, EventLogger eventLogger) throws BundleException, InvalidSyntaxException { BundleContext systemBundleContext = getSystemBundleContext(); Bundle userRegionFactoryBundle = userRegionBundleContext.getBundle(); @@ -170,15 +176,14 @@ public final class Activator implements BundleActivator { } private RegionFilter createUserRegionFilter() throws BundleException { - RegionFilter userRegionFilter = new StandardRegionFilter(); - Filter serviceFilter; + RegionFilter userRegionFilter = new RegionFilter(); + Collection<String> serviceFilter = classesToFilter(this.regionServiceExports); try { - serviceFilter = this.bundleContext.createFilter(classesToFilter(this.regionServiceExports)); + userRegionFilter.setFilters(RegionFilter.VISIBLE_SERVICE_NAMESPACE, serviceFilter); } catch (InvalidSyntaxException e) { throw new BundleException("Invalid " + USER_REGION_SERVICE_EXPORTS_PROPERTY + "in user region configuration: '" + this.regionServiceExports + "'", e); } - userRegionFilter.setServiceFilter(serviceFilter); return userRegionFilter; } @@ -187,31 +192,23 @@ public final class Activator implements BundleActivator { return regionDigraph.iterator().next(); } - private RegionFilter createKernelFilter(BundleContext systemBundleContext, EventLogger eventLogger) throws BundleException { - RegionFilter kernelFilter = new StandardRegionFilter(); + private RegionFilter createKernelFilter(BundleContext systemBundleContext, EventLogger eventLogger) throws BundleException, InvalidSyntaxException { + RegionFilter kernelFilter = new RegionFilter(); allowImportedBundles(kernelFilter, eventLogger); - kernelFilter.setPackageImportPolicy(createUserRegionPackageImportPolicy(systemBundleContext)); - Filter serviceFilter; - try { - serviceFilter = this.bundleContext.createFilter(classesToFilter(this.regionServiceImports)); - } catch (InvalidSyntaxException e) { - throw new BundleException("Invalid " + USER_REGION_SERVICE_IMPORTS_PROPERTY + "in user region configuration: '" - + this.regionServiceImports + "'", e); - } - kernelFilter.setServiceFilter(serviceFilter); + kernelFilter.setFilters(RegionFilter.VISIBLE_PACKAGE_NAMESPACE, createUserRegionPackageImportPolicy(systemBundleContext)); + Collection<String> serviceFilter = classesToFilter(this.regionServiceImports); + kernelFilter.setFilters(RegionFilter.VISIBLE_SERVICE_NAMESPACE, serviceFilter); return kernelFilter; } - private void allowImportedBundles(RegionFilter kernelFilter, EventLogger eventLogger) { + private void allowImportedBundles(RegionFilter kernelFilter, EventLogger eventLogger) throws InvalidSyntaxException { String userRegionBundleImports = this.regionBundleImports != null ? this.regionBundleImports : this.bundleContext.getProperty(USER_REGION_BUNDLE_IMPORTS_PROPERTY); RequireBundle bundleImportsAsRequireBundle = representBundleImportsAsRequireBundle(userRegionBundleImports, eventLogger); - List<RequiredBundle> importedBundles = bundleImportsAsRequireBundle.getRequiredBundles(); - for (RequiredBundle importedBundle : importedBundles) { - kernelFilter.allowBundle(importedBundle.getBundleSymbolicName(), importedBundle.getBundleVersion()); - } - } + Collection<String> importedBundles = importBundleToFilter(bundleImportsAsRequireBundle.getRequiredBundles()); + kernelFilter.setFilters(RegionFilter.VISIBLE_BUNDLE_NAMESPACE, importedBundles); + } private RequireBundle representBundleImportsAsRequireBundle(String userRegionBundleImportsProperty, EventLogger eventLogger) { Dictionary<String, String> headers = new Hashtable<String, String>(); @@ -220,24 +217,82 @@ public final class Activator implements BundleActivator { return manifest.getRequireBundle(); } - private String classesToFilter(String classList) { + private static Collection<String> importBundleToFilter(List<RequiredBundle> importedBundles) { + if (importedBundles == null || importedBundles.isEmpty()) + return Collections.emptyList(); + Collection<String> result = new ArrayList<String>(importedBundles.size()); + for (RequiredBundle importedBundle : importedBundles) { + StringBuilder f = new StringBuilder(); + f.append("(&(").append(RegionFilter.VISIBLE_BUNDLE_NAMESPACE).append('=').append(importedBundle.getBundleSymbolicName()).append(')'); + addRange(Constants.BUNDLE_VERSION_ATTRIBUTE, importedBundle.getBundleVersion(), f); + f.append(')'); + result.add(f.toString()); + } + return result; + } + + private static Collection<String> importPackageToFilter(String importList) { + if (importList == null || importList.isEmpty()) { + return Collections.emptyList(); + } + if (importList.contains(WILDCARD)) { + throw new IllegalArgumentException("Wildcards not supported in region imports: '" + importList + "'"); + } + BundleManifest manifest = BundleManifestFactory.createBundleManifest(); + manifest.setHeader("Import-Package", importList); + List<ImportedPackage> list = manifest.getImportPackage().getImportedPackages(); + if (list.isEmpty()) + return Collections.emptyList(); + Collection<String> filters = new ArrayList<String>(list.size()); + for (ImportedPackage importedPackage : list) { + StringBuilder f = new StringBuilder(); + f.append("(&(").append(RegionFilter.VISIBLE_PACKAGE_NAMESPACE).append('=').append(importedPackage.getPackageName()).append(')'); + Map<String, String> attrs = importedPackage.getAttributes(); + for (Map.Entry<String, String> attr : attrs.entrySet()) { + if (Constants.VERSION_ATTRIBUTE.equals(attr.getKey()) || Constants.BUNDLE_VERSION_ATTRIBUTE.equals(attr.getKey())) { + addRange(attr.getKey(), new VersionRange(attr.getValue()), f); + } else { + f.append('(').append(attr.getKey()).append('=').append(attr.getValue()).append(')'); + } + } + f.append(')'); + filters.add(f.toString()); + } + return filters; + } + + private static void addRange(String key, VersionRange range, StringBuilder f) { + if (range.isFloorInclusive()) { + f.append('(' + key + ">=" + range.getFloor() + ')'); + } else { + f.append("(!(" + key + "<=" + range.getFloor() +"))"); + } + Version ceiling = range.getCeiling(); + if (ceiling != null) { + if (range.isCeilingInclusive()) { + f.append('(' + key + "<=" + ceiling + ')'); + } else { + f.append("(!(" + key + ">=" + ceiling + "))"); + } + } + } + + private static Collection<String> classesToFilter(String classList) { if (classList == null) { - return ""; + return Collections.emptyList(); } String[] classes = classList.split(CLASS_LIST_SEPARATOR); if (classes.length == 0) { - return ""; + return Collections.emptyList(); } - StringBuffer filter = new StringBuffer(); - filter.append("(|"); + Collection<String> result = new ArrayList<String>(classes.length); for (String className : classes) { - filter.append("(objectClass=" + className + ")"); + result.add("(objectClass=" + className + ")"); } - filter.append(")"); - return filter.toString(); + return result; } - private UserRegionPackageImportPolicy createUserRegionPackageImportPolicy(BundleContext systemBundleContext) { + private Collection<String> createUserRegionPackageImportPolicy(BundleContext systemBundleContext) { String userRegionImportsProperty = this.regionPackageImports != null ? this.regionPackageImports : this.bundleContext.getProperty(USER_REGION_PACKAGE_IMPORTS_PROPERTY); String expandedUserRegionImportsProperty = null; @@ -246,8 +301,7 @@ public final class Activator implements BundleActivator { systemBundleContext); } - UserRegionPackageImportPolicy userRegionPackageImportPolicy = new UserRegionPackageImportPolicy(expandedUserRegionImportsProperty); - return userRegionPackageImportPolicy; + return importPackageToFilter(expandedUserRegionImportsProperty); } private BundleContext getSystemBundleContext() { diff --git a/org.eclipse.virgo.kernel.userregionfactory/src/main/java/org/eclipse/virgo/kernel/userregionfactory/UserRegionPackageImportPolicy.java b/org.eclipse.virgo.kernel.userregionfactory/src/main/java/org/eclipse/virgo/kernel/userregionfactory/UserRegionPackageImportPolicy.java deleted file mode 100644 index 06a85b1..0000000 --- a/org.eclipse.virgo.kernel.userregionfactory/src/main/java/org/eclipse/virgo/kernel/userregionfactory/UserRegionPackageImportPolicy.java +++ b/dev/null @@ -1,128 +0,0 @@ -/******************************************************************************* - * This file is part of the Virgo Web Server. - * - * Copyright (c) 2010 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.userregionfactory; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import org.eclipse.osgi.service.resolver.VersionRange; -import org.eclipse.virgo.kernel.osgi.region.RegionPackageImportPolicy; -import org.eclipse.virgo.util.osgi.manifest.BundleManifest; -import org.eclipse.virgo.util.osgi.manifest.BundleManifestFactory; -import org.eclipse.virgo.util.osgi.manifest.ImportedPackage; -import org.osgi.framework.Version; - -/** - * {@link UserRegionPackageImportPolicy} is a {@link RegionPackageImportPolicy} for a user region. - * <p /> - * - * <strong>Concurrent Semantics</strong><br /> - * - * Thread safe. - * - */ -class UserRegionPackageImportPolicy implements RegionPackageImportPolicy { - - private static final String MANDATORY_ATTRIBUTE_NAME_SEPARATOR = ","; - - private static final String MANDATORY_DIRECTIVE_NAME = "mandatory"; - - private static final String VERSION_ATTRIBUTE_NAME = "version"; - - private static final String WILDCARD = "*"; - - private final Map<String, ImportedPackage> importedPackages = new HashMap<String, ImportedPackage>(); - - /** - * Construct a {@link UserRegionPackageImportPolicy} for the specified import package list which must not contain - * wildcards. - * - * @param regionImports a string representing a list of imported packages - */ - UserRegionPackageImportPolicy(String regionImports) { - if (regionImports != null && !regionImports.isEmpty()) { - if (regionImports.contains(WILDCARD)) { - throw new IllegalArgumentException("Wildcards not supported in region imports: '" + regionImports + "'"); - } - BundleManifest manifest = BundleManifestFactory.createBundleManifest(); - manifest.setHeader("Import-Package", regionImports); - List<ImportedPackage> list = manifest.getImportPackage().getImportedPackages(); - for (ImportedPackage importedPackage : list) { - String packageName = importedPackage.getPackageName(); - this.importedPackages.put(packageName, importedPackage); - } - } - } - - /** - * {@inheritDoc} - */ - @Override - public boolean isImported(String packageName, Map<String, Object> exportAttributes, Map<String, String> exportDirectives) { - ImportedPackage importedPackage = this.importedPackages.get(packageName); - if (importedPackage != null) { - Map<String, String> importAttributes = importedPackage.getAttributes(); - Set<String> importAttributeNames = importAttributes.keySet(); - - // Check any attribute values match. - for (String importAttributeName : importAttributeNames) { - if (exportAttributes == null) { - return false; - } - Object exportAttributeValue = exportAttributes.get(importAttributeName); - if (importAttributeName.equals(VERSION_ATTRIBUTE_NAME)) { - if (exportAttributeValue != null && exportAttributeValue instanceof Version) { - Version exportVersion = (Version) exportAttributeValue; - String importAttributeValue = importAttributes.get(importAttributeName); - VersionRange importVersion = new VersionRange(importAttributeValue); - if (!importVersion.isIncluded(exportVersion)) { - return false; - } - } else { - return false; - } - } else { - if (exportAttributeValue != null && exportAttributeValue instanceof String) { - String exportAttributeValueString = (String) exportAttributeValue; - String importAttributeValue = importAttributes.get(importAttributeName); - if (!exportAttributeValueString.equals(importAttributeValue)) { - return false; - } - } else { - return false; - } - } - - } - - // Check mandatory attributes are present. - if (exportDirectives != null) { - String mandatoryDirectiveValue = exportDirectives.get(MANDATORY_DIRECTIVE_NAME); - if (mandatoryDirectiveValue != null) { - for (String mandatoryAttribute : mandatoryDirectiveValue.split(MANDATORY_ATTRIBUTE_NAME_SEPARATOR)) { - if (!importAttributeNames.contains(mandatoryAttribute)) { - return false; - } - } - } - } - return true; - } - - return false; - } - -} diff --git a/org.eclipse.virgo.kernel.userregionfactory/src/test/java/org/eclipse/virgo/kernel/userregionfactory/UserRegionPackageImportPolicyTests.java b/org.eclipse.virgo.kernel.userregionfactory/src/test/java/org/eclipse/virgo/kernel/userregionfactory/UserRegionPackageImportPolicyTests.java index 308470d..4adbca5 100644 --- a/org.eclipse.virgo.kernel.userregionfactory/src/test/java/org/eclipse/virgo/kernel/userregionfactory/UserRegionPackageImportPolicyTests.java +++ b/org.eclipse.virgo.kernel.userregionfactory/src/test/java/org/eclipse/virgo/kernel/userregionfactory/UserRegionPackageImportPolicyTests.java @@ -16,14 +16,13 @@ package org.eclipse.virgo.kernel.userregionfactory; import java.util.HashMap; import java.util.Map; -import org.eclipse.virgo.kernel.osgi.region.RegionPackageImportPolicy; import org.junit.Assert; import org.junit.Test; import org.osgi.framework.Version; import org.osgi.framework.wiring.BundleRevision; public class UserRegionPackageImportPolicyTests { - +/* @Test public void testNullPackageString() { new UserRegionPackageImportPolicy(null); @@ -111,5 +110,5 @@ public class UserRegionPackageImportPolicyTests { Assert.assertTrue(userRegionPackageImportPolicy.isImported("q", null, null)); Assert.assertFalse(userRegionPackageImportPolicy.isImported("r", null, null)); } - +*/ } |

