/******************************************************************************* * Copyright (c) 2011, 2015 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.equinox.internal.region.hook; import java.util.Collection; import java.util.Iterator; import org.eclipse.equinox.internal.region.EquinoxStateHelper; import org.eclipse.equinox.region.*; import org.osgi.framework.Bundle; import org.osgi.framework.hooks.resolver.ResolverHook; import org.osgi.framework.wiring.*; /** * {@link RegionResolverHook} manages the visibility of bundles across regions according to the {@link RegionDigraph}. * <p /> * * <strong>Concurrent Semantics</strong><br /> * Thread safe. */ public final class RegionResolverHook implements ResolverHook { private static final Boolean DEBUG = false; private final RegionDigraph regionDigraph; public RegionResolverHook(RegionDigraph regionDigraph) { this.regionDigraph = regionDigraph; } @Override public void filterMatches(BundleRequirement requirement, Collection<BundleCapability> candidates) { filterCandidates(requirement.getRevision(), candidates, false); } private void filterCandidates(BundleRevision requirer, Collection<BundleCapability> candidates, boolean singleton) { try { if (DEBUG) { debugEntry(requirer, candidates, singleton); } if (getBundleId(requirer) == 0L) { return; } Region requirerRegion = getRegion(requirer); if (requirerRegion == null) { // for singleton check; keep all collisions if (!singleton) { candidates.clear(); } return; } Visitor visitor = new Visitor(candidates); requirerRegion.visitSubgraph(visitor); Collection<BundleCapability> allowed = visitor.getAllowed(); candidates.retainAll(allowed); } finally { if (DEBUG) { debugExit(requirer, candidates); } } } class Visitor extends RegionDigraphVisitorBase<BundleCapability> { 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.isAllowed(candidate) || filter.isAllowed(candidate.getRevision()); } } Region getRegion(BundleRevision bundleRevision) { Bundle bundle = bundleRevision.getBundle(); if (bundle != null) { return getRegion(bundle); } Long bundleId = getBundleId(bundleRevision); return getRegion(bundleId); } private Region getRegion(Long bundleId) { return this.regionDigraph.getRegion(bundleId); } private Long getBundleId(BundleRevision bundleRevision) { return EquinoxStateHelper.getBundleId(bundleRevision); } private Region getRegion(Bundle bundle) { return this.regionDigraph.getRegion(bundle); } @Override public void end() { // do nothing } @Override public void filterResolvable(Collection<BundleRevision> candidates) { // filter any revisions that have no region for (Iterator<BundleRevision> iCandidates = candidates.iterator(); iCandidates.hasNext();) { if (getRegion(iCandidates.next()) == null) { iCandidates.remove(); } } } @Override public void filterSingletonCollisions(BundleCapability singleton, Collection<BundleCapability> collisionCandidates) { filterCandidates(singleton.getRevision(), collisionCandidates, true); } private void debugEntry(BundleRevision requirer, Collection<BundleCapability> candidates, boolean singleton) { System.out.println((singleton ? "Singleton" : "Requirer: ") + requirer.getSymbolicName() + "_" + requirer.getVersion() + "[" + getBundleId(requirer) + "]"); //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ System.out.println(" Candidates: "); //$NON-NLS-1$ Iterator<BundleCapability> i = candidates.iterator(); while (i.hasNext()) { BundleCapability c = i.next(); String namespace = c.getNamespace(); if (BundleRevision.PACKAGE_NAMESPACE.equals(namespace)) { BundleRevision providerRevision = c.getRevision(); String pkg = (String) c.getAttributes().get(BundleRevision.PACKAGE_NAMESPACE); System.out.println(" Package " + pkg + " from provider " + providerRevision.getSymbolicName() + "_" + providerRevision.getVersion() + "[" + getBundleId(providerRevision) + "]"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ if (pkg.equals("slow")) { //$NON-NLS-1$ System.out.println(">>> put breakpoint here <<<"); //$NON-NLS-1$ } } else { BundleRevision providerRevision = c.getRevision(); System.out.println(" Bundle from provider " + providerRevision.getSymbolicName() + "_" + providerRevision.getVersion() + "[" + getBundleId(providerRevision) + "]"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ } } } private void debugExit(BundleRevision requirer, Collection<BundleCapability> candidates) { System.out.println(" Filtered candidates: "); //$NON-NLS-1$ Iterator<BundleCapability> i = candidates.iterator(); while (i.hasNext()) { BundleCapability c = i.next(); String namespace = c.getNamespace(); if (BundleRevision.PACKAGE_NAMESPACE.equals(namespace)) { BundleRevision providerRevision = c.getRevision(); String pkg = (String) c.getAttributes().get(BundleRevision.PACKAGE_NAMESPACE); System.out.println(" Package " + pkg + " from provider " + providerRevision.getSymbolicName() + "_" + providerRevision.getVersion() + "[" + getBundleId(providerRevision) + "]"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ if (pkg.equals("slow")) { //$NON-NLS-1$ System.out.println(">>> put breakpoint here <<<"); //$NON-NLS-1$ } } else { BundleRevision providerRevision = c.getRevision(); System.out.println(" Bundle from provider " + providerRevision.getSymbolicName() + "_" + providerRevision.getVersion() + "[" + getBundleId(providerRevision) + "]"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ } } } }