1 29 30 package com.caucho.loader; 31 32 import com.caucho.config.ConfigException; 33 import com.caucho.lifecycle.Lifecycle; 34 import com.caucho.loader.enhancer.ByteCodeEnhancer; 35 import com.caucho.loader.enhancer.EnhancerRuntimeException; 36 import com.caucho.make.AlwaysModified; 37 import com.caucho.make.DependencyContainer; 38 import com.caucho.make.Make; 39 import com.caucho.make.MakeContainer; 40 import com.caucho.server.util.CauchoSystem; 41 import com.caucho.util.ByteBuffer; 42 import com.caucho.util.L10N; 43 import com.caucho.util.TimedCache; 44 import com.caucho.vfs.Dependency; 45 import com.caucho.vfs.JarPath; 46 import com.caucho.vfs.Path; 47 import com.caucho.vfs.ReadStream; 48 49 import javax.annotation.PostConstruct; 50 import java.io.FilePermission ; 51 import java.io.IOException ; 52 import java.io.InputStream ; 53 import java.net.URL ; 54 import java.security.*; 55 import java.lang.instrument.*; 56 import java.util.ArrayList ; 57 import java.util.Enumeration ; 58 import java.util.Hashtable ; 59 import java.util.Vector ; 60 import java.util.jar.Attributes ; 61 import java.util.jar.Manifest ; 62 import java.util.logging.Level ; 63 import java.util.logging.Logger ; 64 import java.util.regex.Pattern ; 65 66 74 public class DynamicClassLoader extends java.net.URLClassLoader 75 implements Dependency, Make 76 { 77 private static L10N _L; 78 private static Logger _log; 79 80 private final static URL NULL_URL; 81 private final static URL []NULL_URL_ARRAY = new URL [0]; 82 83 private static long _globalDependencyCheckInterval = 2000L; 84 85 private String _id; 86 87 private final boolean _isVerbose; 88 private int _verboseDepth; 89 90 private ArrayList <Loader> _loaders = new ArrayList <Loader>(); 92 93 private JarLoader _jarLoader; 94 private PathLoader _pathLoader; 95 96 private Hashtable <String ,ClassEntry> _entryCache; 98 99 private TimedCache<String ,URL > _resourceCache; 100 101 private DependencyContainer _dependencies = new DependencyContainer(); 103 private boolean _isEnableDependencyCheck = false; 104 105 private MakeContainer _makeList; 107 108 private boolean _useServletHack; 111 112 private String []_parentPriorityPackages; 114 115 private String []_priorityPackages; 117 118 private ArrayList <ClassLoaderListener> _listeners; 125 126 private SecurityManager _securityManager; 128 129 private ArrayList <Permission > _permissions; 131 132 private CodeSource _codeSource; 134 135 private ArrayList <ClassFileTransformer> _classFileTransformerList; 137 138 private URL []_urls = NULL_URL_ARRAY; 139 140 private WeakCloseListener _closeListener; 141 142 protected final Lifecycle _lifecycle = new Lifecycle(); 144 145 private long _lastNullCheck; 146 147 152 public DynamicClassLoader(ClassLoader parent) 153 { 154 this(parent, true); 155 } 156 157 162 public DynamicClassLoader(ClassLoader parent, boolean enableDependencyCheck) 163 { 164 super(NULL_URL_ARRAY, getInitParent(parent)); 165 166 parent = getParent(); 167 168 _securityManager = System.getSecurityManager(); 169 170 _isEnableDependencyCheck = enableDependencyCheck; 171 172 _dependencies.setCheckInterval(_globalDependencyCheckInterval); 173 174 for (; parent != null; parent = parent.getParent()) { 175 if (parent instanceof DynamicClassLoader) { 176 DynamicClassLoader loader = (DynamicClassLoader) parent; 177 178 loader.init(); 179 180 addPermissions(loader.getPermissions()); 181 182 184 _dependencies.add(loader); 185 _dependencies.setCheckInterval(loader.getDependencyCheckInterval()); 186 187 _useServletHack = loader._useServletHack; 188 189 break; 190 } 191 } 192 193 if (System.getProperty("resin.verbose.classpath") != null) { 194 _isVerbose = true; 195 196 int depth = 0; 197 198 while (parent != null) { 199 depth++; 200 parent = parent.getParent(); 201 } 202 203 _verboseDepth = depth; 204 } 205 else 206 _isVerbose = false; 207 } 208 209 213 private static ClassLoader getInitParent(ClassLoader parent) 214 { 215 if (parent != null) 216 return parent; 217 else 218 return Thread.currentThread().getContextClassLoader(); 219 } 220 221 private void verbose(String name, String msg) 222 { 223 if (_isVerbose) { 224 for (int i = _verboseDepth; _verboseDepth > 0; _verboseDepth--) 225 System.err.print(' '); 226 227 System.err.println(toString() + " " + name + " " + msg); 228 } 229 } 230 231 234 public static long getGlobalDependencyCheckInterval() 235 { 236 return _globalDependencyCheckInterval; 237 } 238 239 242 public static void setGlobalDependencyCheckInterval(long interval) 243 { 244 _globalDependencyCheckInterval = interval; 245 } 246 247 250 public void setId(String id) 251 { 252 _id = id; 253 } 254 255 258 public String getId() 259 { 260 return _id; 261 } 262 263 266 public boolean isDestroyed() 267 { 268 return _lifecycle.isDestroyed(); 269 } 270 271 274 public void addLoader(Loader loader) 275 { 276 int p = _loaders.indexOf(loader); 277 278 if (p >= 0) { 281 Loader oldLoader = _loaders.get(p); 282 283 if (oldLoader != loader) 284 addLoader(loader, p); 285 } 286 else 287 addLoader(loader, _loaders.size()); 288 289 } 290 291 294 public void addLoader(Loader loader, int offset) 295 { 296 if (_lifecycle.isDestroyed()) 297 throw new IllegalStateException (L().l("can't add loaders after initialization")); 298 299 _loaders.add(offset, loader); 300 301 if (loader.getLoader() == null) 302 loader.setLoader(this); 303 304 if (loader instanceof Dependency) 305 _dependencies.add((Dependency) loader); 306 307 if (loader instanceof Make) { 308 if (_makeList == null) 309 _makeList = new MakeContainer(); 310 311 _makeList.add((Make) loader); 312 } 313 314 if (loader instanceof ClassLoaderListener) 315 addListener(new WeakLoaderListener((ClassLoaderListener) loader)); 316 } 317 318 public ArrayList <Loader> getLoaders() 319 { 320 return _loaders; 321 } 322 323 326 public void addJarManifestClassPath(Path path) 327 throws IOException 328 { 329 JarPath jar = JarPath.create(path); 330 Path manifestPath = jar.lookup("META-INF/MANIFEST.MF"); 331 332 if (manifestPath.canRead()) { 333 ReadStream is = manifestPath.openRead(); 334 try { 335 Manifest manifest = new Manifest (is); 336 337 Attributes main = manifest.getMainAttributes(); 338 339 String classPath = main.getValue("Class-Path"); 340 341 addManifestClassPath(classPath, path.getParent()); 342 } catch (IOException e) { 343 log().log(Level.WARNING, e.toString(), e); 344 345 return; 346 } finally { 347 is.close(); 348 } 349 } 350 } 351 352 355 public void addManifestClassPath(String classPath, Path pwd) 356 { 357 if (classPath == null) 358 return; 359 360 String []urls = Pattern.compile("[\\s,]+").split(classPath); 361 if (urls == null) 362 return; 363 364 for (int i = 0; i < urls.length; i++) { 365 String url = urls[i]; 366 367 if (url.equals("")) 368 continue; 369 370 addJar(pwd.lookup(url)); 371 } 372 } 373 374 377 public void addJar(Path jar) 378 { 379 if (_lifecycle.isDestroyed()) 380 throw new IllegalStateException (L().l("can't add jars after closing")); 381 382 if (jar.isDirectory()) { 383 SimpleLoader loader = new SimpleLoader(); 384 loader.setPath(jar); 385 addLoader(loader); 386 } 387 else { 388 if (_jarLoader == null) { 389 _jarLoader = new JarLoader(); 390 addLoader(_jarLoader); 391 } 392 393 _jarLoader.addJar(jar); 394 } 395 } 396 397 400 public void addPathClass(String className, Path path) 401 { 402 if (_pathLoader == null) { 403 _pathLoader = new PathLoader(); 404 _loaders.add(0, _pathLoader); 406 } 407 408 _pathLoader.put(className, path); 409 } 410 411 414 public void addURL(Path path) 415 { 416 try { 417 if (path.getScheme().equals("memory")) 418 return; 419 420 if (! path.getScheme().equals("jar") && ! path.getURL().endsWith("/")) 421 path = path.lookup("./"); 422 423 addURL(new URL (path.getURL())); 424 } catch (Exception e) { 425 log().log(Level.WARNING, e.toString(), e); 426 } 427 } 428 429 432 public void addURL(URL url) 433 { 434 addURL(_urls.length, url); 435 } 436 437 440 public void addURL(int index, URL url) 441 { 442 super.addURL(url); 443 444 URL []newURLs = new URL [_urls.length + 1]; 445 446 for (int i = 0; i < index; i++) 447 newURLs[i] = _urls[i]; 448 449 newURLs[index] = url; 450 451 for (int i = index + 1; i < newURLs.length; i++) 452 newURLs[i] = _urls[i - 1]; 453 454 _urls = newURLs; 455 } 456 457 460 public URL []getURLs() 461 { 462 return _urls; 463 } 464 465 468 public void setDependencyCheckInterval(long interval) 469 { 470 _dependencies.setCheckInterval(interval); 471 } 472 473 476 public long getDependencyCheckInterval() 477 { 478 if (_dependencies != null) 479 return _dependencies.getCheckInterval(); 480 else 481 return 0; 482 } 483 484 487 public void setEnableDependencyCheck(boolean enable) 488 { 489 _isEnableDependencyCheck = enable; 490 } 491 492 495 public void addDependency(Dependency dependency) 496 { 497 _dependencies.add(dependency); 498 } 499 500 public void addPermission(String path, String actions) 501 { 502 addPermission(new FilePermission (path, actions)); 503 } 504 505 508 public void addPermission(Permission permission) 509 { 510 if (_permissions == null) 511 _permissions = new ArrayList <Permission >(); 512 513 _permissions.add(permission); 514 } 515 516 public ArrayList <Permission > getPermissions() 517 { 518 return _permissions; 519 } 520 521 public void addPermissions(ArrayList <Permission > perms) 522 { 523 if (perms == null) 524 return; 525 526 if (_permissions == null) 527 _permissions = new ArrayList <Permission >(); 528 529 _permissions.addAll(perms); 530 } 531 532 535 public SecurityManager getSecurityManager() 536 { 537 return _securityManager; 538 } 539 540 543 public void setServletHack(boolean servletHack) 544 { 545 _useServletHack = servletHack; 546 547 if (_parentPriorityPackages == null) 548 _parentPriorityPackages = new String [0]; 549 } 550 551 554 public final void addListener(ClassLoaderListener listener) 555 { 556 if (_lifecycle.isDestroyed()) { 557 IllegalStateException e = new IllegalStateException (L().l("attempted to add listener to a closed classloader {0}", this)); 558 559 log().log(Level.WARNING, e.toString(), e); 560 561 return; 562 } 563 564 ArrayList <ClassLoaderListener> listeners; 565 WeakCloseListener closeListener = null; 566 567 synchronized (this) { 568 if (_listeners == null) { 569 _listeners = new ArrayList <ClassLoaderListener>(); 570 closeListener = new WeakCloseListener(this); 571 } 573 listeners = _listeners; 574 } 575 576 if (closeListener != null) { 577 for (ClassLoader parent = getParent(); 578 parent != null; 579 parent = parent.getParent()) { 580 if (parent instanceof DynamicClassLoader) { 581 ((DynamicClassLoader) parent).addListener(closeListener); 582 break; 583 } 584 } 585 } 586 587 synchronized (listeners) { 588 for (int i = listeners.size() - 1; i >= 0; i--) { 589 ClassLoaderListener oldListener = listeners.get(i); 590 591 if (listener == oldListener) { 592 return; 593 } 594 else if (oldListener == null) 595 listeners.remove(i); 596 } 597 598 listeners.add(listener); 599 } 600 601 if (_lifecycle.isActive()) 602 listener.classLoaderInit(this); 603 } 604 605 608 public final void removeListener(ClassLoaderListener listener) 609 { 610 ArrayList <ClassLoaderListener> listeners = _listeners; 611 612 if (listeners == null) 613 return; 614 615 synchronized (listeners) { 616 for (int i = listeners.size() - 1; i >= 0; i--) { 617 ClassLoaderListener oldListener = listeners.get(i); 618 619 if (listener == oldListener) { 620 listeners.remove(i); 621 return; 622 } 623 else if (oldListener == null) 624 listeners.remove(i); 625 } 626 } 627 } 628 629 632 protected ArrayList <ClassLoaderListener> getListeners() 633 { 634 ArrayList <ClassLoaderListener> listeners; 635 listeners = new ArrayList <ClassLoaderListener>(); 636 637 ArrayList <ClassLoaderListener> listenerList; 638 listenerList = _listeners; 639 640 if (listenerList != null) { 641 synchronized (listenerList) { 642 for (int i = 0; i < listenerList.size(); i++) { 643 ClassLoaderListener listener = listenerList.get(i); 644 645 if (listener != null) 646 listeners.add(listener); 647 else { 648 listenerList.remove(i); 649 i--; 650 } 651 } 652 } 653 } 654 655 return listeners; 656 } 657 658 661 public void addParentPriorityPackages(String []pkg) 662 { 663 for (int i = 0; pkg != null && i < pkg.length; i++) { 664 addParentPriorityPackage(pkg[i]); 665 } 666 } 667 668 671 public void addParentPriorityPackage(String pkg) 672 { 673 if (_parentPriorityPackages == null) 674 _parentPriorityPackages = new String [0]; 675 676 int oldLength = _parentPriorityPackages.length; 677 String []newPkgs = new String [oldLength + 1]; 678 679 System.arraycopy(_parentPriorityPackages, 0, newPkgs, 0, oldLength); 680 681 if (! pkg.endsWith(".")) 682 pkg = pkg + '.'; 683 684 newPkgs[oldLength] = pkg; 685 _parentPriorityPackages = newPkgs; 686 } 687 688 691 public void addPriorityPackage(String pkg) 692 { 693 if (_priorityPackages == null) 694 _priorityPackages = new String [0]; 695 696 int oldLength = _priorityPackages.length; 697 String []newPkgs = new String [oldLength + 1]; 698 699 System.arraycopy(_priorityPackages, 0, newPkgs, 0, oldLength); 700 701 if (! pkg.endsWith(".")) 702 pkg = pkg + '.'; 703 704 newPkgs[oldLength] = pkg; 705 _priorityPackages = newPkgs; 706 } 707 708 711 protected PermissionCollection getPermissions(CodeSource codeSource) 712 { 713 PermissionCollection perms = super.getPermissions(codeSource); 714 715 ArrayList <Permission > permissions = _permissions; 716 717 for (int i = 0; permissions != null && i < permissions.size(); i++) { 718 Permission permission = permissions.get(i); 719 720 perms.add(permission); 721 } 722 723 return perms; 724 } 725 726 protected void addCodeBasePath(String path) 727 { 728 } 729 730 733 public void addTransformer(ClassFileTransformer transformer) 734 { 735 if (_classFileTransformerList == null) 736 _classFileTransformerList = new ArrayList <ClassFileTransformer>(); 737 738 _classFileTransformerList.add(transformer); 739 } 740 741 protected ArrayList <ClassFileTransformer> getTransformerList() 742 { 743 return _classFileTransformerList; 744 } 745 746 750 public final String getClassPath() 751 { 752 ClassLoader parent = getParent(); 753 754 String head; 755 756 if (parent instanceof DynamicClassLoader) 757 head = (((DynamicClassLoader) parent).getClassPath()); 758 else 759 head = CauchoSystem.getClassPath(); 760 761 for (int i = 0; i < _loaders.size(); i++) { 762 Loader loader = _loaders.get(i); 763 764 head = loader.getClassPath(head); 765 } 766 767 return head; 768 } 769 770 774 public final String getLocalClassPath() 775 { 776 String head = ""; 777 778 for (int i = 0; i < _loaders.size(); i++) { 779 Loader loader = _loaders.get(i); 780 781 head = loader.getClassPath(head); 782 } 783 784 return head; 785 } 786 787 791 public final String getSourcePath() 792 { 793 ClassLoader parent = getParent(); 794 795 String head; 796 797 if (parent instanceof DynamicClassLoader) 798 head = (((DynamicClassLoader) parent).getSourcePath()); 799 else 800 head = CauchoSystem.getClassPath(); 801 802 for (int i = 0; i < _loaders.size(); i++) { 803 Loader loader = _loaders.get(i); 804 805 head = loader.getSourcePath(head); 806 } 807 808 return head; 809 } 810 811 814 public final String getResourcePathSpecificFirst() 815 { 816 ClassLoader parent = getParent(); 817 818 String head = ""; 819 int size = _loaders != null ? _loaders.size() : 0; 820 for (int i = 0; i < size; i++) { 821 Loader loader = _loaders.get(i); 822 823 head = loader.getSourcePath(head); 824 } 825 826 String tail; 827 if (parent instanceof DynamicClassLoader) 828 tail = (((DynamicClassLoader) parent).getResourcePathSpecificFirst()); 829 else 830 tail = CauchoSystem.getClassPath(); 831 832 if (head == null || head.equals("")) 833 return tail; 834 if (tail == null || tail.equals("")) 835 return head; 836 else 837 return head + CauchoSystem.getPathSeparatorChar() + tail; 838 } 839 840 843 public final boolean isModified() 844 { 845 return isModified(_isEnableDependencyCheck); 846 } 847 848 851 public final boolean isModified(boolean enable) 852 { 853 if (_lifecycle.isDestroyed()) { 854 return true; 855 } 856 857 DependencyContainer dependencies = _dependencies; 858 859 if (dependencies == null) { 860 return true; 861 } 862 863 if (enable) { 864 boolean isModified = dependencies.isModified(); 865 866 return isModified; 867 } 868 else { 869 boolean isModified = isModified(getParent()); 870 871 return isModified; 872 } 873 } 874 875 878 public final boolean isModifiedNow() 879 { 880 if (_lifecycle.isDestroyed()) 881 return true; 882 883 DependencyContainer dependencies = _dependencies; 884 885 if (dependencies == null) 886 return true; 887 888 return dependencies.isModifiedNow(); 889 } 890 891 894 public final void resetDependencyCheckInterval() 895 { 896 if (_lifecycle.isDestroyed()) 897 return; 898 899 DependencyContainer dependencies = _dependencies; 900 901 if (dependencies == null) 902 return; 903 904 dependencies.resetDependencyCheckInterval(); 905 } 906 907 910 public final void clearModified() 911 { 912 if (_lifecycle.isDestroyed()) 913 return; 914 915 DependencyContainer dependencies = _dependencies; 916 917 if (dependencies == null) 918 return; 919 920 dependencies.clearModified(); 921 } 922 923 926 public static boolean isModified(ClassLoader loader) 927 { 928 for (; loader != null; loader = loader.getParent()) { 929 if (loader instanceof DynamicClassLoader) 930 return ((DynamicClassLoader) loader).isModified(); 931 } 932 933 return false; 934 } 935 936 939 public final void make() 940 throws Exception 941 { 942 for (ClassLoader loader = getParent(); 943 loader != null; 944 loader = loader.getParent()) { 945 if (loader instanceof Make) { 946 ((Make) loader).make(); 947 break; 948 } 949 } 950 951 if (_makeList != null) 952 _makeList.make(); 953 } 954 955 958 protected Package definePackage(String name, 959 String a1, String a2, String a3, 960 String b1, String b2, String b3, 961 URL url) 962 { 963 name = name.replace('/', '.'); 964 965 if (name.endsWith(".")) 966 name = name.substring(0, name.length() - 1); 967 968 return super.definePackage(name, a1, a2, a3, b1, b2, b3, url); 969 } 970 971 974 @PostConstruct 975 public void init() 976 { 977 if (! _lifecycle.toActive()) 978 return; 979 980 try { 981 ArrayList <ClassLoaderListener> listeners = getListeners(); 982 983 if (listeners != null) { 984 for (int i = 0; i < listeners.size(); i++) { 985 ClassLoaderListener listener = listeners.get(i); 986 987 listener.classLoaderInit(this); 988 } 989 } 990 } catch (Throwable e) { 991 log().log(Level.WARNING, e.toString(), e); 992 } 993 } 994 995 998 public void validate() 999 throws ConfigException 1000 { 1001 ArrayList <Loader> loaders = _loaders; 1002 1003 if (loaders == null) 1004 throw new IllegalStateException (_L.l("Class loader {0} is closed during initialization.", this)); 1005 1006 for (int i = 0; i < loaders.size(); i++) 1007 loaders.get(i).validate(); 1008 } 1009 1010 public Class <?> loadClass(String name) throws ClassNotFoundException 1011 { 1012 return loadClass(name, false); 1016 } 1017 1018 1026 protected synchronized Class loadClass(String name, boolean resolve) 1028 throws ClassNotFoundException 1029 { 1030 1036 1037 Class cl = findLoadedClass(name); 1039 1040 if (cl != null) { 1041 if (resolve) 1042 resolveClass(cl); 1043 return cl; 1044 } 1045 1046 if (_lifecycle.isDestroyed()) { 1047 log().fine(L().l("Loading class {0} when class loader {1} has been closed.", 1048 name, this)); 1049 1050 return super.loadClass(name, resolve); 1051 } 1052 1053 boolean normalJdkOrder = isNormalJdkOrder(name); 1054 1055 if (_lifecycle.isBeforeInit()) 1056 init(); 1057 1058 if (normalJdkOrder) { 1059 try { 1060 ClassLoader parent = getParent(); 1061 if (parent != null) 1062 cl = Class.forName(name, false, parent); 1063 else 1064 cl = findSystemClass(name); 1065 } catch (ClassNotFoundException e) { 1066 cl = findClass(name); 1067 } 1068 } 1069 else { 1070 1071 try { 1072 cl = findClass(name); 1073 } catch (ClassNotFoundException e) { 1074 ClassLoader parent = getParent(); 1075 if (parent != null) 1076 cl = Class.forName(name, false, parent); 1077 else 1078 cl = findSystemClass(name); 1079 } 1080 } 1081 1082 if (resolve) 1083 resolveClass(cl); 1084 1085 return cl; 1086 } 1087 1088 1095 protected Class findClass(String name) 1096 throws ClassNotFoundException 1097 { 1098 if (_isVerbose) 1099 verbose(name, "findClass"); 1100 1101 if (_lifecycle.isDestroyed()) { 1102 log().fine("Class loader has been closed."); 1103 return super.findClass(name); 1104 } 1105 1106 if (_lifecycle.isBeforeInit()) 1107 init(); 1108 1112 1113 name = name.replace('/', '.'); 1114 1115 ClassEntry entry = null; 1116 1117 synchronized (this) { 1118 entry = _entryCache == null ? null : _entryCache.get(name); 1119 1120 if (entry == null) 1121 entry = getClassEntry(name); 1122 1123 if (entry == null) 1124 throw new ClassNotFoundException (name); 1125 1126 if (entry != null && _isVerbose) 1127 verbose(name, (isNormalJdkOrder(name) ? "found" : "found (took priority from parent)")); 1128 1129 if (_isEnableDependencyCheck) 1130 entry.addDependencies(_dependencies); 1131 1132 1136 if (_entryCache == null) 1137 _entryCache = new Hashtable <String ,ClassEntry>(8); 1138 1139 _entryCache.put(name, entry); 1140 } 1141 1142 try { 1143 return loadClass(entry); 1144 } catch (RuntimeException e) { 1145 throw e; 1146 } catch (ClassNotFoundException e) { 1147 throw e; 1148 } catch (Exception e) { 1149 log().log(Level.FINE, e.toString(), e); 1150 1151 throw new ClassNotFoundException (name + " [" + e + "]", e); 1152 } 1153 } 1154 1155 1158 protected ClassEntry getClassEntry(String name) 1159 throws ClassNotFoundException 1160 { 1161 for (int i = 0; i < _loaders.size(); i++) { 1162 Loader loader = _loaders.get(i); 1163 1164 ClassEntry entry = loader.getClassEntry(name); 1165 1166 if (entry != null) 1167 return entry; 1168 } 1169 1170 return null; 1171 } 1172 1173 1177 protected Class loadClass(ClassEntry entry) 1178 throws IOException , ClassNotFoundException 1179 { 1180 synchronized (entry) { 1181 Class cl = entry.getEntryClass(); 1182 1183 if (cl != null) 1184 return cl; 1185 1186 entry.preLoad(); 1187 1188 String name = entry.getName(); 1189 int p = name.lastIndexOf('.'); 1190 if (p > 0) { 1191 String packageName = name.substring(0, p); 1192 Package pkg = getPackage(packageName); 1193 1194 ClassPackage classPackage = entry.getClassPackage(); 1195 1196 if (pkg != null) { 1197 } 1198 else if (classPackage != null) { 1199 definePackage(packageName, 1200 classPackage.getSpecificationTitle(), 1201 classPackage.getSpecificationVersion(), 1202 classPackage.getSpecificationVendor(), 1203 classPackage.getImplementationTitle(), 1204 classPackage.getImplementationVersion(), 1205 classPackage.getImplementationVendor(), 1206 null); 1207 } 1208 else { 1209 definePackage(packageName, 1210 null, 1211 null, 1212 null, 1213 null, 1214 null, 1215 null, 1216 null); 1217 } 1218 } 1219 1220 ByteBuffer buffer = new ByteBuffer(); 1221 1222 entry.load(buffer); 1223 1224 byte []bBuf = buffer.getBuffer(); 1225 int bLen = buffer.length(); 1226 1227 if (_classFileTransformerList != null) { 1228 Class redefineClass = null; 1229 String className = name.replace('.', '/'); 1230 1231 if (bBuf.length != bLen) { 1232 byte []tempBuf = new byte[bLen]; 1233 System.arraycopy(bBuf, 0, tempBuf, 0, bLen); 1234 bBuf = tempBuf; 1235 } 1236 1237 ProtectionDomain protectionDomain = null; 1238 1239 for (int i = 0; i < _classFileTransformerList.size(); i++) { 1240 ClassFileTransformer transformer = _classFileTransformerList.get(i); 1241 1242 try { 1243 byte []enhancedBuffer = transformer.transform(this, 1244 className, 1245 redefineClass, 1246 protectionDomain, 1247 bBuf); 1248 1249 if (enhancedBuffer != null) { 1250 bBuf = enhancedBuffer; 1251 bLen = enhancedBuffer.length; 1252 1253 if (_isVerbose || true) 1254 verbose(name, String.valueOf(transformer)); 1255 } 1256 1262 } catch (EnhancerRuntimeException e) { 1263 throw e; 1264 } catch (Throwable e) { 1265 log().log(Level.WARNING, e.toString(), e); 1266 } 1267 } 1268 } 1269 1270 try { 1271 cl = defineClass(entry.getName(), 1272 bBuf, 0, bLen, 1273 entry.getCodeSource()); 1274 } catch (RuntimeException e) { 1275 log().log(Level.FINE, entry.getName() + " [" + e.toString() + "]", e); 1276 1277 throw e; 1278 } catch (Exception e) { 1279 log().log(Level.FINE, entry.getName() + " [" + e.toString() + "]", e); 1280 1281 ClassNotFoundException exn; 1282 exn = new ClassNotFoundException (entry.getName() + " [" + e + "]", e); 1283 1285 throw exn; 1286 } 1287 1288 entry.setEntryClass(cl); 1289 1290 if (entry.postLoad()) { 1291 _dependencies.add(AlwaysModified.create()); 1292 _dependencies.setModified(true); 1293 } 1294 1295 return cl; 1296 } 1297 } 1298 1299 1304 public URL getResource(String name) 1305 { 1306 if (_resourceCache == null) { 1307 long expireInterval = getDependencyCheckInterval(); 1308 1309 _resourceCache = new TimedCache<String ,URL >(256, expireInterval); 1310 } 1311 1312 URL url = _resourceCache.get(name); 1313 1314 if (url == NULL_URL) 1315 return null; 1316 else if (url != null) 1317 return url; 1318 1319 boolean isNormalJdkOrder = isNormalJdkOrder(name); 1320 1321 if (isNormalJdkOrder) { 1322 url = getParentResource(name); 1323 1324 if (url != null) 1325 return url; 1326 } 1327 1328 ArrayList <Loader> loaders = _loaders; 1329 1330 for (int i = 0; loaders != null && i < loaders.size(); i++) { 1331 Loader loader = loaders.get(i); 1332 1333 url = loader.getResource(name); 1334 1335 if (url != null) { 1336 _resourceCache.put(name, url); 1337 1338 return url; 1339 } 1340 } 1341 1342 if (! isNormalJdkOrder) { 1343 url = getParentResource(name); 1344 1345 if (url != null) 1346 return url; 1347 } 1348 1349 _resourceCache.put(name, NULL_URL); 1350 1351 return null; 1352 } 1353 1354 private URL getParentResource(String name) 1355 { 1356 ClassLoader parent = getParent(); 1357 1358 ClassLoader systemLoader = ClassLoader.getSystemClassLoader(); 1359 1360 URL url; 1361 1362 if (parent != null) { 1363 url = parent.getResource(name); 1364 1365 if (url != null) { 1366 _resourceCache.put(name, url); 1367 1368 return url; 1369 } 1370 } 1371 else if (this != systemLoader) { 1372 url = getSystemResource(name); 1373 1374 if (url != null) { 1375 _resourceCache.put(name, url); 1376 1377 return url; 1378 } 1379 } 1380 1381 return null; 1382 } 1383 1384 1385 1392 public InputStream getResourceAsStream(String name) 1393 { 1394 boolean isNormalJdkOrder = isNormalJdkOrder(name); 1395 InputStream is = null; 1396 1397 if (isNormalJdkOrder) { 1398 is = getParentResourceAsStream(name); 1399 1400 if (is != null) 1401 return is; 1402 } 1403 1404 ArrayList <Loader> loaders = _loaders; 1405 1406 for (int i = 0; loaders != null && i < loaders.size(); i++) { 1407 Loader loader = loaders.get(i); 1408 1409 is = loader.getResourceAsStream(name); 1410 1411 if (is != null) 1412 return is; 1413 } 1414 1415 if (! isNormalJdkOrder) { 1416 is = getParentResourceAsStream(name); 1417 } 1418 1419 return is; 1420 } 1421 1422 private InputStream getParentResourceAsStream(String name) 1423 { 1424 ClassLoader parent = getParent(); 1425 1426 ClassLoader systemLoader = ClassLoader.getSystemClassLoader(); 1427 1428 InputStream is; 1429 1430 if (parent != null) { 1431 is = parent.getResourceAsStream(name); 1432 1433 if (is != null) 1434 return is; 1435 } 1436 else if (this != systemLoader) { 1437 is = getSystemResourceAsStream(name); 1438 1439 if (is != null) { 1440 return is; 1441 } 1442 } 1443 1444 return null; 1445 } 1446 1447 1450 public Enumeration <URL > findResources(String name) 1451 { 1452 Vector <URL > resources = new Vector <URL >(); 1453 1454 for (int i = 0; i < _loaders.size(); i++) { 1455 Loader loader = _loaders.get(i); 1456 1457 loader.getResources(resources, name); 1458 } 1459 1460 return resources.elements(); 1461 } 1462 1463 1466 public String findLibrary(String name) 1467 { 1468 String systemName = System.mapLibraryName(name); 1469 1470 for (int i = 0; i < _loaders.size(); i++) { 1471 Loader loader = _loaders.get(i); 1472 1473 Path path = loader.getPath(systemName); 1474 1475 if (path != null && path.canRead()) { 1476 return path.getNativePath(); 1477 } 1478 } 1479 1480 return super.findLibrary(name); 1481 } 1482 1483 1486 public Path findPath(String name) 1487 { 1488 for (int i = 0; i < _loaders.size(); i++) { 1489 Loader loader = _loaders.get(i); 1490 1491 Path path = loader.getPath(name); 1492 1493 if (path != null && path.canRead()) { 1494 return path; 1495 } 1496 } 1497 1498 return null; 1499 } 1500 1501 1505 private boolean isNormalJdkOrder(String className) 1506 { 1507 if (_priorityPackages != null) { 1508 String canonName = className.replace('/', '.'); 1509 1510 for (String priorityPackage : _priorityPackages) { 1511 if (canonName.startsWith(priorityPackage)) 1512 return false; 1513 } 1514 } 1515 1516 if (! _useServletHack) 1517 return true; 1518 1519 String canonName = className.replace('/', '.'); 1520 String []pkgs = _parentPriorityPackages; 1521 1522 for (int i = 0; pkgs != null && i < pkgs.length; i++) { 1523 if (canonName.startsWith(pkgs[i])) 1524 return true; 1525 } 1526 1527 return false; 1528 } 1529 1530 1533 public void stop() 1534 { 1535 } 1536 1537 1540 public void destroy() 1541 { 1542 try { 1543 stop(); 1544 } catch (Throwable e) { 1545 } 1546 1547 if (! _lifecycle.toDestroying()) 1548 return; 1549 1550 try { 1551 ClassLoader parent = getParent(); 1552 for (; parent != null; parent = parent.getParent()) { 1553 if (parent instanceof DynamicClassLoader) { 1554 DynamicClassLoader loader = (DynamicClassLoader) parent; 1555 1556 if (_closeListener != null) 1557 loader.removeListener(_closeListener); 1558 } 1559 } 1560 1561 ArrayList <ClassLoaderListener> listeners = _listeners; 1562 _listeners = null; 1563 1564 Thread thread = Thread.currentThread(); 1565 ClassLoader oldLoader = thread.getContextClassLoader(); 1566 1567 try { 1568 if (listeners != null) { 1570 for (int i = listeners.size() - 1; i >= 0; i--) { 1571 ClassLoaderListener listener = listeners.get(i); 1572 1573 try { 1574 thread.setContextClassLoader(this); 1575 1576 listener.classLoaderDestroy(this); 1577 } catch (Throwable e) { 1578 log().log(Level.WARNING, e.toString(), e); 1579 } 1580 } 1581 } 1582 } finally { 1583 thread.setContextClassLoader(oldLoader); 1584 } 1585 1586 for (int i = _loaders.size() - 1; i >= 0; i--) { 1587 Loader loader = _loaders.get(i); 1588 1589 try { 1590 loader.destroy(); 1591 } catch (Throwable e) { 1592 log().log(Level.WARNING, e.toString(), e); 1593 } 1594 } 1595 } finally { 1596 _closeListener = null; 1597 _listeners = null; 1598 _entryCache = null; 1599 _makeList = null; 1600 _loaders = null; 1601 _jarLoader = null; 1602 _dependencies = null; 1603 _permissions = null; 1604 _securityManager = null; 1605 _codeSource = null; 1606 _classFileTransformerList = null; 1607 1608 _lifecycle.toDestroy(); 1609 } 1610 } 1611 1612 1615 public static void setOldLoader(Thread thread, ClassLoader oldLoader) 1616 { 1617 if (! (oldLoader instanceof DynamicClassLoader)) { 1618 thread.setContextClassLoader(oldLoader); 1619 return; 1620 } 1621 1622 DynamicClassLoader dynLoader = (DynamicClassLoader) oldLoader; 1623 1624 if (! dynLoader.isDestroyed()) 1625 thread.setContextClassLoader(oldLoader); 1626 else 1627 thread.setContextClassLoader(ClassLoader.getSystemClassLoader()); 1628 } 1629 1630 public ClassLoader getInstrumentableClassLoader() 1631 { 1632 return this; 1633 } 1634 1635 public ClassLoader getThrowawayClassLoader() 1636 { 1637 DynamicClassLoader dynLoader = new DynamicClassLoader(getParent()); 1638 1639 for (int i = 0; i < _loaders.size(); i++) { 1640 dynLoader.addLoader(_loaders.get(i)); 1641 } 1642 1643 return dynLoader; 1644 } 1645 1646 1649 protected void replace(DynamicClassLoader source) 1650 { 1651 _id = source._id; 1652 1653 _loaders.addAll(source._loaders); 1654 _jarLoader = source._jarLoader; 1655 1656 _dependencies = source._dependencies; 1657 1658 _makeList = source._makeList; 1659 _useServletHack = source._useServletHack; 1660 _parentPriorityPackages = source._parentPriorityPackages; 1661 1662 if (source._listeners != null) { 1663 if (_listeners == null) 1664 _listeners = new ArrayList <ClassLoaderListener>(); 1665 1666 _listeners.addAll(source._listeners); 1667 source._listeners.clear(); 1668 } 1669 1670 _securityManager = source._securityManager; 1671 if (source._permissions != null) { 1672 if (_permissions == null) 1673 _permissions = new ArrayList <Permission >(); 1674 1675 _permissions.addAll(source._permissions); 1676 } 1677 1678 _codeSource = source._codeSource; 1679 1680 _lifecycle.copyState(source._lifecycle); 1681 } 1682 1683 public String toString() 1684 { 1685 if (_id != null) 1686 return "DynamicClassLoader[" + _id + "]"; 1687 else 1688 return "DynamicClassLoader" + _loaders; 1689 } 1690 1691 private static L10N L() 1692 { 1693 if (_L == null) 1694 _L = new L10N(DynamicClassLoader.class); 1695 1696 return _L; 1697 } 1698 1699 protected static Logger log() 1700 { 1701 if (_log == null) 1702 _log = Logger.getLogger(DynamicClassLoader.class.getName()); 1703 1704 return _log; 1705 } 1706 1707 1714 1715 static { 1716 URL url = null; 1717 1718 try { 1719 url = new URL ("file:/caucho/null"); 1720 } catch (Throwable e) { 1721 } 1722 1723 NULL_URL = url; 1724 } 1725} 1726 | Popular Tags |