1 11 12 package org.eclipse.osgi.framework.internal.core; 13 14 import java.io.IOException ; 15 import java.net.URL ; 16 import java.security.AccessController ; 17 import java.security.PrivilegedAction ; 18 import java.util.*; 19 import org.eclipse.osgi.framework.adaptor.*; 20 import org.eclipse.osgi.framework.debug.Debug; 21 import org.eclipse.osgi.framework.util.KeyedHashSet; 22 import org.eclipse.osgi.service.resolver.*; 23 import org.eclipse.osgi.util.ManifestElement; 24 import org.osgi.framework.BundleException; 25 import org.osgi.framework.FrameworkEvent; 26 27 34 public class BundleLoader implements ClassLoaderDelegate { 35 public final static String DEFAULT_PACKAGE = "."; public final static String JAVA_PACKAGE = "java."; public final static byte FLAG_IMPORTSINIT = 0x01; 38 public final static byte FLAG_HASDYNAMICIMPORTS = 0x02; 39 public final static byte FLAG_HASDYNAMICEIMPORTALL = 0x04; 40 public final static byte FLAG_CLOSED = 0x08; 41 42 public final static ClassContext CLASS_CONTEXT = (ClassContext) AccessController.doPrivileged(new PrivilegedAction () { 43 public Object run() { 44 return new ClassContext(); 45 } 46 }); 47 public final static ClassLoader FW_CLASSLOADER = getClassLoader(Framework.class); 48 49 private static final boolean USE_GLOBAL_DEADLOCK_AVOIDANCE_LOCK = "true".equals(FrameworkProperties.getProperty("osgi.classloader.singleThreadLoads")); private static final List waitingList = USE_GLOBAL_DEADLOCK_AVOIDANCE_LOCK ? new ArrayList(0) : null; 51 private static Object lockThread; 52 private static int lockCount = 0; 53 54 55 final private BundleLoaderProxy proxy; 56 57 final BundleHost bundle; 58 final private PolicyHandler policy; 59 60 final private Collection exportedPackages; 61 62 final BundleLoaderProxy[] requiredBundles; 63 64 final int[] reexportTable; 65 66 final private KeyedHashSet requiredSources; 67 68 70 private KeyedHashSet importedSources; 71 72 private String [] dynamicImportPackageStems; 73 74 private String [] dynamicImportPackages; 75 76 private byte loaderFlags = 0; 77 78 private BundleClassLoader classloader; 79 private ClassLoader parent; 80 81 89 public final static String getPackageName(String name) { 90 if (name != null) { 91 int index = name.lastIndexOf('.'); 92 if (index > 0) 93 return name.substring(0, index); 94 } 95 return DEFAULT_PACKAGE; 96 } 97 98 106 public final static String getResourcePackageName(String name) { 107 if (name != null) { 108 109 int begin = ((name.length() > 1) && (name.charAt(0) == '/')) ? 1 : 0; 110 int end = name.lastIndexOf('/'); 111 if (end > begin) 112 return name.substring(begin, end).replace('/', '.'); 113 } 114 return DEFAULT_PACKAGE; 115 } 116 117 125 protected BundleLoader(BundleHost bundle, BundleLoaderProxy proxy) throws BundleException { 126 this.bundle = bundle; 127 this.proxy = proxy; 128 try { 129 bundle.getBundleData().open(); 130 } catch (IOException e) { 131 throw new BundleException(Msg.BUNDLE_READ_EXCEPTION, e); 132 } 133 BundleDescription description = proxy.getBundleDescription(); 134 BundleDescription[] required = description.getResolvedRequires(); 136 if (required.length > 0) { 137 HashSet reExportSet = new HashSet(required.length); 139 BundleSpecification[] requiredSpecs = description.getRequiredBundles(); 140 if (requiredSpecs != null && requiredSpecs.length > 0) 141 for (int i = 0; i < requiredSpecs.length; i++) 142 if (requiredSpecs[i].isExported()) 143 reExportSet.add(requiredSpecs[i].getName()); 144 145 requiredBundles = new BundleLoaderProxy[required.length]; 146 int[] reexported = new int[required.length]; 147 int reexportIndex = 0; 148 for (int i = 0; i < required.length; i++) { 149 requiredBundles[i] = getLoaderProxy(required[i]); 150 if (reExportSet.contains(required[i].getSymbolicName())) 151 reexported[reexportIndex++] = i; 152 } 153 if (reexportIndex > 0) { 154 reexportTable = new int[reexportIndex]; 155 System.arraycopy(reexported, 0, reexportTable, 0, reexportIndex); 156 } else { 157 reexportTable = null; 158 } 159 requiredSources = new KeyedHashSet(10, false); 160 } else { 161 requiredBundles = null; 162 reexportTable = null; 163 requiredSources = null; 164 } 165 166 ExportPackageDescription[] exports = description.getSelectedExports(); 168 if (exports != null && exports.length > 0) { 169 exportedPackages = exports.length > 10 ? (Collection) new HashSet(exports.length) : new ArrayList(exports.length); 170 for (int i = 0; i < exports.length; i++) { 171 if (proxy.forceSourceCreation(exports[i])) { 172 if (!exportedPackages.contains(exports[i].getName())) { 173 proxy.createPackageSource(exports[i], true); 177 } 178 } 179 exportedPackages.add(exports[i].getName()); 180 } 181 } else { 182 exportedPackages = null; 183 } 184 org.osgi.framework.Bundle[] fragmentObjects = bundle.getFragments(); 186 BundleDescription[] fragments = new BundleDescription[fragmentObjects == null ? 0 : fragmentObjects.length]; 187 for (int i = 0; i < fragments.length; i++) 188 fragments[i] = ((AbstractBundle) fragmentObjects[i]).getBundleDescription(); 189 if (description.hasDynamicImports()) 191 addDynamicImportPackage(description.getImportPackages()); 192 for (int i = 0; i < fragments.length; i++) 194 if (fragments[i].isResolved() && fragments[i].hasDynamicImports()) 195 addDynamicImportPackage(fragments[i].getImportPackages()); 196 197 String buddyList = null; 199 try { 200 buddyList = (String ) bundle.getBundleData().getManifest().get(Constants.BUDDY_LOADER); 201 } catch (BundleException e) { 202 } 204 policy = buddyList != null ? new PolicyHandler(this, buddyList) : null; 205 } 206 207 private synchronized KeyedHashSet getImportedSources() { 208 if ((loaderFlags & FLAG_IMPORTSINIT) != 0) 209 return importedSources; 210 ExportPackageDescription[] packages = proxy.getBundleDescription().getResolvedImports(); 211 if (packages != null && packages.length > 0) { 212 if (importedSources == null) 213 importedSources = new KeyedHashSet(packages.length, false); 214 for (int i = 0; i < packages.length; i++) { 215 PackageSource source = createExportPackageSource(packages[i]); 216 if (source != null) 217 importedSources.add(source); 218 } 219 } 220 loaderFlags |= FLAG_IMPORTSINIT; 221 return importedSources; 222 } 223 224 final PackageSource createExportPackageSource(ExportPackageDescription export) { 225 BundleLoaderProxy exportProxy = getLoaderProxy(export.getExporter()); 226 if (exportProxy == null) 227 return null; 229 PackageSource requiredSource = exportProxy.getBundleLoader().findRequiredSource(export.getName()); 230 PackageSource exportSource = exportProxy.createPackageSource(export, false); 231 if (requiredSource == null) 232 return exportSource; 233 return createMultiSource(export.getName(), new PackageSource[] {requiredSource, exportSource}); 234 } 235 236 private static PackageSource createMultiSource(String packageName, PackageSource[] sources) { 237 if (sources.length == 1) 238 return sources[0]; 239 ArrayList sourceList = new ArrayList(sources.length); 240 for (int i = 0; i < sources.length; i++) { 241 SingleSourcePackage[] innerSources = sources[i].getSuppliers(); 242 for (int j = 0; j < innerSources.length; j++) 243 if (!sourceList.contains(innerSources[j])) 244 sourceList.add(innerSources[j]); 245 } 246 return new MultiSourcePackage(packageName, (SingleSourcePackage[]) sourceList.toArray(new SingleSourcePackage[sourceList.size()])); 247 } 248 249 252 final BundleLoaderProxy getLoaderProxy(BundleDescription source) { 253 BundleLoaderProxy sourceProxy = (BundleLoaderProxy) source.getUserObject(); 254 if (sourceProxy == null) { 255 long exportingID = source.getBundleId(); 257 BundleHost exportingBundle = (BundleHost) bundle.framework.getBundle(exportingID); 258 if (exportingBundle == null) 259 return null; 260 sourceProxy = exportingBundle.getLoaderProxy(); 261 } 262 return sourceProxy; 263 } 264 265 269 synchronized void close() { 270 if ((loaderFlags & FLAG_CLOSED) != 0) 271 return; 272 if (classloader != null) 273 classloader.close(); 274 if (policy != null) 275 policy.close(); 276 loaderFlags |= FLAG_CLOSED; 277 } 278 279 288 final Class loadClass(String name) throws ClassNotFoundException { 289 return createClassLoader().loadClass(name); 290 } 291 292 301 final URL getResource(String name) { 302 return createClassLoader().getResource(name); 303 } 304 305 final synchronized ClassLoader getParentClassLoader() { 306 if (parent != null) 307 return parent; 308 createClassLoader(); 309 return parent; 310 } 311 312 final synchronized BundleClassLoader createClassLoader() { 313 if (classloader != null) 314 return classloader; 315 try { 316 String [] classpath = bundle.getBundleData().getClassPath(); 317 if (classpath != null) { 318 BundleClassLoader bcl = createBCLPrevileged(bundle.getProtectionDomain(), classpath); 319 parent = getParentPrivileged(bcl); 320 classloader = bcl; 321 } else { 322 bundle.framework.publishFrameworkEvent(FrameworkEvent.ERROR, bundle, new BundleException(Msg.BUNDLE_NO_CLASSPATH_MATCH)); 323 } 324 } catch (BundleException e) { 325 bundle.framework.publishFrameworkEvent(FrameworkEvent.ERROR, bundle, e); 326 } 327 return classloader; 328 } 329 330 336 Class findLocalClass(String name) throws ClassNotFoundException { 337 if (Debug.DEBUG && Debug.DEBUG_LOADER) 338 Debug.println("BundleLoader[" + this + "].findLocalClass(" + name + ")"); try { 340 Class clazz = createClassLoader().findLocalClass(name); 341 if (Debug.DEBUG && Debug.DEBUG_LOADER && clazz != null) 342 Debug.println("BundleLoader[" + this + "] found local class " + name); return clazz; 344 } catch (ClassNotFoundException e) { 345 if (e instanceof StatusException) { 346 if ((((StatusException) e).getStatusCode() & StatusException.CODE_ERROR) != 0) 347 throw e; 348 } 349 return null; 350 } 351 } 352 353 356 public Class findClass(String name) throws ClassNotFoundException { 357 return findClass(name, true); 358 } 359 360 Class findClass(String name, boolean checkParent) throws ClassNotFoundException { 361 ClassLoader parentCL = getParentClassLoader(); 362 if (checkParent && parentCL != null && name.startsWith(JAVA_PACKAGE)) 363 return parentCL.loadClass(name); 366 try { 367 if (USE_GLOBAL_DEADLOCK_AVOIDANCE_LOCK) 368 lock(createClassLoader()); 369 return findClassInternal(name, checkParent, parentCL); 370 } finally { 371 if (USE_GLOBAL_DEADLOCK_AVOIDANCE_LOCK) 372 unlock(); 373 } 374 } 375 376 private Class findClassInternal(String name, boolean checkParent, ClassLoader parentCL) throws ClassNotFoundException { 377 if (Debug.DEBUG && Debug.DEBUG_LOADER) 378 Debug.println("BundleLoader[" + this + "].loadBundleClass(" + name + ")"); String pkgName = getPackageName(name); 380 boolean bootDelegation = false; 381 if (checkParent && parentCL != null && isBootDelegationPackage(pkgName)) 383 try { 385 return parentCL.loadClass(name); 386 } catch (ClassNotFoundException cnfe) { 387 bootDelegation = true; 389 } 390 391 Class result = null; 392 PackageSource source = findImportedSource(pkgName); 394 if (source != null) { 395 result = source.loadClass(name); 397 if (result != null) 398 return result; 399 throw new ClassNotFoundException (name); 400 } 401 source = findRequiredSource(pkgName); 403 if (source != null) 404 result = source.loadClass(name); 406 if (result == null) 408 result = findLocalClass(name); 409 if (result != null) 410 return result; 411 if (source == null) { 413 source = findDynamicSource(pkgName); 414 if (source != null) { 415 result = source.loadClass(name); 416 if (result != null) 417 return result; 418 throw new ClassNotFoundException (name); 420 } 421 } 422 423 if (result == null && policy != null) 425 result = policy.doBuddyClassLoading(name); 426 if (parentCL != null && checkParent && !bootDelegation && bundle.framework.compatibiltyBootDelegation && result == null && source == null && !isExportedPackage(pkgName)) 428 return parentCL.loadClass(name); 430 if (parentCL != null && result == null && !bootDelegation && isRequestFromVM()) 432 result = parentCL.loadClass(name); 433 if (result == null) 434 throw new ClassNotFoundException (name); 435 return result; 436 } 437 438 private boolean isRequestFromVM() { 439 if (bundle.framework.bootDelegateAll || !bundle.framework.contextBootDelegation) 440 return false; 441 Class [] context = CLASS_CONTEXT.getClassContext(); 443 if (context == null || context.length < 2) 444 return false; 445 for (int i = 1; i < context.length; i++) 447 if (context[i] != BundleLoader.class && !ClassLoader .class.isAssignableFrom(context[i])) { 449 ClassLoader cl = getClassLoader(context[i]); 451 if (cl != FW_CLASSLOADER) { if (Class .class != context[i] && !(cl instanceof BundleClassLoader)) 453 return true; 454 break; 455 } 456 } 457 return false; 458 } 459 460 private static ClassLoader getClassLoader(final Class clazz) { 461 if (System.getSecurityManager() == null) 462 return clazz.getClassLoader(); 463 return (ClassLoader ) AccessController.doPrivileged(new PrivilegedAction () { 464 public Object run() { 465 return clazz.getClassLoader(); 466 } 467 }); 468 } 469 470 473 public URL findResource(String name) { 474 return findResource(name, true); 475 } 476 477 URL findResource(String name, boolean checkParent) { 478 if ((name.length() > 1) && (name.charAt(0) == '/')) 479 name = name.substring(1); 480 String pkgName = getResourcePackageName(name); 481 boolean bootDelegation = false; 482 ClassLoader parentCL = getParentClassLoader(); 483 if (checkParent && parentCL != null) { 486 if (pkgName.startsWith(JAVA_PACKAGE)) 487 return parentCL.getResource(name); 490 else if (isBootDelegationPackage(pkgName)) { 491 URL result = parentCL.getResource(name); 493 if (result != null) 494 return result; 495 bootDelegation = true; 496 } 497 } 498 499 URL result = null; 500 PackageSource source = findImportedSource(pkgName); 502 if (source != null) 503 return source.getResource(name); 505 source = findRequiredSource(pkgName); 507 if (source != null) 508 result = source.getResource(name); 510 if (result == null) 512 result = findLocalResource(name); 513 if (result != null) 514 return result; 515 if (source == null) { 517 source = findDynamicSource(pkgName); 518 if (source != null) 519 return source.getResource(name); 521 } 522 523 if (result == null && policy != null) 525 result = policy.doBuddyResourceLoading(name); 526 if (parentCL != null && checkParent && !bootDelegation && bundle.framework.compatibiltyBootDelegation && result == null && source == null && !isExportedPackage(pkgName)) 528 return parentCL.getResource(name); 530 if (parentCL != null && result == null && !bootDelegation && isRequestFromVM()) 532 result = parentCL.getResource(name); 533 return result; 534 } 535 536 boolean isBootDelegationPackage(String name) { 537 if (bundle.framework.bootDelegateAll) 538 return true; 539 if (bundle.framework.bootDelegation != null) 540 for (int i = 0; i < bundle.framework.bootDelegation.length; i++) 541 if (name.equals(bundle.framework.bootDelegation[i])) 542 return true; 543 if (bundle.framework.bootDelegationStems != null) 544 for (int i = 0; i < bundle.framework.bootDelegationStems.length; i++) 545 if (name.startsWith(bundle.framework.bootDelegationStems[i])) 546 return true; 547 return false; 548 } 549 550 553 public Enumeration findResources(String name) throws IOException { 554 if ((name.length() > 1) && (name.charAt(0) == '/')) 556 name = name.substring(1); 557 String pkgName = getResourcePackageName(name); 558 Enumeration result = null; 559 PackageSource source = findImportedSource(pkgName); 562 if (source != null) 563 return source.getResources(name); 565 source = findRequiredSource(pkgName); 567 if (source != null) 568 result = source.getResources(name); 570 571 Enumeration localResults = findLocalResources(name); 574 result = compoundEnumerations(result, localResults); 575 if (result == null && source == null) { 577 source = findDynamicSource(pkgName); 578 if (source != null) 579 return source.getResources(name); 580 } 581 if (policy != null) { 582 Enumeration buddyResult = policy.doBuddyResourcesLoading(name); 583 result = compoundEnumerations(result, buddyResult); 584 } 585 return result; 586 } 587 588 591 Enumeration getResources(String name) throws IOException { 592 if ((name.length() > 1) && (name.charAt(0) == '/')) 593 name = name.substring(1); 594 String pkgName = getResourcePackageName(name); 595 Enumeration result = null; 598 if (pkgName.startsWith(JAVA_PACKAGE) || isBootDelegationPackage(pkgName)) { 599 ClassLoader parentCL = getParentClassLoader(); 602 result = parentCL == null ? null : parentCL.getResources(name); 603 if (pkgName.startsWith(JAVA_PACKAGE)) 604 return result; 605 } 606 return compoundEnumerations(result, findResources(name)); 607 } 608 609 static Enumeration compoundEnumerations(Enumeration list1, Enumeration list2) { 610 if (list2 == null || !list2.hasMoreElements()) 611 return list1; 612 if (list1 == null || !list1.hasMoreElements()) 613 return list2; 614 Vector compoundResults = new Vector(); 615 while (list1.hasMoreElements()) 616 compoundResults.add(list1.nextElement()); 617 while (list2.hasMoreElements()) { 618 Object item = list2.nextElement(); 619 if (!compoundResults.contains(item)) compoundResults.add(item); 621 } 622 return compoundResults.elements(); 623 } 624 625 630 URL findLocalResource(final String name) { 631 return createClassLoader().findLocalResource(name); 632 } 633 634 641 Enumeration findLocalResources(String name) { 642 return createClassLoader().findLocalResources(name); 643 } 644 645 651 public String findLibrary(final String name) { 652 if (System.getSecurityManager() == null) 653 return findLocalLibrary(name); 654 return (String ) AccessController.doPrivileged(new PrivilegedAction () { 655 public Object run() { 656 return findLocalLibrary(name); 657 } 658 }); 659 } 660 661 final String findLocalLibrary(final String name) { 662 String result = bundle.getBundleData().findLibrary(name); 663 if (result != null) 664 return result; 665 666 org.osgi.framework.Bundle[] fragments = bundle.getFragments(); 667 if (fragments == null || fragments.length == 0) 668 return null; 669 670 for (int i = 0; i < fragments.length; i++) { 672 result = ((AbstractBundle) fragments[i]).getBundleData().findLibrary(name); 673 if (result != null) 674 return result; 675 } 676 return result; 677 } 678 679 682 final AbstractBundle getBundle() { 683 return bundle; 684 } 685 686 private BundleClassLoader createBCLPrevileged(final BundleProtectionDomain pd, final String [] cp) { 687 if (System.getSecurityManager() == null) 689 return createBCL(pd, cp); 690 691 return (BundleClassLoader) AccessController.doPrivileged(new PrivilegedAction () { 692 public Object run() { 693 return createBCL(pd, cp); 694 } 695 }); 696 697 } 698 699 BundleClassLoader createBCL(final BundleProtectionDomain pd, final String [] cp) { 700 BundleClassLoader bcl = bundle.getBundleData().createClassLoader(BundleLoader.this, pd, cp); 701 org.osgi.framework.Bundle[] fragments = bundle.getFragments(); 703 if (fragments != null) 704 for (int i = 0; i < fragments.length; i++) { 705 AbstractBundle fragment = (AbstractBundle) fragments[i]; 706 try { 707 bcl.attachFragment(fragment.getBundleData(), fragment.domain, fragment.getBundleData().getClassPath()); 708 } catch (BundleException be) { 709 bundle.framework.publishFrameworkEvent(FrameworkEvent.ERROR, bundle, be); 710 } 711 } 712 713 bcl.initialize(); 715 return bcl; 716 } 717 718 722 public final String toString() { 723 BundleData result = bundle.getBundleData(); 724 return result == null ? "BundleLoader.bundledata == null!" : result.toString(); } 726 727 734 private final synchronized boolean isDynamicallyImported(String pkgname) { 735 if (this instanceof SystemBundleLoader) 736 return false; if (pkgname.startsWith("java.")) return true; 740 741 742 if ((loaderFlags & FLAG_HASDYNAMICIMPORTS) == 0) 743 return false; 744 745 746 if ((loaderFlags & FLAG_HASDYNAMICEIMPORTALL) != 0) 747 return true; 748 749 750 if (dynamicImportPackages != null) 751 for (int i = 0; i < dynamicImportPackages.length; i++) 752 if (pkgname.equals(dynamicImportPackages[i])) 753 return true; 754 755 756 if (dynamicImportPackageStems != null) 757 for (int i = 0; i < dynamicImportPackageStems.length; i++) 758 if (pkgname.startsWith(dynamicImportPackageStems[i])) 759 return true; 760 761 return false; 762 } 763 764 final void addExportedProvidersFor(String symbolicName, String packageName, ArrayList result, KeyedHashSet visited) { 765 if (!visited.add(bundle)) 766 return; 767 768 PackageSource local = null; 770 if (isExportedPackage(packageName)) 771 local = proxy.getPackageSource(packageName); 772 if (requiredBundles != null) { 774 int size = reexportTable == null ? 0 : reexportTable.length; 775 int reexportIndex = 0; 776 for (int i = 0; i < requiredBundles.length; i++) { 777 if (local != null) { 778 requiredBundles[i].getBundleLoader().addExportedProvidersFor(symbolicName, packageName, result, visited); 782 } else if (reexportIndex < size && reexportTable[reexportIndex] == i) { 783 reexportIndex++; 784 requiredBundles[i].getBundleLoader().addExportedProvidersFor(symbolicName, packageName, result, visited); 785 } 786 } 787 } 788 789 if (local != null && local.isFriend(symbolicName)) { 791 if (local instanceof BundleLoaderProxy.ReexportPackageSource) 792 local = new SingleSourcePackage(packageName, -1, proxy); 793 result.add(local); 794 } 795 } 796 797 final boolean isExportedPackage(String name) { 798 return exportedPackages == null ? false : exportedPackages.contains(name); 799 } 800 801 private void addDynamicImportPackage(ImportPackageSpecification[] packages) { 802 if (packages == null) 803 return; 804 ArrayList dynamicImports = new ArrayList(packages.length); 805 for (int i = 0; i < packages.length; i++) 806 if (ImportPackageSpecification.RESOLUTION_DYNAMIC.equals(packages[i].getDirective(Constants.RESOLUTION_DIRECTIVE))) 807 dynamicImports.add(packages[i].getName()); 808 if (dynamicImports.size() > 0) 809 addDynamicImportPackage((String []) dynamicImports.toArray(new String [dynamicImports.size()])); 810 } 811 812 819 private void addDynamicImportPackage(String [] packages) { 820 if (packages == null) 821 return; 822 823 loaderFlags |= FLAG_HASDYNAMICIMPORTS; 824 int size = packages.length; 825 ArrayList stems; 826 if (dynamicImportPackageStems == null) { 827 stems = new ArrayList(size); 828 } else { 829 stems = new ArrayList(size + dynamicImportPackageStems.length); 830 for (int i = 0; i < dynamicImportPackageStems.length; i++) { 831 stems.add(dynamicImportPackageStems[i]); 832 } 833 } 834 835 ArrayList names; 836 if (dynamicImportPackages == null) { 837 names = new ArrayList(size); 838 } else { 839 names = new ArrayList(size + dynamicImportPackages.length); 840 for (int i = 0; i < dynamicImportPackages.length; i++) { 841 names.add(dynamicImportPackages[i]); 842 } 843 } 844 845 for (int i = 0; i < size; i++) { 846 String name = packages[i]; 847 if (isDynamicallyImported(name)) 848 continue; 849 if (name.equals("*")) { loaderFlags |= FLAG_HASDYNAMICEIMPORTALL; 851 return; 852 } 853 854 if (name.endsWith(".*")) stems.add(name.substring(0, name.length() - 1)); 856 else 857 names.add(name); 858 } 859 860 size = stems.size(); 861 if (size > 0) 862 dynamicImportPackageStems = (String []) stems.toArray(new String [size]); 863 864 size = names.size(); 865 if (size > 0) 866 dynamicImportPackages = (String []) names.toArray(new String [size]); 867 } 868 869 875 public final synchronized void addDynamicImportPackage(ManifestElement[] packages) { 876 if (packages == null) 877 return; 878 ArrayList dynamicImports = new ArrayList(packages.length); 879 for (int i = 0; i < packages.length; i++) 880 dynamicImports.add(packages[i].getValue()); 881 if (dynamicImports.size() > 0) 882 addDynamicImportPackage((String []) dynamicImports.toArray(new String [dynamicImports.size()])); 883 } 884 885 final synchronized void attachFragment(BundleFragment fragment) throws BundleException { 886 if (classloader == null) 887 return; 888 String [] classpath = fragment.getBundleData().getClassPath(); 889 if (classpath != null) 890 classloader.attachFragment(fragment.getBundleData(), fragment.domain, classpath); 891 } 892 893 897 private PackageSource findSource(String pkgName) { 898 if (pkgName == null) 899 return null; 900 PackageSource result = findImportedSource(pkgName); 901 if (result != null) 902 return result; 903 return findRequiredSource(pkgName); 905 } 906 907 private PackageSource findImportedSource(String pkgName) { 908 KeyedHashSet imports = getImportedSources(); 909 if (imports == null) 910 return null; 911 synchronized (imports) { 912 return (PackageSource) imports.getByKey(pkgName); 913 } 914 } 915 916 private PackageSource findDynamicSource(String pkgName) { 917 if (isDynamicallyImported(pkgName)) { 918 ExportPackageDescription exportPackage = bundle.framework.adaptor.getState().linkDynamicImport(proxy.getBundleDescription(), pkgName); 919 if (exportPackage != null) { 920 PackageSource source = createExportPackageSource(exportPackage); 921 synchronized (this) { 922 if (importedSources == null) 923 importedSources = new KeyedHashSet(false); 924 } 925 synchronized (importedSources) { 926 importedSources.add(source); 927 } 928 return source; 929 } 930 } 931 return null; 932 } 933 934 private PackageSource findRequiredSource(String pkgName) { 935 if (requiredBundles == null) 936 return null; 937 synchronized (requiredSources) { 938 PackageSource result = (PackageSource) requiredSources.getByKey(pkgName); 939 if (result != null) 940 return result.isNullSource() ? null : result; 941 } 942 KeyedHashSet visited = new KeyedHashSet(false); 943 visited.add(bundle); ArrayList result = new ArrayList(3); 945 for (int i = 0; i < requiredBundles.length; i++) { 946 BundleLoader requiredLoader = requiredBundles[i].getBundleLoader(); 947 requiredLoader.addExportedProvidersFor(proxy.getSymbolicName(), pkgName, result, visited); 948 } 949 PackageSource source; 951 if (result.size() == 0) { 952 source = NullPackageSource.getNullPackageSource(pkgName); 955 } else if (result.size() == 1) { 956 source = (PackageSource) result.get(0); 958 } else { 959 PackageSource[] srcs = (PackageSource[]) result.toArray(new PackageSource[result.size()]); 961 source = createMultiSource(pkgName, srcs); 962 } 963 synchronized (requiredSources) { 964 requiredSources.add(source); 965 } 966 return source.isNullSource() ? null : source; 967 } 968 969 974 final PackageSource getPackageSource(String pkgName) { 975 PackageSource result = findSource(pkgName); 976 if (!isExportedPackage(pkgName)) 977 return result; 978 PackageSource localSource = proxy.getPackageSource(pkgName); 980 if (localSource instanceof BundleLoaderProxy.ReexportPackageSource) 981 localSource = new SingleSourcePackage(pkgName, -1, proxy); 982 if (result == null) 983 return localSource; 984 if (localSource == null) 985 return result; 986 return createMultiSource(pkgName, new PackageSource[] {result, localSource}); 987 } 988 989 private ClassLoader getParentPrivileged(final BundleClassLoader bcl) { 990 if (System.getSecurityManager() == null) 991 return bcl.getParent(); 992 993 return (ClassLoader ) AccessController.doPrivileged(new PrivilegedAction () { 994 public Object run() { 995 return bcl.getParent(); 996 } 997 }); 998 } 999 1000 static final class ClassContext extends SecurityManager { 1001 public Class [] getClassContext() { 1003 return super.getClassContext(); 1004 } 1005 } 1006 1007 1013 private static void lock(Object loader) { 1014 Thread currentThread = Thread.currentThread(); 1015 boolean interrupted = false; 1016 synchronized (loader) { 1017 if (tryLock(currentThread, loader)) 1018 return; 1020 do { 1021 try { 1022 loader.wait(); 1025 } catch (InterruptedException e) { 1026 interrupted = true; 1027 } 1029 } while (!tryLock(currentThread)); 1030 } 1031 if (interrupted) 1032 currentThread.interrupt(); 1033 } 1034 1035 1039 private synchronized static boolean tryLock(Thread currentThread, Object loader) { 1040 if (lockThread == currentThread) { 1041 lockCount++; 1042 return true; 1043 } 1044 if (lockThread == null) { 1045 lockCount++; 1046 lockThread = currentThread; 1047 return true; 1048 } 1049 waitingList.add(new Object [] {currentThread, loader}); 1050 return false; 1051 } 1052 1053 1056 private synchronized static boolean tryLock(Thread currentThread) { 1057 if (lockThread == currentThread) { 1058 lockCount++; 1059 return true; 1060 } 1061 return false; 1062 } 1063 1064 1068 private static void unlock() { 1069 Thread waitingThread = null; 1070 Object loader = null; 1071 synchronized (BundleLoader.class) { 1072 lockCount--; 1073 if (lockCount != 0) 1074 return; 1075 1076 if (waitingList.isEmpty()) { 1077 lockThread = null; 1078 return; 1079 } 1080 1081 Object [] waiting = (Object []) waitingList.get(0); 1082 waitingThread = (Thread ) waiting[0]; 1083 loader = waiting[1]; 1084 } 1085 synchronized (loader) { 1086 synchronized (BundleLoader.class) { 1087 lockThread = waitingThread; 1088 waitingList.remove(0); 1089 loader.notifyAll(); 1090 } 1091 } 1092 } 1093 1094} 1095 | Popular Tags |