1 /******************************************************************************* 2 * Copyright (c) 2003, 2016 IBM Corporation and others. 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 * IBM Corporation - initial API and implementation 13 * Danail Nachev - ProSyst - bug 218625 14 * Rob Harrop - SpringSource Inc. (bug 247522 and 255520) 15 *******************************************************************************/ 16 package org.eclipse.osgi.internal.resolver; 17 18 import java.io.IOException; 19 import java.net.URL; 20 import java.util.ArrayList; 21 import java.util.Collection; 22 import java.util.Collections; 23 import java.util.HashMap; 24 import java.util.Iterator; 25 import java.util.List; 26 import java.util.Map; 27 import org.eclipse.osgi.framework.util.KeyedElement; 28 import org.eclipse.osgi.service.resolver.BaseDescription; 29 import org.eclipse.osgi.service.resolver.BundleDescription; 30 import org.eclipse.osgi.service.resolver.BundleSpecification; 31 import org.eclipse.osgi.service.resolver.ExportPackageDescription; 32 import org.eclipse.osgi.service.resolver.GenericDescription; 33 import org.eclipse.osgi.service.resolver.GenericSpecification; 34 import org.eclipse.osgi.service.resolver.HostSpecification; 35 import org.eclipse.osgi.service.resolver.ImportPackageSpecification; 36 import org.eclipse.osgi.service.resolver.NativeCodeDescription; 37 import org.eclipse.osgi.service.resolver.NativeCodeSpecification; 38 import org.eclipse.osgi.service.resolver.State; 39 import org.eclipse.osgi.service.resolver.StateWire; 40 import org.eclipse.osgi.service.resolver.VersionConstraint; 41 import org.osgi.framework.Bundle; 42 import org.osgi.framework.BundleReference; 43 import org.osgi.framework.Constants; 44 import org.osgi.framework.wiring.BundleCapability; 45 import org.osgi.framework.wiring.BundleRequirement; 46 import org.osgi.framework.wiring.BundleRevision; 47 import org.osgi.framework.wiring.BundleWire; 48 import org.osgi.framework.wiring.BundleWiring; 49 import org.osgi.resource.Capability; 50 import org.osgi.resource.Requirement; 51 import org.osgi.resource.Wire; 52 53 public final class BundleDescriptionImpl extends BaseDescriptionImpl implements BundleDescription, KeyedElement { 54 static final String[] EMPTY_STRING = new String[0]; 55 static final ImportPackageSpecification[] EMPTY_IMPORTS = new ImportPackageSpecification[0]; 56 static final BundleSpecification[] EMPTY_BUNDLESPECS = new BundleSpecification[0]; 57 static final ExportPackageDescription[] EMPTY_EXPORTS = new ExportPackageDescription[0]; 58 static final BundleDescription[] EMPTY_BUNDLEDESCS = new BundleDescription[0]; 59 static final GenericSpecification[] EMPTY_GENERICSPECS = new GenericSpecification[0]; 60 static final GenericDescription[] EMPTY_GENERICDESCS = new GenericDescription[0]; 61 static final RuntimePermission GET_CLASSLOADER_PERM = new RuntimePermission("getClassLoader"); //$NON-NLS-1$ 62 63 static final int RESOLVED = 0x01; 64 static final int SINGLETON = 0x02; 65 static final int REMOVAL_PENDING = 0x04; 66 static final int FULLY_LOADED = 0x08; 67 static final int LAZY_LOADED = 0x10; 68 static final int HAS_DYNAMICIMPORT = 0x20; 69 static final int ATTACH_FRAGMENTS = 0x40; 70 static final int DYNAMIC_FRAGMENTS = 0x80; 71 72 // set to fully loaded and allow dynamic fragments by default 73 private volatile int stateBits = FULLY_LOADED | ATTACH_FRAGMENTS | DYNAMIC_FRAGMENTS; 74 75 private volatile long bundleId = -1; 76 volatile HostSpecification host; //null if the bundle is not a fragment. volatile to allow unsynchronized checks for null 77 private volatile StateImpl containingState; 78 79 private volatile int lazyDataOffset = -1; 80 private volatile int lazyDataSize = -1; 81 82 private List<BundleDescription> dependencies; 83 private List<BundleDescription> dependents; 84 private String[] mandatory; 85 private Map<String, Object> attributes; 86 private Map<String, String> arbitraryDirectives; 87 88 private volatile LazyData lazyData; 89 private volatile int equinox_ee = -1; 90 91 private DescriptionWiring bundleWiring; 92 BundleDescriptionImpl()93 public BundleDescriptionImpl() { 94 // 95 } 96 getBundleId()97 public long getBundleId() { 98 return bundleId; 99 } 100 getSymbolicName()101 public String getSymbolicName() { 102 return getName(); 103 } 104 getSupplier()105 public BundleDescription getSupplier() { 106 return this; 107 } 108 getLocation()109 public String getLocation() { 110 LazyData currentData = loadLazyData(); 111 synchronized (this.monitor) { 112 return currentData.location; 113 } 114 } 115 getPlatformFilter()116 public String getPlatformFilter() { 117 LazyData currentData = loadLazyData(); 118 synchronized (this.monitor) { 119 return currentData.platformFilter; 120 } 121 } 122 getExecutionEnvironments()123 public String[] getExecutionEnvironments() { 124 LazyData currentData = loadLazyData(); 125 synchronized (this.monitor) { 126 if (currentData.executionEnvironments == null) 127 return EMPTY_STRING; 128 return currentData.executionEnvironments; 129 } 130 } 131 getImportPackages()132 public ImportPackageSpecification[] getImportPackages() { 133 LazyData currentData = loadLazyData(); 134 synchronized (this.monitor) { 135 if (currentData.importPackages == null) 136 return EMPTY_IMPORTS; 137 return currentData.importPackages; 138 } 139 } 140 getAddedDynamicImportPackages()141 public ImportPackageSpecification[] getAddedDynamicImportPackages() { 142 LazyData currentData = loadLazyData(); 143 synchronized (this.monitor) { 144 if (currentData.addedDynamicImports == null) 145 return EMPTY_IMPORTS; 146 return currentData.addedDynamicImports.toArray(new ImportPackageSpecification[currentData.addedDynamicImports.size()]); 147 } 148 } 149 getRequiredBundles()150 public BundleSpecification[] getRequiredBundles() { 151 LazyData currentData = loadLazyData(); 152 synchronized (this.monitor) { 153 if (currentData.requiredBundles == null) 154 return EMPTY_BUNDLESPECS; 155 return currentData.requiredBundles; 156 } 157 } 158 getGenericRequires()159 public GenericSpecification[] getGenericRequires() { 160 LazyData currentData = loadLazyData(); 161 synchronized (this.monitor) { 162 if (currentData.genericRequires == null) 163 return EMPTY_GENERICSPECS; 164 return currentData.genericRequires; 165 } 166 } 167 getGenericCapabilities()168 public GenericDescription[] getGenericCapabilities() { 169 LazyData currentData = loadLazyData(); 170 synchronized (this.monitor) { 171 if (currentData.genericCapabilities == null) 172 return EMPTY_GENERICDESCS; 173 return currentData.genericCapabilities; 174 } 175 } 176 getNativeCodeSpecification()177 public NativeCodeSpecification getNativeCodeSpecification() { 178 LazyData currentData = loadLazyData(); 179 synchronized (this.monitor) { 180 return currentData.nativeCode; 181 } 182 } 183 getExportPackages()184 public ExportPackageDescription[] getExportPackages() { 185 LazyData currentData = loadLazyData(); 186 synchronized (this.monitor) { 187 return currentData.exportPackages == null ? EMPTY_EXPORTS : currentData.exportPackages; 188 } 189 } 190 isResolved()191 public boolean isResolved() { 192 return (stateBits & RESOLVED) != 0; 193 } 194 getContainingState()195 public State getContainingState() { 196 return containingState; 197 } 198 getFragments()199 public BundleDescription[] getFragments() { 200 if (host != null) 201 return EMPTY_BUNDLEDESCS; 202 StateImpl currentState = (StateImpl) getContainingState(); 203 if (currentState == null) 204 throw new IllegalStateException("BundleDescription does not belong to a state."); //$NON-NLS-1$ 205 return currentState.getFragments(this); 206 } 207 getHost()208 public HostSpecification getHost() { 209 return host; 210 } 211 isSingleton()212 public boolean isSingleton() { 213 return (stateBits & SINGLETON) != 0; 214 } 215 isRemovalPending()216 public boolean isRemovalPending() { 217 return (stateBits & REMOVAL_PENDING) != 0; 218 } 219 hasDynamicImports()220 public boolean hasDynamicImports() { 221 return (stateBits & HAS_DYNAMICIMPORT) != 0; 222 } 223 attachFragments()224 public boolean attachFragments() { 225 return (stateBits & ATTACH_FRAGMENTS) != 0; 226 } 227 dynamicFragments()228 public boolean dynamicFragments() { 229 return (stateBits & DYNAMIC_FRAGMENTS) != 0; 230 } 231 getSelectedExports()232 public ExportPackageDescription[] getSelectedExports() { 233 LazyData currentData = loadLazyData(); 234 synchronized (this.monitor) { 235 if (currentData.selectedExports == null) 236 return EMPTY_EXPORTS; 237 return currentData.selectedExports; 238 } 239 } 240 getSelectedGenericCapabilities()241 public GenericDescription[] getSelectedGenericCapabilities() { 242 LazyData currentData = loadLazyData(); 243 synchronized (this.monitor) { 244 if (currentData.selectedCapabilities == null) 245 return EMPTY_GENERICDESCS; 246 return currentData.selectedCapabilities; 247 } 248 } 249 getSubstitutedExports()250 public ExportPackageDescription[] getSubstitutedExports() { 251 LazyData currentData = loadLazyData(); 252 synchronized (this.monitor) { 253 if (currentData.substitutedExports == null) 254 return EMPTY_EXPORTS; 255 return currentData.substitutedExports; 256 } 257 } 258 getResolvedRequires()259 public BundleDescription[] getResolvedRequires() { 260 LazyData currentData = loadLazyData(); 261 synchronized (this.monitor) { 262 if (currentData.resolvedRequires == null) 263 return EMPTY_BUNDLEDESCS; 264 return currentData.resolvedRequires; 265 } 266 } 267 getResolvedImports()268 public ExportPackageDescription[] getResolvedImports() { 269 LazyData currentData = loadLazyData(); 270 synchronized (this.monitor) { 271 if (currentData.resolvedImports == null) 272 return EMPTY_EXPORTS; 273 return currentData.resolvedImports; 274 } 275 } 276 getResolvedGenericRequires()277 public GenericDescription[] getResolvedGenericRequires() { 278 LazyData currentData = loadLazyData(); 279 synchronized (this.monitor) { 280 if (currentData.resolvedCapabilities == null) 281 return EMPTY_GENERICDESCS; 282 return currentData.resolvedCapabilities; 283 } 284 } 285 getWires()286 public Map<String, List<StateWire>> getWires() { 287 LazyData currentData = loadLazyData(); 288 synchronized (this.monitor) { 289 if (currentData.stateWires == null) { 290 currentData.stateWires = new HashMap<>(0); 291 } 292 return currentData.stateWires; 293 } 294 } 295 getWiresInternal()296 Map<String, List<StateWire>> getWiresInternal() { 297 LazyData currentData = loadLazyData(); 298 synchronized (this.monitor) { 299 return currentData.stateWires; 300 } 301 } 302 setBundleId(long bundleId)303 protected void setBundleId(long bundleId) { 304 this.bundleId = bundleId; 305 } 306 setSymbolicName(String symbolicName)307 protected void setSymbolicName(String symbolicName) { 308 setName(symbolicName); 309 } 310 setLocation(String location)311 protected void setLocation(String location) { 312 synchronized (this.monitor) { 313 checkLazyData(); 314 lazyData.location = location; 315 } 316 } 317 setPlatformFilter(String platformFilter)318 protected void setPlatformFilter(String platformFilter) { 319 synchronized (this.monitor) { 320 checkLazyData(); 321 lazyData.platformFilter = platformFilter; 322 } 323 } 324 setExecutionEnvironments(String[] executionEnvironments)325 protected void setExecutionEnvironments(String[] executionEnvironments) { 326 synchronized (this.monitor) { 327 checkLazyData(); 328 lazyData.executionEnvironments = executionEnvironments == null || executionEnvironments.length > 0 ? executionEnvironments : EMPTY_STRING; 329 } 330 } 331 setExportPackages(ExportPackageDescription[] exportPackages)332 protected void setExportPackages(ExportPackageDescription[] exportPackages) { 333 synchronized (this.monitor) { 334 checkLazyData(); 335 lazyData.exportPackages = exportPackages == null || exportPackages.length > 0 ? exportPackages : EMPTY_EXPORTS; 336 if (exportPackages != null) { 337 for (ExportPackageDescription exportPackage : exportPackages) { 338 ((ExportPackageDescriptionImpl) exportPackage).setExporter(this); 339 } 340 } 341 } 342 } 343 setImportPackages(ImportPackageSpecification[] importPackages)344 protected void setImportPackages(ImportPackageSpecification[] importPackages) { 345 synchronized (this.monitor) { 346 checkLazyData(); 347 lazyData.importPackages = importPackages == null || importPackages.length > 0 ? importPackages : EMPTY_IMPORTS; 348 if (importPackages != null) { 349 for (ImportPackageSpecification importPackage : importPackages) { 350 ((ImportPackageSpecificationImpl) importPackage).setBundle(this); 351 if (ImportPackageSpecification.RESOLUTION_DYNAMIC.equals(importPackage.getDirective(Constants.RESOLUTION_DIRECTIVE))) { 352 stateBits |= HAS_DYNAMICIMPORT; 353 } 354 } 355 } 356 } 357 } 358 setRequiredBundles(BundleSpecification[] requiredBundles)359 protected void setRequiredBundles(BundleSpecification[] requiredBundles) { 360 synchronized (this.monitor) { 361 checkLazyData(); 362 lazyData.requiredBundles = requiredBundles == null || requiredBundles.length > 0 ? requiredBundles : EMPTY_BUNDLESPECS; 363 if (requiredBundles != null) 364 for (BundleSpecification requiredBundle : requiredBundles) { 365 ((VersionConstraintImpl) requiredBundle).setBundle(this); 366 } 367 } 368 } 369 setGenericCapabilities(GenericDescription[] genericCapabilities)370 protected void setGenericCapabilities(GenericDescription[] genericCapabilities) { 371 synchronized (this.monitor) { 372 checkLazyData(); 373 lazyData.genericCapabilities = genericCapabilities == null || genericCapabilities.length > 0 ? genericCapabilities : EMPTY_GENERICDESCS; 374 if (genericCapabilities != null) 375 for (GenericDescription genericCapability : genericCapabilities) { 376 ((GenericDescriptionImpl) genericCapability).setSupplier(this); 377 } 378 } 379 } 380 setGenericRequires(GenericSpecification[] genericRequires)381 protected void setGenericRequires(GenericSpecification[] genericRequires) { 382 synchronized (this.monitor) { 383 checkLazyData(); 384 lazyData.genericRequires = genericRequires == null || genericRequires.length > 0 ? genericRequires : EMPTY_GENERICSPECS; 385 if (genericRequires != null) 386 for (GenericSpecification genericRequire : genericRequires) { 387 ((VersionConstraintImpl) genericRequire).setBundle(this); 388 } 389 } 390 } 391 setNativeCodeSpecification(NativeCodeSpecification nativeCode)392 protected void setNativeCodeSpecification(NativeCodeSpecification nativeCode) { 393 synchronized (this.monitor) { 394 checkLazyData(); 395 lazyData.nativeCode = nativeCode; 396 if (nativeCode != null) { 397 ((NativeCodeSpecificationImpl) nativeCode).setBundle(this); 398 NativeCodeDescription[] suppliers = nativeCode.getPossibleSuppliers(); 399 if (suppliers != null) 400 for (NativeCodeDescription supplier : suppliers) { 401 ((NativeCodeDescriptionImpl) supplier).setSupplier(this); 402 } 403 } 404 } 405 } 406 getStateBits()407 protected int getStateBits() { 408 return stateBits; 409 } 410 setStateBit(int stateBit, boolean on)411 protected void setStateBit(int stateBit, boolean on) { 412 synchronized (this.monitor) { 413 if (on) { 414 stateBits |= stateBit; 415 } else { 416 stateBits &= ~stateBit; 417 if (stateBit == RESOLVED) { 418 if (bundleWiring != null) 419 bundleWiring.invalidate(); 420 bundleWiring = null; 421 } 422 } 423 } 424 } 425 setContainingState(State value)426 protected void setContainingState(State value) { 427 synchronized (this.monitor) { 428 containingState = (StateImpl) value; 429 if (containingState != null && containingState.getReader() != null) { 430 if (containingState.getReader().isLazyLoaded()) 431 stateBits |= LAZY_LOADED; 432 else 433 stateBits &= ~LAZY_LOADED; 434 } else { 435 stateBits &= ~LAZY_LOADED; 436 } 437 } 438 } 439 setHost(HostSpecification host)440 protected void setHost(HostSpecification host) { 441 synchronized (this.monitor) { 442 this.host = host; 443 if (host != null) { 444 ((VersionConstraintImpl) host).setBundle(this); 445 } 446 } 447 } 448 setLazyLoaded(boolean lazyLoad)449 protected void setLazyLoaded(boolean lazyLoad) { 450 loadLazyData(); 451 synchronized (this.monitor) { 452 if (lazyLoad) 453 stateBits |= LAZY_LOADED; 454 else 455 stateBits &= ~LAZY_LOADED; 456 } 457 } 458 setSelectedExports(ExportPackageDescription[] selectedExports)459 protected void setSelectedExports(ExportPackageDescription[] selectedExports) { 460 synchronized (this.monitor) { 461 checkLazyData(); 462 lazyData.selectedExports = selectedExports == null || selectedExports.length > 0 ? selectedExports : EMPTY_EXPORTS; 463 if (selectedExports != null) { 464 for (ExportPackageDescription selectedExport : selectedExports) { 465 ((ExportPackageDescriptionImpl) selectedExport).setExporter(this); 466 } 467 } 468 } 469 } 470 setSelectedCapabilities(GenericDescription[] selectedCapabilities)471 protected void setSelectedCapabilities(GenericDescription[] selectedCapabilities) { 472 synchronized (this.monitor) { 473 checkLazyData(); 474 lazyData.selectedCapabilities = selectedCapabilities == null || selectedCapabilities.length > 0 ? selectedCapabilities : EMPTY_GENERICDESCS; 475 if (selectedCapabilities != null) { 476 for (GenericDescription capability : selectedCapabilities) { 477 ((GenericDescriptionImpl) capability).setSupplier(this); 478 } 479 } 480 } 481 } 482 setSubstitutedExports(ExportPackageDescription[] substitutedExports)483 protected void setSubstitutedExports(ExportPackageDescription[] substitutedExports) { 484 synchronized (this.monitor) { 485 checkLazyData(); 486 lazyData.substitutedExports = substitutedExports != null && substitutedExports.length > 0 ? substitutedExports : EMPTY_EXPORTS; 487 } 488 } 489 setResolvedImports(ExportPackageDescription[] resolvedImports)490 protected void setResolvedImports(ExportPackageDescription[] resolvedImports) { 491 synchronized (this.monitor) { 492 checkLazyData(); 493 lazyData.resolvedImports = resolvedImports == null || resolvedImports.length > 0 ? resolvedImports : EMPTY_EXPORTS; 494 } 495 } 496 setResolvedRequires(BundleDescription[] resolvedRequires)497 protected void setResolvedRequires(BundleDescription[] resolvedRequires) { 498 synchronized (this.monitor) { 499 checkLazyData(); 500 lazyData.resolvedRequires = resolvedRequires == null || resolvedRequires.length > 0 ? resolvedRequires : EMPTY_BUNDLEDESCS; 501 } 502 } 503 setResolvedCapabilities(GenericDescription[] resolvedCapabilities)504 protected void setResolvedCapabilities(GenericDescription[] resolvedCapabilities) { 505 synchronized (this.monitor) { 506 checkLazyData(); 507 lazyData.resolvedCapabilities = resolvedCapabilities == null || resolvedCapabilities.length > 0 ? resolvedCapabilities : EMPTY_GENERICDESCS; 508 } 509 } 510 setStateWires(Map<String, List<StateWire>> stateWires)511 protected void setStateWires(Map<String, List<StateWire>> stateWires) { 512 synchronized (this.monitor) { 513 checkLazyData(); 514 lazyData.stateWires = stateWires; 515 } 516 } 517 clearAddedDynamicImportPackages()518 void clearAddedDynamicImportPackages() { 519 synchronized (this.monitor) { 520 checkLazyData(); 521 lazyData.addedDynamicImports = null; 522 } 523 } 524 525 @Override toString()526 public String toString() { 527 if (getSymbolicName() == null) 528 return "[" + getBundleId() + "]"; //$NON-NLS-1$ //$NON-NLS-2$ 529 return getSymbolicName() + "_" + getVersion(); //$NON-NLS-1$ 530 } 531 getKey()532 public Object getKey() { 533 return new Long(bundleId); 534 } 535 compare(KeyedElement other)536 public boolean compare(KeyedElement other) { 537 if (!(other instanceof BundleDescriptionImpl)) 538 return false; 539 BundleDescriptionImpl otherBundleDescription = (BundleDescriptionImpl) other; 540 return bundleId == otherBundleDescription.bundleId; 541 } 542 getKeyHashCode()543 public int getKeyHashCode() { 544 return (int) (bundleId ^ (bundleId >>> 32)); 545 } 546 547 /* TODO Determine if we need more than just Object ID type of hashcode. 548 public int hashCode() { 549 if (getSymbolicName() == null) 550 return (int) (bundleId % Integer.MAX_VALUE); 551 return (int) ((bundleId * (getSymbolicName().hashCode())) % Integer.MAX_VALUE); 552 } 553 */ 554 removeDependencies()555 protected void removeDependencies() { 556 synchronized (this.monitor) { 557 if (dependencies == null) 558 return; 559 Iterator<BundleDescription> iter = dependencies.iterator(); 560 while (iter.hasNext()) { 561 ((BundleDescriptionImpl) iter.next()).removeDependent(this); 562 } 563 dependencies = null; 564 } 565 } 566 addDependencies(BaseDescription[] newDependencies, boolean checkDups)567 protected void addDependencies(BaseDescription[] newDependencies, boolean checkDups) { 568 synchronized (this.monitor) { 569 if (newDependencies == null) 570 return; 571 if (!checkDups && dependencies == null) 572 dependencies = new ArrayList<>(newDependencies.length); 573 for (BaseDescription newDependency : newDependencies) { 574 addDependency((BaseDescriptionImpl) newDependency, checkDups); 575 } 576 } 577 } 578 addDependency(BaseDescriptionImpl dependency, boolean checkDups)579 protected void addDependency(BaseDescriptionImpl dependency, boolean checkDups) { 580 synchronized (this.monitor) { 581 BundleDescriptionImpl bundle = (BundleDescriptionImpl) dependency.getSupplier(); 582 if (bundle == this) 583 return; 584 if (dependencies == null) 585 dependencies = new ArrayList<>(10); 586 if (!checkDups || !dependencies.contains(bundle)) { 587 bundle.addDependent(this); 588 dependencies.add(bundle); 589 } 590 } 591 } 592 593 /* 594 * Gets all the bundle dependencies as a result of import-package or require-bundle. 595 * Self and fragment bundles are removed. 596 */ getBundleDependencies()597 List<BundleDescription> getBundleDependencies() { 598 synchronized (this.monitor) { 599 if (dependencies == null) 600 return new ArrayList<>(0); 601 ArrayList<BundleDescription> required = new ArrayList<>(dependencies.size()); 602 for (Iterator<BundleDescription> iter = dependencies.iterator(); iter.hasNext();) { 603 BundleDescription dep = iter.next(); 604 if (dep != this && dep.getHost() == null) 605 required.add(dep); 606 } 607 return required; 608 } 609 } 610 addDependent(BundleDescription dependent)611 protected void addDependent(BundleDescription dependent) { 612 synchronized (this.monitor) { 613 if (dependents == null) 614 dependents = new ArrayList<>(10); 615 // no need to check for duplicates here; this is only called in addDepenency which already checks for dups. 616 dependents.add(dependent); 617 } 618 } 619 removeDependent(BundleDescription dependent)620 protected void removeDependent(BundleDescription dependent) { 621 synchronized (this.monitor) { 622 if (dependents == null) 623 return; 624 dependents.remove(dependent); 625 } 626 } 627 getDependents()628 public BundleDescription[] getDependents() { 629 synchronized (this.monitor) { 630 if (dependents == null) 631 return EMPTY_BUNDLEDESCS; 632 return dependents.toArray(new BundleDescription[dependents.size()]); 633 } 634 } 635 hasDependents()636 boolean hasDependents() { 637 synchronized (this.monitor) { 638 return dependents == null ? false : dependents.size() > 0; 639 } 640 } 641 setFullyLoaded(boolean fullyLoaded)642 void setFullyLoaded(boolean fullyLoaded) { 643 synchronized (this.monitor) { 644 if (fullyLoaded) { 645 stateBits |= FULLY_LOADED; 646 } else { 647 stateBits &= ~FULLY_LOADED; 648 } 649 } 650 } 651 isFullyLoaded()652 boolean isFullyLoaded() { 653 return (stateBits & FULLY_LOADED) != 0; 654 } 655 setLazyDataOffset(int lazyDataOffset)656 void setLazyDataOffset(int lazyDataOffset) { 657 this.lazyDataOffset = lazyDataOffset; 658 } 659 getLazyDataOffset()660 int getLazyDataOffset() { 661 return this.lazyDataOffset; 662 } 663 setLazyDataSize(int lazyDataSize)664 void setLazyDataSize(int lazyDataSize) { 665 this.lazyDataSize = lazyDataSize; 666 } 667 getLazyDataSize()668 int getLazyDataSize() { 669 return this.lazyDataSize; 670 } 671 672 // DO NOT call while holding this.monitor loadLazyData()673 private LazyData loadLazyData() { 674 // TODO add back if ee min 1.2 adds holdsLock method 675 //if (Thread.holdsLock(this.monitor)) { 676 // throw new IllegalStateException("Should not call fullyLoad() holding monitor."); //$NON-NLS-1$ 677 //} 678 if ((stateBits & LAZY_LOADED) == 0) 679 return this.lazyData; 680 681 StateImpl currentState = (StateImpl) getContainingState(); 682 StateReader reader = currentState == null ? null : currentState.getReader(); 683 if (reader == null) 684 throw new IllegalStateException("No valid reader for the bundle description"); //$NON-NLS-1$ 685 686 synchronized (currentState.monitor) { 687 if (isFullyLoaded()) { 688 reader.setAccessedFlag(true); // set reader accessed flag 689 return this.lazyData; 690 } 691 try { 692 reader.fullyLoad(this); 693 return this.lazyData; 694 } catch (IOException e) { 695 throw new RuntimeException(e.getMessage(), e); // TODO not sure what to do here!! 696 } 697 } 698 } 699 addDynamicResolvedImport(ExportPackageDescriptionImpl result)700 void addDynamicResolvedImport(ExportPackageDescriptionImpl result) { 701 synchronized (this.monitor) { 702 // mark the dependency 703 addDependency(result, true); 704 // add the export to the list of the resolvedImports 705 checkLazyData(); 706 if (lazyData.resolvedImports == null) { 707 lazyData.resolvedImports = new ExportPackageDescription[] {result}; 708 return; 709 } 710 ExportPackageDescription[] newImports = new ExportPackageDescription[lazyData.resolvedImports.length + 1]; 711 System.arraycopy(lazyData.resolvedImports, 0, newImports, 0, lazyData.resolvedImports.length); 712 newImports[newImports.length - 1] = result; 713 lazyData.resolvedImports = newImports; 714 } 715 } 716 addDynamicImportPackages(ImportPackageSpecification[] dynamicImport)717 void addDynamicImportPackages(ImportPackageSpecification[] dynamicImport) { 718 LazyData currentData = loadLazyData(); 719 synchronized (this.monitor) { 720 if (currentData.addedDynamicImports == null) 721 currentData.addedDynamicImports = new ArrayList<>(); 722 for (ImportPackageSpecification addImport : dynamicImport) { 723 if (!ImportPackageSpecification.RESOLUTION_DYNAMIC.equals(addImport.getDirective(Constants.RESOLUTION_DIRECTIVE))) 724 throw new IllegalArgumentException("Import must be a dynamic import."); //$NON-NLS-1$ 725 } 726 adding: for (ImportPackageSpecification addImport : dynamicImport) { 727 for (ImportPackageSpecification currentImport : currentData.addedDynamicImports) { 728 if (equalImports(addImport, currentImport)) 729 continue adding; 730 } 731 ((ImportPackageSpecificationImpl) addImport).setBundle(this); 732 currentData.addedDynamicImports.add(addImport); 733 } 734 } 735 } 736 equalImports(ImportPackageSpecification addImport, ImportPackageSpecification currentImport)737 private boolean equalImports(ImportPackageSpecification addImport, ImportPackageSpecification currentImport) { 738 if (!isEqual(addImport.getName(), currentImport.getName())) 739 return false; 740 if (!isEqual(addImport.getVersionRange(), currentImport.getVersionRange())) 741 return false; 742 if (!isEqual(addImport.getBundleSymbolicName(), currentImport.getBundleSymbolicName())) 743 return false; 744 if (!isEqual(addImport.getBundleVersionRange(), currentImport.getBundleVersionRange())) 745 return false; 746 return isEqual(addImport.getAttributes(), currentImport.getAttributes()); 747 } 748 isEqual(Object o1, Object o2)749 private boolean isEqual(Object o1, Object o2) { 750 return (o1 == null) ? o2 == null : o1.equals(o2); 751 } 752 unload()753 void unload() { 754 StateImpl currentState = (StateImpl) getContainingState(); 755 StateReader reader = currentState == null ? null : currentState.getReader(); 756 if (reader == null) 757 throw new IllegalStateException("BundleDescription does not belong to a reader."); //$NON-NLS-1$ 758 synchronized (currentState.monitor) { 759 if ((stateBits & LAZY_LOADED) == 0) 760 return; 761 if (!isFullyLoaded()) 762 return; 763 synchronized (this.monitor) { 764 setFullyLoaded(false); 765 lazyData = null; 766 } 767 } 768 } 769 setDynamicStamps(Map<String, Long> dynamicStamps)770 void setDynamicStamps(Map<String, Long> dynamicStamps) { 771 synchronized (this.monitor) { 772 checkLazyData(); 773 lazyData.dynamicStamps = dynamicStamps; 774 } 775 } 776 setDynamicStamp(String requestedPackage, Long timestamp)777 void setDynamicStamp(String requestedPackage, Long timestamp) { 778 synchronized (this.monitor) { 779 checkLazyData(); 780 if (lazyData.dynamicStamps == null) { 781 if (timestamp == null) 782 return; 783 lazyData.dynamicStamps = new HashMap<>(); 784 } 785 if (timestamp == null) 786 lazyData.dynamicStamps.remove(requestedPackage); 787 else 788 lazyData.dynamicStamps.put(requestedPackage, timestamp); 789 } 790 } 791 getDynamicStamp(String requestedPackage)792 long getDynamicStamp(String requestedPackage) { 793 LazyData currentData = loadLazyData(); 794 synchronized (this.monitor) { 795 Long stamp = currentData.dynamicStamps == null ? null : (Long) currentData.dynamicStamps.get(requestedPackage); 796 return stamp == null ? 0 : stamp.longValue(); 797 } 798 } 799 getDynamicStamps()800 Map<String, Long> getDynamicStamps() { 801 LazyData currentData = loadLazyData(); 802 synchronized (this.monitor) { 803 return currentData.dynamicStamps; 804 } 805 } 806 setEquinoxEE(int equinox_ee)807 public void setEquinoxEE(int equinox_ee) { 808 this.equinox_ee = equinox_ee; 809 } 810 getEquinoxEE()811 public int getEquinoxEE() { 812 return equinox_ee; 813 } 814 checkLazyData()815 private void checkLazyData() { 816 if (lazyData == null) 817 lazyData = new LazyData(); 818 } 819 820 final class LazyData { 821 String location; 822 String platformFilter; 823 824 BundleSpecification[] requiredBundles; 825 ExportPackageDescription[] exportPackages; 826 ImportPackageSpecification[] importPackages; 827 GenericDescription[] genericCapabilities; 828 GenericSpecification[] genericRequires; 829 NativeCodeSpecification nativeCode; 830 831 ExportPackageDescription[] selectedExports; 832 GenericDescription[] selectedCapabilities; 833 BundleDescription[] resolvedRequires; 834 ExportPackageDescription[] resolvedImports; 835 GenericDescription[] resolvedCapabilities; 836 ExportPackageDescription[] substitutedExports; 837 String[] executionEnvironments; 838 839 Map<String, Long> dynamicStamps; 840 Map<String, List<StateWire>> stateWires; 841 // Note that this is not persisted in the state cache 842 List<ImportPackageSpecification> addedDynamicImports; 843 } 844 getAttributes()845 public Map<String, Object> getAttributes() { 846 synchronized (this.monitor) { 847 return attributes; 848 } 849 } 850 851 @SuppressWarnings("unchecked") setAttributes(Map<String, ?> attributes)852 void setAttributes(Map<String, ?> attributes) { 853 synchronized (this.monitor) { 854 this.attributes = (Map<String, Object>) attributes; 855 } 856 } 857 getDirective(String key)858 Object getDirective(String key) { 859 synchronized (this.monitor) { 860 if (Constants.MANDATORY_DIRECTIVE.equals(key)) 861 return mandatory; 862 if (Constants.SINGLETON_DIRECTIVE.equals(key)) 863 return isSingleton() ? Boolean.TRUE : Boolean.FALSE; 864 if (Constants.FRAGMENT_ATTACHMENT_DIRECTIVE.equals(key)) { 865 if (!attachFragments()) 866 return Constants.FRAGMENT_ATTACHMENT_NEVER; 867 if (dynamicFragments()) 868 return Constants.FRAGMENT_ATTACHMENT_ALWAYS; 869 return Constants.FRAGMENT_ATTACHMENT_RESOLVETIME; 870 } 871 } 872 return null; 873 } 874 setDirective(String key, Object value)875 void setDirective(String key, Object value) { 876 // only pay attention to mandatory directive for now; others are set with setState method 877 if (Constants.MANDATORY_DIRECTIVE.equals(key)) 878 mandatory = (String[]) value; 879 } 880 881 @SuppressWarnings("unchecked") setArbitraryDirectives(Map<String, ?> directives)882 void setArbitraryDirectives(Map<String, ?> directives) { 883 synchronized (this.monitor) { 884 this.arbitraryDirectives = (Map<String, String>) directives; 885 } 886 } 887 getArbitraryDirectives()888 Map<String, String> getArbitraryDirectives() { 889 synchronized (this.monitor) { 890 return arbitraryDirectives; 891 } 892 } 893 getDeclaredDirectives()894 public Map<String, String> getDeclaredDirectives() { 895 Map<String, String> result = new HashMap<>(2); 896 Map<String, String> arbitrary = getArbitraryDirectives(); 897 if (arbitrary != null) 898 result.putAll(arbitrary); 899 if (!attachFragments()) { 900 result.put(Constants.FRAGMENT_ATTACHMENT_DIRECTIVE, Constants.FRAGMENT_ATTACHMENT_NEVER); 901 } else { 902 if (dynamicFragments()) 903 result.put(Constants.FRAGMENT_ATTACHMENT_DIRECTIVE, Constants.FRAGMENT_ATTACHMENT_ALWAYS); 904 else 905 result.put(Constants.FRAGMENT_ATTACHMENT_DIRECTIVE, Constants.FRAGMENT_ATTACHMENT_RESOLVETIME); 906 } 907 if (isSingleton()) 908 result.put(Constants.SINGLETON_DIRECTIVE, Boolean.TRUE.toString()); 909 String[] mandatoryDirective = (String[]) getDirective(Constants.MANDATORY_DIRECTIVE); 910 if (mandatoryDirective != null) 911 result.put(Constants.MANDATORY_DIRECTIVE, ExportPackageDescriptionImpl.toString(mandatoryDirective)); 912 return Collections.unmodifiableMap(result); 913 } 914 getDeclaredAttributes()915 public Map<String, Object> getDeclaredAttributes() { 916 Map<String, Object> result = new HashMap<>(1); 917 synchronized (this.monitor) { 918 if (attributes != null) 919 result.putAll(attributes); 920 } 921 result.put(BundleRevision.BUNDLE_NAMESPACE, getName()); 922 result.put(Constants.BUNDLE_VERSION_ATTRIBUTE, getVersion()); 923 return Collections.unmodifiableMap(result); 924 } 925 getDeclaredRequirements(String namespace)926 public List<BundleRequirement> getDeclaredRequirements(String namespace) { 927 List<BundleRequirement> result = new ArrayList<>(); 928 if (namespace == null || BundleRevision.BUNDLE_NAMESPACE.equals(namespace)) { 929 BundleSpecification[] requires = getRequiredBundles(); 930 for (BundleSpecification require : requires) { 931 result.add(require.getRequirement()); 932 } 933 } 934 if (host != null && (namespace == null || BundleRevision.HOST_NAMESPACE.equals(namespace))) { 935 result.add(host.getRequirement()); 936 } 937 if (namespace == null || BundleRevision.PACKAGE_NAMESPACE.equals(namespace)) { 938 ImportPackageSpecification[] imports = getImportPackages(); 939 for (ImportPackageSpecification importPkg : imports) 940 result.add(importPkg.getRequirement()); 941 } 942 GenericSpecification[] genericSpecifications = getGenericRequires(); 943 for (GenericSpecification requirement : genericSpecifications) { 944 if (namespace == null || namespace.equals(requirement.getType())) 945 result.add(requirement.getRequirement()); 946 } 947 return Collections.unmodifiableList(result); 948 } 949 getDeclaredCapabilities(String namespace)950 public List<BundleCapability> getDeclaredCapabilities(String namespace) { 951 List<BundleCapability> result = new ArrayList<>(); 952 if (host == null) { 953 if (getSymbolicName() != null) { 954 if (namespace == null || BundleRevision.BUNDLE_NAMESPACE.equals(namespace)) { 955 result.add(BundleDescriptionImpl.this.getCapability()); 956 } 957 if (attachFragments() && (namespace == null || BundleRevision.HOST_NAMESPACE.equals(namespace))) { 958 result.add(BundleDescriptionImpl.this.getCapability(BundleRevision.HOST_NAMESPACE)); 959 } 960 } 961 962 } else { 963 // may need to have a osgi.wiring.fragment capability 964 } 965 if (namespace == null || BundleRevision.PACKAGE_NAMESPACE.equals(namespace)) { 966 ExportPackageDescription[] exports = getExportPackages(); 967 for (ExportPackageDescription exportPkg : exports) 968 result.add(exportPkg.getCapability()); 969 } 970 GenericDescription[] genericCapabilities = getGenericCapabilities(); 971 for (GenericDescription capabilitiy : genericCapabilities) { 972 if (namespace == null || namespace.equals(capabilitiy.getType())) 973 result.add(capabilitiy.getCapability()); 974 } 975 return Collections.unmodifiableList(result); 976 } 977 getTypes()978 public int getTypes() { 979 return getHost() != null ? BundleRevision.TYPE_FRAGMENT : 0; 980 } 981 getBundle()982 public Bundle getBundle() { 983 Object ref = getUserObject(); 984 if (ref instanceof BundleReference) 985 return ((BundleReference) ref).getBundle(); 986 return null; 987 } 988 989 @Override getInternalNameSpace()990 String getInternalNameSpace() { 991 return BundleRevision.BUNDLE_NAMESPACE; 992 } 993 getWiring()994 public BundleWiring getWiring() { 995 synchronized (this.monitor) { 996 if (bundleWiring != null || !isResolved()) 997 return bundleWiring; 998 return bundleWiring = new DescriptionWiring(); 999 } 1000 } 1001 1002 static class BundleWireImpl implements BundleWire { 1003 private final BundleCapability capability; 1004 private final BundleWiring provider; 1005 private final BundleRequirement requirement; 1006 private final BundleWiring requirer; 1007 BundleWireImpl(StateWire wire)1008 public BundleWireImpl(StateWire wire) { 1009 VersionConstraint declaredRequirement = wire.getDeclaredRequirement(); 1010 if (declaredRequirement instanceof HostSpecification) 1011 this.capability = ((BaseDescriptionImpl) wire.getDeclaredCapability()).getCapability(BundleRevision.HOST_NAMESPACE); 1012 else 1013 this.capability = wire.getDeclaredCapability().getCapability(); 1014 this.provider = wire.getCapabilityHost().getWiring(); 1015 this.requirement = declaredRequirement.getRequirement(); 1016 this.requirer = wire.getRequirementHost().getWiring(); 1017 } 1018 getCapability()1019 public BundleCapability getCapability() { 1020 return capability; 1021 } 1022 getRequirement()1023 public BundleRequirement getRequirement() { 1024 return requirement; 1025 } 1026 getProviderWiring()1027 public BundleWiring getProviderWiring() { 1028 return provider; 1029 } 1030 getRequirerWiring()1031 public BundleWiring getRequirerWiring() { 1032 return requirer; 1033 } 1034 1035 @Override hashCode()1036 public int hashCode() { 1037 int hashcode = 31 + capability.hashCode(); 1038 hashcode = hashcode * 31 + requirement.hashCode(); 1039 hashcode = hashcode * 31 + provider.hashCode(); 1040 hashcode = hashcode * 31 + requirer.hashCode(); 1041 return hashcode; 1042 } 1043 1044 @Override equals(Object obj)1045 public boolean equals(Object obj) { 1046 if (!(obj instanceof BundleWireImpl)) 1047 return false; 1048 BundleWireImpl other = (BundleWireImpl) obj; 1049 return capability.equals(other.getCapability()) && requirement.equals(other.getRequirement()) && provider.equals(other.getProviderWiring()) && requirer.equals(other.getRequirerWiring()); 1050 } 1051 1052 @Override toString()1053 public String toString() { 1054 return getRequirement() + " -> " + getCapability(); //$NON-NLS-1$ 1055 } 1056 getProvider()1057 public BundleRevision getProvider() { 1058 return provider.getRevision(); 1059 } 1060 getRequirer()1061 public BundleRevision getRequirer() { 1062 return requirer.getRevision(); 1063 } 1064 } 1065 1066 /** 1067 * Coerce the generic type of a list from List<BundleWire> 1068 * to List<Wire> 1069 * @param l List to be coerced. 1070 * @return l coerced to List<Wire> 1071 */ 1072 @SuppressWarnings("unchecked") asListWire(List<? extends Wire> l)1073 static List<Wire> asListWire(List<? extends Wire> l) { 1074 return (List<Wire>) l; 1075 } 1076 1077 /** 1078 * Coerce the generic type of a list from List<BundleCapability> 1079 * to List<Capability> 1080 * @param l List to be coerced. 1081 * @return l coerced to List<Capability> 1082 */ 1083 @SuppressWarnings("unchecked") asListCapability(List<? extends Capability> l)1084 static List<Capability> asListCapability(List<? extends Capability> l) { 1085 return (List<Capability>) l; 1086 } 1087 1088 /** 1089 * Coerce the generic type of a list from List<BundleRequirement> 1090 * to List<Requirement> 1091 * @param l List to be coerced. 1092 * @return l coerced to List<Requirement> 1093 */ 1094 @SuppressWarnings("unchecked") asListRequirement(List<? extends Requirement> l)1095 static List<Requirement> asListRequirement(List<? extends Requirement> l) { 1096 return (List<Requirement>) l; 1097 } 1098 1099 // Note that description wiring are identity equality based 1100 class DescriptionWiring implements BundleWiring { 1101 private volatile boolean valid = true; 1102 getBundle()1103 public Bundle getBundle() { 1104 return BundleDescriptionImpl.this.getBundle(); 1105 } 1106 isInUse()1107 public boolean isInUse() { 1108 return valid && (isCurrent() || BundleDescriptionImpl.this.hasDependents()); 1109 } 1110 invalidate()1111 void invalidate() { 1112 valid = false; 1113 } 1114 isCurrent()1115 public boolean isCurrent() { 1116 return valid && !BundleDescriptionImpl.this.isRemovalPending(); 1117 } 1118 getCapabilities(String namespace)1119 public List<BundleCapability> getCapabilities(String namespace) { 1120 if (!isInUse()) 1121 return null; 1122 List<BundleCapability> result = new ArrayList<>(); 1123 GenericDescription[] genericCapabilities = getSelectedGenericCapabilities(); 1124 for (GenericDescription capabilitiy : genericCapabilities) { 1125 if (namespace == null || namespace.equals(capabilitiy.getType())) 1126 result.add(capabilitiy.getCapability()); 1127 } 1128 if (host != null) 1129 return result; 1130 if (getSymbolicName() != null) { 1131 if (namespace == null || BundleRevision.BUNDLE_NAMESPACE.equals(namespace)) { 1132 result.add(BundleDescriptionImpl.this.getCapability()); 1133 } 1134 if (attachFragments() && (namespace == null || BundleRevision.HOST_NAMESPACE.equals(namespace))) { 1135 result.add(BundleDescriptionImpl.this.getCapability(BundleRevision.HOST_NAMESPACE)); 1136 } 1137 } 1138 if (namespace == null || BundleRevision.PACKAGE_NAMESPACE.equals(namespace)) { 1139 ExportPackageDescription[] exports = getSelectedExports(); 1140 for (ExportPackageDescription exportPkg : exports) 1141 result.add(exportPkg.getCapability()); 1142 } 1143 return result; 1144 } 1145 getResourceCapabilities(String namespace)1146 public List<Capability> getResourceCapabilities(String namespace) { 1147 return asListCapability(getCapabilities(namespace)); 1148 } 1149 getRequirements(String namespace)1150 public List<BundleRequirement> getRequirements(String namespace) { 1151 List<BundleWire> requiredWires = getRequiredWires(namespace); 1152 if (requiredWires == null) 1153 // happens if not in use 1154 return null; 1155 List<BundleRequirement> requirements = new ArrayList<>(requiredWires.size()); 1156 for (BundleWire wire : requiredWires) { 1157 if (!requirements.contains(wire.getRequirement())) 1158 requirements.add(wire.getRequirement()); 1159 } 1160 // get dynamic imports 1161 if (getHost() == null && (namespace == null || BundleRevision.PACKAGE_NAMESPACE.equals(namespace))) { 1162 // TODO need to handle fragments that add dynamic imports 1163 if (hasDynamicImports()) { 1164 ImportPackageSpecification[] imports = getImportPackages(); 1165 for (ImportPackageSpecification impPackage : imports) { 1166 if (ImportPackageSpecification.RESOLUTION_DYNAMIC.equals(impPackage.getDirective(Constants.RESOLUTION_DIRECTIVE))) { 1167 BundleRequirement req = impPackage.getRequirement(); 1168 if (!requirements.contains(req)) 1169 requirements.add(req); 1170 } 1171 } 1172 } 1173 ImportPackageSpecification[] addedDynamic = getAddedDynamicImportPackages(); 1174 for (ImportPackageSpecification dynamicImport : addedDynamic) { 1175 BundleRequirement req = dynamicImport.getRequirement(); 1176 if (!requirements.contains(req)) 1177 requirements.add(req); 1178 } 1179 } 1180 return requirements; 1181 } 1182 getResourceRequirements(String namespace)1183 public List<Requirement> getResourceRequirements(String namespace) { 1184 return asListRequirement(getRequirements(namespace)); 1185 } 1186 getProvidedWires(String namespace)1187 public List<BundleWire> getProvidedWires(String namespace) { 1188 if (!isInUse()) 1189 return null; 1190 BundleDescription[] dependentBundles = getDependents(); 1191 List<BundleWire> unorderedResult = new ArrayList<>(); 1192 for (BundleDescription dependent : dependentBundles) { 1193 List<BundleWire> dependentWires = dependent.getWiring().getRequiredWires(namespace); 1194 if (dependentWires != null) 1195 for (BundleWire bundleWire : dependentWires) { 1196 if (bundleWire.getProviderWiring() == this) 1197 unorderedResult.add(bundleWire); 1198 } 1199 } 1200 List<BundleWire> orderedResult = new ArrayList<>(unorderedResult.size()); 1201 List<BundleCapability> capabilities = getCapabilities(namespace); 1202 for (BundleCapability capability : capabilities) { 1203 for (Iterator<BundleWire> wires = unorderedResult.iterator(); wires.hasNext();) { 1204 BundleWire wire = wires.next(); 1205 if (wire.getCapability().equals(capability)) { 1206 wires.remove(); 1207 orderedResult.add(wire); 1208 } 1209 } 1210 } 1211 return orderedResult; 1212 } 1213 getProvidedResourceWires(String namespace)1214 public List<Wire> getProvidedResourceWires(String namespace) { 1215 return asListWire(getProvidedWires(namespace)); 1216 } 1217 getRequiredWires(String namespace)1218 public List<BundleWire> getRequiredWires(String namespace) { 1219 if (!isInUse()) 1220 return null; 1221 List<BundleWire> result = Collections.<BundleWire> emptyList(); 1222 Map<String, List<StateWire>> wireMap = getWires(); 1223 if (namespace == null) { 1224 result = new ArrayList<>(); 1225 for (List<StateWire> wires : wireMap.values()) { 1226 for (StateWire wire : wires) { 1227 result.add(new BundleWireImpl(wire)); 1228 } 1229 } 1230 return result; 1231 } 1232 List<StateWire> wires = wireMap.get(namespace); 1233 if (wires == null) 1234 return result; 1235 result = new ArrayList<>(wires.size()); 1236 for (StateWire wire : wires) { 1237 result.add(new BundleWireImpl(wire)); 1238 } 1239 return result; 1240 } 1241 getRequiredResourceWires(String namespace)1242 public List<Wire> getRequiredResourceWires(String namespace) { 1243 return asListWire(getRequiredWires(namespace)); 1244 } 1245 getRevision()1246 public BundleRevision getRevision() { 1247 return BundleDescriptionImpl.this; 1248 } 1249 getResource()1250 public BundleRevision getResource() { 1251 return getRevision(); 1252 } 1253 getClassLoader()1254 public ClassLoader getClassLoader() { 1255 throw new UnsupportedOperationException(); 1256 } 1257 findEntries(String path, String filePattern, int options)1258 public List<URL> findEntries(String path, String filePattern, int options) { 1259 return null; 1260 } 1261 listResources(String path, String filePattern, int options)1262 public Collection<String> listResources(String path, String filePattern, int options) { 1263 return null; 1264 } 1265 1266 @Override toString()1267 public String toString() { 1268 return BundleDescriptionImpl.this.toString(); 1269 } 1270 } 1271 getCapabilities(String namespace)1272 public List<Capability> getCapabilities(String namespace) { 1273 return asListCapability(getDeclaredCapabilities(namespace)); 1274 } 1275 getRequirements(String namespace)1276 public List<Requirement> getRequirements(String namespace) { 1277 return asListRequirement(getDeclaredRequirements(namespace)); 1278 } 1279 } 1280