1 11 package org.eclipse.osgi.internal.module; 12 13 import java.util.*; 14 import org.eclipse.osgi.internal.resolver.ExportPackageDescriptionImpl; 15 import org.eclipse.osgi.service.resolver.*; 16 import org.osgi.framework.Constants; 17 18 21 public class ResolverBundle extends VersionSupplier implements Comparable { 22 public static final int UNRESOLVED = 0; 23 public static final int RESOLVING = 1; 24 public static final int RESOLVED = 2; 25 26 private Long bundleID; 27 private BundleConstraint host; 28 private ResolverImport[] imports; 29 private ResolverExport[] exports; 30 private BundleConstraint[] requires; 31 private GenericCapability[] capabilities; 32 private GenericConstraint[] genericReqiures; 33 private ArrayList fragments; 35 private HashMap fragmentExports; 36 private HashMap fragmentImports; 37 private HashMap fragmentRequires; 38 private HashMap fragmentGenericRequires; 39 private boolean resolvable = true; 41 private int state = UNRESOLVED; 43 44 private ResolverImpl resolver; 45 private boolean newFragmentExports; 46 private ArrayList refs; 47 48 ResolverBundle(BundleDescription bundle, ResolverImpl resolver) { 49 super(bundle); 50 this.bundleID = new Long (bundle.getBundleId()); 51 this.resolver = resolver; 52 initialize(bundle.isResolved()); 53 } 54 55 void initialize(boolean useSelectedExports) { 56 if (getBundle().isSingleton()) 57 refs = new ArrayList(); 58 GenericDescription[] actualCapabilities = getBundle().getGenericCapabilities(); 60 capabilities = new GenericCapability[actualCapabilities.length]; 61 for (int i = 0; i < capabilities.length; i++) 62 capabilities[i] = new GenericCapability(this, actualCapabilities[i]); 63 if (getBundle().getHost() != null) { 64 host = new BundleConstraint(this, getBundle().getHost()); 65 exports = new ResolverExport[0]; 66 imports = new ResolverImport[0]; 67 requires = new BundleConstraint[0]; 68 genericReqiures = new GenericConstraint[0]; 69 return; 70 } 71 72 ImportPackageSpecification[] actualImports = getBundle().getImportPackages(); 73 ArrayList importList = new ArrayList(actualImports.length); 75 for (int i = actualImports.length - 1; i >= 0; i--) 76 if (ImportPackageSpecification.RESOLUTION_OPTIONAL.equals(actualImports[i].getDirective(Constants.RESOLUTION_DIRECTIVE))) 77 importList.add(new ResolverImport(this, actualImports[i])); 78 else 79 importList.add(0, new ResolverImport(this, actualImports[i])); 80 imports = (ResolverImport[]) importList.toArray(new ResolverImport[importList.size()]); 81 82 ExportPackageDescription[] actualExports = useSelectedExports ? getBundle().getSelectedExports() : getBundle().getExportPackages(); 83 exports = new ResolverExport[actualExports.length]; 84 for (int i = 0; i < actualExports.length; i++) 85 exports[i] = new ResolverExport(this, actualExports[i]); 86 87 BundleSpecification[] actualRequires = getBundle().getRequiredBundles(); 88 requires = new BundleConstraint[actualRequires.length]; 89 for (int i = 0; i < requires.length; i++) 90 requires[i] = new BundleConstraint(this, actualRequires[i]); 91 92 GenericSpecification[] actualGenericRequires = getBundle().getGenericRequires(); 93 genericReqiures = new GenericConstraint[actualGenericRequires.length]; 94 for (int i = 0; i < genericReqiures.length; i++) 95 genericReqiures[i] = new GenericConstraint(this, actualGenericRequires[i]); 96 97 fragments = null; 98 fragmentExports = null; 99 fragmentImports = null; 100 fragmentRequires = null; 101 fragmentGenericRequires = null; 102 } 103 104 ResolverExport getExport(String name) { 105 ResolverExport[] allExports = getExports(name); 106 return allExports.length == 0 ? null : allExports[0]; 107 } 108 109 ResolverExport[] getExports(String name) { 110 ArrayList results = new ArrayList(1); Object [] resolverExports = resolver.getResolverExports().get(name); 113 for (int i = 0; i < resolverExports.length; i++) 114 if (((ResolverExport)resolverExports[i]).getExporter() == this) 115 results.add(resolverExports[i]); 116 return (ResolverExport[]) results.toArray(new ResolverExport[results.size()]); 117 } 118 119 void clearWires() { 120 ResolverImport[] allImports = getImportPackages(); 121 for (int i = 0; i < allImports.length; i++) 122 allImports[i].clearPossibleSuppliers(); 123 124 if (host != null) 125 host.clearPossibleSuppliers(); 126 127 BundleConstraint[] allRequires = getRequires(); 128 for (int i = 0; i < allRequires.length; i++) 129 allRequires[i].clearPossibleSuppliers(); 130 131 GenericConstraint[] allGenericRequires = getGenericRequires(); 132 for (int i = 0; i < allGenericRequires.length; i++) 133 allGenericRequires[i].setMatchingCapability(null); 134 } 135 136 boolean isResolved() { 137 return getState() == ResolverBundle.RESOLVED; 138 } 139 140 boolean isFragment() { 141 return host != null; 142 } 143 144 int getState() { 145 return state; 146 } 147 148 void setState(int state) { 149 this.state = state; 150 } 151 152 ResolverImport[] getImportPackages() { 153 if (isFragment()) 154 return new ResolverImport[0]; 155 if (fragments == null || fragments.size() == 0) 156 return imports; 157 ArrayList resultList = new ArrayList(imports.length); 158 for (int i = 0; i < imports.length; i++) 159 resultList.add(imports[i]); 160 for (Iterator iter = fragments.iterator(); iter.hasNext();) { 161 ResolverBundle fragment = (ResolverBundle) iter.next(); 162 ArrayList fragImports = (ArrayList) fragmentImports.get(fragment.bundleID); 163 if (fragImports != null) 164 resultList.addAll(fragImports); 165 } 166 return (ResolverImport[]) resultList.toArray(new ResolverImport[resultList.size()]); 167 } 168 169 ResolverExport[] getExportPackages() { 170 if (isFragment()) 171 return new ResolverExport[0]; 172 if (fragments == null || fragments.size() == 0) 173 return exports; 174 ArrayList resultList = new ArrayList(exports.length); 175 for (int i = 0; i < exports.length; i++) 176 resultList.add(exports[i]); 177 for (Iterator iter = fragments.iterator(); iter.hasNext();) { 178 ResolverBundle fragment = (ResolverBundle) iter.next(); 179 ArrayList fragExports = (ArrayList) fragmentExports.get(fragment.bundleID); 180 if (fragExports != null) 181 resultList.addAll(fragExports); 182 } 183 return (ResolverExport[]) resultList.toArray(new ResolverExport[resultList.size()]); 184 } 185 186 ResolverExport[] getSelectedExports() { 187 ResolverExport[] allExports = getExportPackages(); 188 int removedExports = 0; 189 for (int i = 0; i < allExports.length; i++) 190 if (allExports[i].isDropped()) 191 removedExports++; 192 if (removedExports == 0) 193 return allExports; 194 ResolverExport[] selectedExports = new ResolverExport[allExports.length - removedExports]; 195 int index = 0; 196 for (int i = 0; i < allExports.length; i++) { 197 if (allExports[i].isDropped()) 198 continue; 199 selectedExports[index] = allExports[i]; 200 index++; 201 } 202 return selectedExports; 203 } 204 205 BundleConstraint getHost() { 206 return host; 207 } 208 209 GenericCapability[] getGenericCapabilities() { 210 return capabilities; 211 } 212 213 BundleConstraint[] getRequires() { 214 if (isFragment()) 215 return new BundleConstraint[0]; 216 if (fragments == null || fragments.size() == 0) 217 return requires; 218 ArrayList resultList = new ArrayList(requires.length); 219 for (int i = 0; i < requires.length; i++) 220 resultList.add(requires[i]); 221 for (Iterator iter = fragments.iterator(); iter.hasNext();) { 222 ResolverBundle fragment = (ResolverBundle) iter.next(); 223 ArrayList fragRequires = (ArrayList) fragmentRequires.get(fragment.bundleID); 224 if (fragRequires != null) 225 resultList.addAll(fragRequires); 226 } 227 return (BundleConstraint[]) resultList.toArray(new BundleConstraint[resultList.size()]); 228 } 229 230 GenericConstraint[] getGenericRequires() { 231 if (isFragment() || fragments == null || fragments.size() == 0) 232 return genericReqiures; 233 ArrayList resultList = new ArrayList(genericReqiures.length); 234 for (int i = 0; i < genericReqiures.length; i++) 235 resultList.add(genericReqiures[i]); 236 for (Iterator iter = fragments.iterator(); iter.hasNext();) { 237 ResolverBundle fragment = (ResolverBundle) iter.next(); 238 ArrayList fragGenericRegs = (ArrayList) fragmentGenericRequires.get(fragment.bundleID); 239 if (fragGenericRegs != null) 240 resultList.addAll(fragGenericRegs); 241 } 242 return (GenericConstraint[]) resultList.toArray(new GenericConstraint[resultList.size()]); 243 } 244 245 BundleConstraint getRequire(String name) { 246 BundleConstraint[] allRequires = getRequires(); 247 for (int i = 0; i < allRequires.length; i++) 248 if (allRequires[i].getVersionConstraint().getName().equals(name)) 249 return allRequires[i]; 250 return null; 251 } 252 253 public BundleDescription getBundle() { 254 return (BundleDescription) getBaseDescription(); 255 } 256 257 ResolverImport getImport(String name) { 258 ResolverImport[] allImports = getImportPackages(); 259 for (int i = 0; i < allImports.length; i++) { 260 if (allImports[i].getName().equals(name)) { 261 return allImports[i]; 262 } 263 } 264 return null; 265 } 266 267 public String toString() { 268 return "[" + getBundle() + "]"; } 270 271 private void initFragments() { 272 if (fragments == null) 273 fragments = new ArrayList(1); 274 if (fragmentExports == null) 275 fragmentExports = new HashMap(1); 276 if (fragmentImports == null) 277 fragmentImports = new HashMap(1); 278 if (fragmentRequires == null) 279 fragmentRequires = new HashMap(1); 280 if (fragmentGenericRequires == null) 281 fragmentGenericRequires = new HashMap(1); 282 } 283 284 private boolean isImported(String packageName) { 285 ResolverImport[] allImports = getImportPackages(); 286 for (int i = 0; i < allImports.length; i++) 287 if (packageName.equals(allImports[i].getName())) 288 return true; 289 290 return false; 291 } 292 293 private boolean isExported(String packageName) { 294 ResolverExport export = getExport(packageName); 295 if (export == null) 296 return false; 297 return 0 > ((Integer ) export.getExportPackageDescription().getDirective(ExportPackageDescriptionImpl.EQUINOX_EE)).intValue(); 299 } 300 301 private boolean isRequired(String bundleName) { 302 return getRequire(bundleName) != null; 303 } 304 305 ResolverExport[] attachFragment(ResolverBundle fragment, boolean dynamicAttach) { 306 if (isFragment()) 307 return new ResolverExport[0]; if (!getBundle().attachFragments() || (isResolved() && !getBundle().dynamicFragments())) 309 return new ResolverExport[0]; if (fragment.getHost().getNumPossibleSuppliers() > 0 && !((HostSpecification) fragment.getHost().getVersionConstraint()).isMultiHost()) 311 return new ResolverExport[0]; 313 ImportPackageSpecification[] newImports = fragment.getBundle().getImportPackages(); 314 BundleSpecification[] newRequires = fragment.getBundle().getRequiredBundles(); 315 ExportPackageDescription[] newExports = fragment.getBundle().getExportPackages(); 316 GenericSpecification[] newGenericRequires = fragment.getBundle().getGenericRequires(); 317 318 if (dynamicAttach && constraintsConflict(fragment.getBundle(), newImports, newRequires, newGenericRequires)) 320 return new ResolverExport[0]; if (isResolved() && newExports.length > 0) 322 fragment.setNewFragmentExports(true); 323 324 initFragments(); 325 if (fragments.contains(fragment)) 326 return new ResolverExport[0]; 327 fragments.add(fragment); 328 fragment.getHost().addPossibleSupplier(this); 329 330 if (newImports.length > 0) { 331 ArrayList hostImports = new ArrayList(newImports.length); 332 for (int i = 0; i < newImports.length; i++) 333 if (!isImported(newImports[i].getName())) 334 hostImports.add(new ResolverImport(this, newImports[i])); 335 fragmentImports.put(fragment.bundleID, hostImports); 336 } 337 338 if (newRequires.length > 0) { 339 ArrayList hostRequires = new ArrayList(newRequires.length); 340 for (int i = 0; i < newRequires.length; i++) 341 if (!isRequired(newRequires[i].getName())) 342 hostRequires.add(new BundleConstraint(this, newRequires[i])); 343 fragmentRequires.put(fragment.bundleID, hostRequires); 344 } 345 346 if (newGenericRequires.length > 0) { 347 ArrayList hostGenericRequires = new ArrayList(newGenericRequires.length); 348 for (int i = 0; i < newGenericRequires.length; i++) 349 hostGenericRequires.add(new GenericConstraint(this, newGenericRequires[i])); 350 fragmentGenericRequires.put(fragment.bundleID, hostGenericRequires); 351 } 352 353 ArrayList hostExports = new ArrayList(newExports.length); 354 if (newExports.length > 0 && dynamicAttach) { 355 StateObjectFactory factory = resolver.getState().getFactory(); 356 for (int i = 0; i < newExports.length; i++) { 357 if (!isExported(newExports[i].getName())) { 358 ExportPackageDescription hostExport = factory.createExportPackageDescription(newExports[i].getName(), newExports[i].getVersion(), newExports[i].getDirectives(), newExports[i].getAttributes(), newExports[i].isRoot(), getBundle()); 359 hostExports.add(new ResolverExport(this, hostExport)); 360 } 361 } 362 fragmentExports.put(fragment.bundleID, hostExports); 363 } 364 return (ResolverExport[]) hostExports.toArray(new ResolverExport[hostExports.size()]); 365 } 366 367 boolean constraintsConflict(BundleDescription fragment, ImportPackageSpecification[] newImports, BundleSpecification[] newRequires, GenericSpecification[] newGenericRequires) { 368 boolean result = false; 372 for (int i = 0; i < newImports.length; i++) { 373 ResolverImport hostImport = getImport(newImports[i].getName()); 374 ResolverExport resolvedExport = (ResolverExport) (hostImport == null ? null : hostImport.getSelectedSupplier()); 375 if ((resolvedExport == null && isResolved()) || (resolvedExport != null && !newImports[i].isSatisfiedBy(resolvedExport.getExportPackageDescription()))) { 376 result = true; 377 resolver.getState().addResolverError(fragment, ResolverError.FRAGMENT_CONFLICT, newImports[i].toString(), newImports[i]); 378 } 379 } 380 for (int i = 0; i < newRequires.length; i++) { 381 BundleConstraint hostRequire = getRequire(newRequires[i].getName()); 382 ResolverBundle resolvedRequire = (ResolverBundle) (hostRequire == null ? null : hostRequire.getSelectedSupplier()); 383 if ((resolvedRequire == null && isResolved()) || (resolvedRequire != null && !newRequires[i].isSatisfiedBy(resolvedRequire.getBundle()))) { 384 result = true; 385 resolver.getState().addResolverError(fragment, ResolverError.FRAGMENT_CONFLICT, newRequires[i].toString(), newRequires[i]); 386 } 387 } 388 if (isResolved() && newGenericRequires != null && newGenericRequires.length > 0) 391 result = true; 392 return result; 393 } 394 395 private void setNewFragmentExports(boolean newFragmentExports) { 396 this.newFragmentExports = newFragmentExports; 397 } 398 399 boolean isNewFragmentExports() { 400 return newFragmentExports; 401 } 402 403 ResolverExport[] detachFragment(ResolverBundle fragment, ResolverConstraint reason) { 404 if (isFragment()) 405 return new ResolverExport[0]; 406 initFragments(); 407 408 if (!fragments.remove(fragment)) 409 return new ResolverExport[0]; 410 411 fragment.setNewFragmentExports(false); 412 fragment.getHost().removePossibleSupplier(this); 413 ArrayList fragImports = (ArrayList) fragmentImports.remove(fragment.bundleID); 414 ArrayList fragRequires = (ArrayList) fragmentRequires.remove(fragment.bundleID); 415 ArrayList removedExports = (ArrayList) fragmentExports.remove(fragment.bundleID); 416 fragmentGenericRequires.remove(fragment.bundleID); 417 if (reason != null) { 418 ResolverBundle[] remainingFrags = (ResolverBundle[]) fragments.toArray(new ResolverBundle[fragments.size()]); 419 for (int i = 0; i < remainingFrags.length; i++) { 420 resolver.getResolverExports().remove(detachFragment(remainingFrags[i], null)); 421 VersionConstraint[] constraints; 422 if (reason instanceof ResolverImport) 423 constraints = remainingFrags[i].getBundle().getImportPackages(); 424 else 425 constraints = remainingFrags[i].getBundle().getRequiredBundles(); 426 for (int j = 0; j < constraints.length; j++) 427 if (reason.getName().equals(constraints[j].getName())) 428 continue; resolver.getResolverExports().put(attachFragment(remainingFrags[i], true)); 430 ArrayList newImports = (ArrayList) fragmentImports.get(remainingFrags[i].bundleID); 431 if (newImports != null && fragImports != null) 432 for (Iterator iNewImports = newImports.iterator(); iNewImports.hasNext();) { 433 ResolverImport newImport = (ResolverImport) iNewImports.next(); 434 for (Iterator iOldImports = fragImports.iterator(); iOldImports.hasNext();) { 435 ResolverImport oldImport = (ResolverImport) iOldImports.next(); 436 if (newImport.getName().equals(oldImport.getName())) 437 newImport.setPossibleSuppliers(oldImport.getPossibleSuppliers()); 438 } 439 } 440 ArrayList newRequires = (ArrayList) fragmentRequires.get(remainingFrags[i].bundleID); 441 if (newRequires != null && fragRequires != null) 442 for (Iterator iNewRequires = newRequires.iterator(); iNewRequires.hasNext();) { 443 BundleConstraint newRequire = (BundleConstraint) iNewRequires.next(); 444 for (Iterator iOldRequires = fragRequires.iterator(); iOldRequires.hasNext();) { 445 BundleConstraint oldRequire = (BundleConstraint) iOldRequires.next(); 446 if (newRequire.getName().equals(oldRequire.getName())) 447 newRequire.setPossibleSuppliers(oldRequire.getPossibleSuppliers()); 448 } 449 } 450 } 451 } 452 return removedExports == null ? new ResolverExport[0] : (ResolverExport[]) removedExports.toArray(new ResolverExport[removedExports.size()]); 453 } 454 455 void detachAllFragments() { 456 if (fragments == null) 457 return; 458 ResolverBundle[] allFragments = (ResolverBundle[]) fragments.toArray(new ResolverBundle[fragments.size()]); 459 for (int i = 0; i < allFragments.length; i++) 460 detachFragment(allFragments[i], null); 461 } 462 463 boolean isResolvable() { 464 return resolvable; 465 } 466 467 void setResolvable(boolean resolvable) { 468 this.resolvable = resolvable; 469 } 470 471 void addExport(ResolverExport re) { 472 ResolverExport[] newExports = new ResolverExport[exports.length + 1]; 473 for (int i = 0; i < exports.length; i++) 474 newExports[i] = exports[i]; 475 newExports[exports.length] = re; 476 exports = newExports; 477 } 478 479 ResolverImpl getResolver() { 480 return resolver; 481 } 482 483 void clearRefs() { 484 if (refs != null) 485 refs.clear(); 486 } 487 488 void addRef(ResolverBundle ref) { 489 if (refs != null && !refs.contains(ref)) 490 refs.add(ref); 491 } 492 493 int getRefs() { 494 return refs == null ? 0 : refs.size(); 495 } 496 497 ResolverBundle[] getFragments() { 498 return fragments == null ? new ResolverBundle[0] : (ResolverBundle[]) fragments.toArray(new ResolverBundle[fragments.size()]); 499 } 500 501 508 public int compareTo(Object o) { 509 String bsn = getName(); 510 String otherBsn = ((ResolverBundle) o).getName(); 511 if (bsn == null) 512 return otherBsn == null ? 0 : 1; 513 return otherBsn == null ? -1 : bsn.compareTo(otherBsn); 514 } 515 } 516 | Popular Tags |