1 /******************************************************************************* 2 * Copyright (c) 2011, 2015 VMware Inc. 3 * 4 * This program and the accompanying materials 5 * are made available under the terms of the Eclipse Public License 2.0 6 * which accompanies this distribution, and is available at 7 * https://www.eclipse.org/legal/epl-2.0/ 8 * 9 * SPDX-License-Identifier: EPL-2.0 10 * 11 * Contributors: 12 * VMware Inc. - initial contribution 13 *******************************************************************************/ 14 15 package org.eclipse.equinox.internal.region.hook; 16 17 import java.util.Collection; 18 import java.util.Iterator; 19 import org.eclipse.equinox.internal.region.EquinoxStateHelper; 20 import org.eclipse.equinox.region.*; 21 import org.osgi.framework.Bundle; 22 import org.osgi.framework.hooks.resolver.ResolverHook; 23 import org.osgi.framework.wiring.*; 24 25 /** 26 * {@link RegionResolverHook} manages the visibility of bundles across regions according to the {@link RegionDigraph}. 27 * <p /> 28 * 29 * <strong>Concurrent Semantics</strong><br /> 30 * Thread safe. 31 */ 32 public final class RegionResolverHook implements ResolverHook { 33 34 private static final Boolean DEBUG = false; 35 36 private final RegionDigraph regionDigraph; 37 RegionResolverHook(RegionDigraph regionDigraph)38 public RegionResolverHook(RegionDigraph regionDigraph) { 39 this.regionDigraph = regionDigraph; 40 } 41 42 @Override filterMatches(BundleRequirement requirement, Collection<BundleCapability> candidates)43 public void filterMatches(BundleRequirement requirement, Collection<BundleCapability> candidates) { 44 filterCandidates(requirement.getRevision(), candidates, false); 45 } 46 filterCandidates(BundleRevision requirer, Collection<BundleCapability> candidates, boolean singleton)47 private void filterCandidates(BundleRevision requirer, Collection<BundleCapability> candidates, boolean singleton) { 48 try { 49 if (DEBUG) { 50 debugEntry(requirer, candidates, singleton); 51 } 52 53 if (getBundleId(requirer) == 0L) { 54 return; 55 } 56 57 Region requirerRegion = getRegion(requirer); 58 if (requirerRegion == null) { 59 // for singleton check; keep all collisions 60 if (!singleton) { 61 candidates.clear(); 62 } 63 return; 64 } 65 66 Visitor visitor = new Visitor(candidates); 67 requirerRegion.visitSubgraph(visitor); 68 Collection<BundleCapability> allowed = visitor.getAllowed(); 69 70 candidates.retainAll(allowed); 71 } finally { 72 if (DEBUG) { 73 debugExit(requirer, candidates); 74 } 75 } 76 } 77 78 class Visitor extends RegionDigraphVisitorBase<BundleCapability> { 79 Visitor(Collection<BundleCapability> candidates)80 Visitor(Collection<BundleCapability> candidates) { 81 super(candidates); 82 } 83 84 @Override contains(Region region, BundleCapability candidate)85 protected boolean contains(Region region, BundleCapability candidate) { 86 return region.equals(getRegion(candidate.getRevision())); 87 } 88 89 @Override isAllowed(BundleCapability candidate, RegionFilter filter)90 protected boolean isAllowed(BundleCapability candidate, RegionFilter filter) { 91 return filter.isAllowed(candidate) || filter.isAllowed(candidate.getRevision()); 92 } 93 94 } 95 getRegion(BundleRevision bundleRevision)96 Region getRegion(BundleRevision bundleRevision) { 97 Bundle bundle = bundleRevision.getBundle(); 98 if (bundle != null) { 99 return getRegion(bundle); 100 } 101 Long bundleId = getBundleId(bundleRevision); 102 return getRegion(bundleId); 103 } 104 getRegion(Long bundleId)105 private Region getRegion(Long bundleId) { 106 return this.regionDigraph.getRegion(bundleId); 107 } 108 getBundleId(BundleRevision bundleRevision)109 private Long getBundleId(BundleRevision bundleRevision) { 110 return EquinoxStateHelper.getBundleId(bundleRevision); 111 } 112 getRegion(Bundle bundle)113 private Region getRegion(Bundle bundle) { 114 return this.regionDigraph.getRegion(bundle); 115 } 116 117 @Override end()118 public void end() { 119 // do nothing 120 } 121 122 @Override filterResolvable(Collection<BundleRevision> candidates)123 public void filterResolvable(Collection<BundleRevision> candidates) { 124 // filter any revisions that have no region 125 for (Iterator<BundleRevision> iCandidates = candidates.iterator(); iCandidates.hasNext();) { 126 if (getRegion(iCandidates.next()) == null) { 127 iCandidates.remove(); 128 } 129 } 130 } 131 132 @Override filterSingletonCollisions(BundleCapability singleton, Collection<BundleCapability> collisionCandidates)133 public void filterSingletonCollisions(BundleCapability singleton, Collection<BundleCapability> collisionCandidates) { 134 filterCandidates(singleton.getRevision(), collisionCandidates, true); 135 } 136 debugEntry(BundleRevision requirer, Collection<BundleCapability> candidates, boolean singleton)137 private void debugEntry(BundleRevision requirer, Collection<BundleCapability> candidates, boolean singleton) { 138 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$ 139 System.out.println(" Candidates: "); //$NON-NLS-1$ 140 Iterator<BundleCapability> i = candidates.iterator(); 141 while (i.hasNext()) { 142 BundleCapability c = i.next(); 143 String namespace = c.getNamespace(); 144 if (BundleRevision.PACKAGE_NAMESPACE.equals(namespace)) { 145 BundleRevision providerRevision = c.getRevision(); 146 String pkg = (String) c.getAttributes().get(BundleRevision.PACKAGE_NAMESPACE); 147 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$ 148 if (pkg.equals("slow")) { //$NON-NLS-1$ 149 System.out.println(">>> put breakpoint here <<<"); //$NON-NLS-1$ 150 } 151 } else { 152 BundleRevision providerRevision = c.getRevision(); 153 System.out.println(" Bundle from provider " + providerRevision.getSymbolicName() + "_" + providerRevision.getVersion() + "[" + getBundleId(providerRevision) + "]"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ 154 } 155 } 156 } 157 debugExit(BundleRevision requirer, Collection<BundleCapability> candidates)158 private void debugExit(BundleRevision requirer, Collection<BundleCapability> candidates) { 159 System.out.println(" Filtered candidates: "); //$NON-NLS-1$ 160 Iterator<BundleCapability> i = candidates.iterator(); 161 while (i.hasNext()) { 162 BundleCapability c = i.next(); 163 String namespace = c.getNamespace(); 164 if (BundleRevision.PACKAGE_NAMESPACE.equals(namespace)) { 165 BundleRevision providerRevision = c.getRevision(); 166 String pkg = (String) c.getAttributes().get(BundleRevision.PACKAGE_NAMESPACE); 167 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$ 168 if (pkg.equals("slow")) { //$NON-NLS-1$ 169 System.out.println(">>> put breakpoint here <<<"); //$NON-NLS-1$ 170 } 171 } else { 172 BundleRevision providerRevision = c.getRevision(); 173 System.out.println(" Bundle from provider " + providerRevision.getSymbolicName() + "_" + providerRevision.getVersion() + "[" + getBundleId(providerRevision) + "]"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ 174 } 175 } 176 } 177 } 178