1 9 package org.eclipse.osgi.internal.module; 10 11 import java.util.*; 12 import org.eclipse.osgi.service.resolver.BundleSpecification; 13 14 17 public class GroupingChecker { 18 final PackageRoots nullPackageRoots = new PackageRoots(null, null); 19 private HashMap bundles = new HashMap(); 23 24 29 public void populateRoots(ResolverBundle bundle) { 30 bundles.remove(bundle); 31 BundleConstraint[] requires = bundle.getRequires(); 33 for (int j = 0; j < requires.length; j++) { 34 ResolverBundle selectedSupplier = (ResolverBundle) requires[j].getSelectedSupplier(); 35 if (selectedSupplier != null) 36 isConsistentInternal(bundle, selectedSupplier, new ArrayList(1), true, null); 37 } 38 ResolverImport[] imports = bundle.getImportPackages(); 40 for (int j = 0; j < imports.length; j++) { 41 ResolverExport selectedSupplier = (ResolverExport) imports[j].getSelectedSupplier(); 42 if (selectedSupplier != null) 43 isConsistentInternal(bundle, selectedSupplier, true, null); 44 } 45 } 46 47 51 public PackageRoots[][] isConsistent(ResolverBundle requiringBundle, ResolverBundle matchingBundle) { 52 ArrayList results = isConsistentInternal(requiringBundle, matchingBundle, new ArrayList(1), false, null); 53 return results == null ? null : (PackageRoots[][]) results.toArray(new PackageRoots[results.size()][]); 54 } 55 56 private ArrayList isConsistentInternal(ResolverBundle requiringBundle, ResolverBundle matchingBundle, ArrayList visited, boolean dynamicImport, ArrayList results) { 57 if (visited.contains(matchingBundle)) 59 return results; 60 visited.add(matchingBundle); 61 ResolverExport[] matchingExports = matchingBundle.getExportPackages(); 63 for (int i = 0; i < matchingExports.length; i++) { 64 if (matchingExports[i].isDropped()) 65 continue; 66 results = isConsistentInternal(requiringBundle, matchingExports[i], dynamicImport, results); 67 } 68 BundleConstraint[] supplierRequires = matchingBundle.getRequires(); 70 for (int j = 0; j < supplierRequires.length; j++) { 71 ResolverBundle reexported = (ResolverBundle) supplierRequires[j].getSelectedSupplier(); 72 if (reexported == null || !((BundleSpecification) supplierRequires[j].getVersionConstraint()).isExported()) 73 continue; 74 results = isConsistentInternal(requiringBundle, reexported, visited, dynamicImport, results); 75 } 76 return results; 77 } 78 79 83 public PackageRoots[][] isConsistent(ResolverBundle importingBundle, ResolverExport matchingExport) { 84 ArrayList results = isConsistentInternal(importingBundle, matchingExport, false, null); 85 return results == null ? null : (PackageRoots[][]) results.toArray(new PackageRoots[results.size()][]); 86 } 87 88 94 public PackageRoots[][] isDynamicConsistent(ResolverBundle importingBundle, ResolverExport matchingExport) { 95 ArrayList results = isConsistentInternal(importingBundle, matchingExport, true, null); 96 return results == null ? null : (PackageRoots[][]) results.toArray(new PackageRoots[results.size()][]); 97 } 98 99 private ArrayList isConsistentInternal(ResolverBundle importingBundle, ResolverExport matchingExport, boolean dyanamicImport, ArrayList results) { 100 PackageRoots exportingRoots = getPackageRoots(matchingExport.getExporter(), matchingExport.getName(), null); 101 results = exportingRoots.isConsistentClassSpace(importingBundle, null, results); 103 if (!dyanamicImport) 104 return results; 105 PackageRoots importingRoots = getPackageRoots(importingBundle, matchingExport.getName(), null); 107 HashMap importingPackages = (HashMap) bundles.get(importingBundle); 108 if (importingPackages != null) 109 for (Iterator allImportingPackages = importingPackages.values().iterator(); allImportingPackages.hasNext();) { 110 PackageRoots roots = (PackageRoots) allImportingPackages.next(); 111 if (roots != importingRoots) 112 results = roots.isConsistentClassSpace(exportingRoots, null, results); 113 } 114 return results; 115 } 116 117 120 PackageRoots getPackageRoots(ResolverBundle bundle, String packageName, ArrayList visited) { 121 HashMap packages = (HashMap) bundles.get(bundle); 122 if (packages == null) { 123 packages = new HashMap(5); 124 bundles.put(bundle, packages); 125 } 126 PackageRoots packageRoots = (PackageRoots) packages.get(packageName); 127 if (packageRoots == null) { 128 packageRoots = createPackageRoots(bundle, packageName, visited == null ? new ArrayList(1) : visited); 129 packages.put(packageName, packageRoots); 130 } 131 return packageRoots != null ? packageRoots : nullPackageRoots; 132 } 133 134 private PackageRoots createPackageRoots(ResolverBundle bundle, String packageName, ArrayList visited) { 135 if (visited.contains(bundle)) 136 return null; 137 visited.add(bundle); ResolverImport imported = bundle.getImport(packageName); 140 if (imported != null && imported.getSelectedSupplier() != null) { 141 ResolverExport selectedExport = (ResolverExport) imported.getSelectedSupplier(); 143 if (selectedExport.getExporter() != bundle) { 144 return getPackageRoots(selectedExport.getExporter(), packageName, visited); 147 } 148 } 149 ResolverExport export = bundle.getExport(packageName); 151 ArrayList roots = new ArrayList(0); 152 BundleConstraint[] requires = bundle.getRequires(); 154 for (int i = 0; i < requires.length; i++) { 155 ResolverBundle supplier = (ResolverBundle) requires[i].getSelectedSupplier(); 156 if (supplier == null) 157 continue; if (supplier.getExport(packageName) != null) { 159 PackageRoots requiredRoots = getPackageRoots(supplier, packageName, visited); 161 if (requiredRoots != null) 162 roots.add(requiredRoots); 163 } else { 164 BundleConstraint[] supplierRequires = supplier.getRequires(); 166 for (int j = 0; j < supplierRequires.length; j++) { 167 ResolverBundle reexported = (ResolverBundle) supplierRequires[j].getSelectedSupplier(); 168 if (reexported == null || !((BundleSpecification) supplierRequires[j].getVersionConstraint()).isExported()) 169 continue; 170 if (reexported.getExport(packageName) != null) { 171 PackageRoots reExportedRoots = getPackageRoots(reexported, packageName, visited); 173 if (reexported != null) 174 roots.add(reExportedRoots); 175 } 176 } 177 } 178 } 179 if (export != null || roots.size() > 1) { 180 PackageRoots[] requiredRoots = (PackageRoots[]) roots.toArray(new PackageRoots[roots.size()]); 181 if (export == null) { 182 PackageRoots superSet = requiredRoots[0]; 183 for (int i = 1; i < requiredRoots.length; i++) { 184 if (requiredRoots[i].superSet(superSet)) { 185 superSet = requiredRoots[i]; 186 } else if (!superSet.superSet(requiredRoots[i])) { 187 superSet = null; 188 break; 189 } 190 } 191 if (superSet != null) 192 return superSet; 193 } 194 PackageRoots result = new PackageRoots(packageName, bundle); 196 for (int i = 0; i < requiredRoots.length; i++) 198 result.merge(requiredRoots[i]); 199 if (export != null) 200 result.addRoot(export); 202 return result; 203 } 204 return (PackageRoots) (roots.size() == 0 ? nullPackageRoots : roots.get(0)); 205 } 206 207 public void clear() { 208 bundles.clear(); 209 } 210 211 public void clear(ResolverBundle rb) { 212 bundles.remove(rb); 213 } 214 215 class PackageRoots { 216 private String name; 217 private ResolverBundle bundle; 218 private ResolverExport[] roots; 219 220 PackageRoots(String name, ResolverBundle bundle) { 221 this.name = name; 222 this.bundle = bundle; 223 } 224 225 public boolean hasRoots() { 226 return roots != null && roots.length > 0; 227 } 228 229 public void addRoot(ResolverExport export) { 230 if (roots == null) { 231 roots = new ResolverExport[] {export}; 232 return; 233 } 234 String exportBSN = export.getExporter().getName(); 237 if (exportBSN != null) { 238 for (int i = 0; i < roots.length; i++) 240 if (exportBSN.equals(roots[i].getExporter().getName())) 241 return; 242 } 243 if (!contains(export, roots)) { 244 ResolverExport[] newRoots = new ResolverExport[roots.length + 1]; 245 System.arraycopy(roots, 0, newRoots, 0, roots.length); 246 newRoots[roots.length] = export; 247 roots = newRoots; 248 } 249 } 250 251 private boolean contains(ResolverExport export, ResolverExport[] exports) { 252 for (int i = 0; i < exports.length; i++) 253 if (exports[i] == export) 254 return true; 255 return false; 256 } 257 258 public void merge(PackageRoots packageRoots) { 259 if (packageRoots == null || packageRoots.roots == null) 260 return; 261 int size = packageRoots.roots.length; 262 for (int i = 0; i < size; i++) 263 addRoot(packageRoots.roots[i]); 264 } 265 266 public ArrayList isConsistentClassSpace(ResolverBundle importingBundle, ArrayList visited, ArrayList results) { 267 if (roots == null) 268 return results; 269 int size = roots.length; 270 for (int i = 0; i < size; i++) { 271 ResolverExport root = roots[i]; 272 String [] uses = root.getUsesDirective(); 273 if (uses == null) 274 continue; 275 if (visited == null) 276 visited = new ArrayList(1); 277 if (visited.contains(this)) 278 return results; 279 visited.add(this); 280 for (int j = 0; j < uses.length; j++) { 281 if (uses[j].equals(root.getName())) 282 continue; 283 PackageRoots thisUsedRoots = getPackageRoots(root.getExporter(), uses[j], null); 284 PackageRoots importingUsedRoots = getPackageRoots(importingBundle, uses[j], null); 285 if (thisUsedRoots == importingUsedRoots) 286 return results; 287 if (thisUsedRoots != nullPackageRoots && importingUsedRoots != nullPackageRoots) 288 if (!(subSet(thisUsedRoots.roots, importingUsedRoots.roots) || subSet(importingUsedRoots.roots, thisUsedRoots.roots))) { 289 if (results == null) 290 results = new ArrayList(1); 291 results.add(new PackageRoots[] {this, importingUsedRoots}); 292 } 293 results = thisUsedRoots.isConsistentClassSpace(importingBundle, visited, results); 295 } 296 } 297 return results; 298 } 299 300 public ArrayList isConsistentClassSpace(PackageRoots exportingRoots, ArrayList visited, ArrayList results) { 301 if (roots == null) 302 return results; 303 int size = roots.length; 304 for (int i = 0; i < size; i++) { 305 ResolverExport root = roots[i]; 306 String [] uses = root.getUsesDirective(); 307 if (uses == null) 308 continue; 309 if (visited == null) 310 visited = new ArrayList(1); 311 if (visited.contains(this)) 312 return results; 313 visited.add(this); 314 for (int j = 0; j < uses.length; j++) { 315 if (uses[j].equals(root.getName()) || !uses[j].equals(exportingRoots.name)) 316 continue; 317 PackageRoots thisUsedRoots = getPackageRoots(root.getExporter(), uses[j], null); 318 PackageRoots exportingUsedRoots = getPackageRoots(exportingRoots.bundle, uses[j], null); 319 if (thisUsedRoots == exportingRoots) 320 return results; 321 if (thisUsedRoots != nullPackageRoots && exportingUsedRoots != nullPackageRoots) 322 if (!(subSet(thisUsedRoots.roots, exportingUsedRoots.roots) || subSet(exportingUsedRoots.roots, thisUsedRoots.roots))) { 323 if (results == null) 324 results = new ArrayList(1); 325 results.add(new PackageRoots[] {this, exportingUsedRoots}); 326 } 327 results = thisUsedRoots.isConsistentClassSpace(exportingRoots, visited, results); 329 } 330 } 331 return results; 332 } 333 334 private boolean subSet(ResolverExport[] superSet, ResolverExport[] subSet) { 336 for (int i = 0; i < subSet.length; i++) { 337 boolean found = false; 338 for (int j = 0; j < superSet.length; j++) 339 if (subSet[i].getExporter() == superSet[j].getExporter()) { 341 found = true; 342 break; 343 } 344 if (!found) 345 return false; 346 } 347 return true; 348 } 349 350 public boolean superSet(PackageRoots subSet) { 351 return subSet(roots, subSet.roots); 352 } 353 354 public String getName() { 355 return name; 356 } 357 358 public ResolverExport[] getRoots() { 359 return roots; 360 } 361 } 362 } 363 | Popular Tags |