| 1 58 package org.oddjob.arooa; 59 60 import java.io.ByteArrayOutputStream ; 61 import java.io.File ; 62 import java.io.FileInputStream ; 63 import java.io.IOException ; 64 import java.io.InputStream ; 65 import java.lang.reflect.Constructor ; 66 import java.net.MalformedURLException ; 67 import java.net.URL ; 68 import java.util.Enumeration ; 69 import java.util.Hashtable ; 70 import java.util.Vector ; 71 import java.util.zip.ZipEntry ; 72 import java.util.zip.ZipFile ; 73 74 import org.apache.log4j.Logger; 75 import org.apache.tools.ant.AntClassLoader; 76 77 86 public class ArooaClassLoader extends ClassLoader { 87 private static final Logger logger = Logger.getLogger(ArooaClassLoader.class); 88 89 99 private class ResourceEnumeration implements Enumeration { 100 103 private String resourceName; 104 105 108 private int pathElementsIndex; 109 110 115 private URL nextResource; 116 117 123 ResourceEnumeration(String name) { 124 this.resourceName = name; 125 this.pathElementsIndex = 0; 126 findNextResource(); 127 } 128 129 136 public boolean hasMoreElements() { 137 return (this.nextResource != null); 138 } 139 140 145 public Object nextElement() { 146 URL ret = this.nextResource; 147 findNextResource(); 148 return ret; 149 } 150 151 157 private void findNextResource() { 158 URL url = null; 159 while ((pathElementsIndex < pathComponents.size()) 160 && (url == null)) { 161 File pathComponent 162 = (File ) pathComponents.elementAt(pathElementsIndex); 163 url = getResourceURL(pathComponent, this.resourceName); 164 pathElementsIndex++; 165 } 166 this.nextResource = url; 167 } 168 } 169 170 173 private static final int BUFFER_SIZE = 8192; 174 177 private static final int NUMBER_OF_STRINGS = 256; 178 179 183 private Vector pathComponents = new Vector (); 184 185 189 private boolean parentFirst = true; 190 191 196 private Vector systemPackages = new Vector (); 197 198 203 private Vector loaderPackages = new Vector (); 204 205 211 private boolean ignoreBase = false; 212 213 216 private ClassLoader parent = null; 217 218 221 private Hashtable zipFiles = new Hashtable (); 222 223 224 227 public ArooaClassLoader() { 228 setParent(null); 229 } 230 231 242 public ArooaClassLoader(File [] classpath) { 243 setParent(null); 244 setClassPath(classpath); 245 } 246 247 263 public ArooaClassLoader(ClassLoader parent, File [] classpath, 264 boolean parentFirst) { 265 this(classpath); 266 if (parent != null) { 267 setParent(parent); 268 } 269 setParentFirst(parentFirst); 270 } 271 272 273 285 public ArooaClassLoader(File [] classpath, 286 boolean parentFirst) { 287 this(null, classpath, parentFirst); 288 } 289 290 303 public ArooaClassLoader(ClassLoader parent, boolean parentFirst) { 304 setParent(parent); 305 this.parentFirst = parentFirst; 306 } 307 308 315 public void setClassPath(File [] classpath) { 316 pathComponents.removeAllElements(); 317 if (classpath != null) { 318 logger.debug("Setting classloader classpath with [" 319 + classpath.length + "] files..."); 320 for (int i = 0; i < classpath.length; ++i) { 321 try { 322 addPathFile(classpath[i]); 323 logger.debug("" + classpath[i]); 324 } catch (IOException e) { 325 throw new ArooaException(e); 326 } 327 } 328 } 329 else { 330 logger.debug("Setting classloader classpath null"); 331 } 332 } 333 334 340 public void setParent(ClassLoader parent) { 341 if (parent == null) { 342 this.parent = ArooaClassLoader.class.getClassLoader(); 343 } else { 344 this.parent = parent; 345 } 346 } 347 348 356 public void setParentFirst(boolean parentFirst) { 357 this.parentFirst = parentFirst; 358 } 359 360 368 protected void addPathFile(File pathComponent) throws IOException { 369 pathComponents.addElement(pathComponent); 370 } 371 372 378 public String getClasspath() { 379 StringBuffer sb = new StringBuffer (); 380 boolean firstPass = true; 381 Enumeration componentEnum = pathComponents.elements(); 382 while (componentEnum.hasMoreElements()) { 383 if (!firstPass) { 384 sb.append(System.getProperty("path.separator")); 385 } else { 386 firstPass = false; 387 } 388 sb.append(((File ) componentEnum.nextElement()).getAbsolutePath()); 389 } 390 return sb.toString(); 391 } 392 393 public String toString() { 394 StringBuffer sb = new StringBuffer (); 395 boolean firstPass = true; 396 Enumeration componentEnum = pathComponents.elements(); 397 sb.append("ArooaClassLoader ("); 398 while (componentEnum.hasMoreElements()) { 399 if (!firstPass) { 400 sb.append(','); 401 } else { 402 firstPass = false; 403 } 404 sb.append(((File ) componentEnum.nextElement()).getName()); 405 } 406 sb.append(')'); 407 return sb.toString(); 408 } 409 410 419 public synchronized void setIsolated(boolean isolated) { 420 ignoreBase = isolated; 421 } 422 423 432 public static void initializeClass(Class theClass) { 433 438 final Constructor [] cons = theClass.getDeclaredConstructors(); 439 if (cons != null) { 441 if (cons.length > 0 && cons[0] != null) { 442 final String [] strs = new String [NUMBER_OF_STRINGS]; 443 try { 444 cons[0].newInstance(strs); 445 } catch (Throwable t) { 448 } 461 } 462 } 463 } 464 465 474 public void addSystemPackageRoot(String packageRoot) { 475 systemPackages.addElement(packageRoot 476 + (packageRoot.endsWith(".") ? "" : ".")); 477 } 478 479 488 public void addLoaderPackageRoot(String packageRoot) { 489 loaderPackages.addElement(packageRoot 490 + (packageRoot.endsWith(".") ? "" : ".")); 491 } 492 493 508 public Class forceLoadClass(String classname) 509 throws ClassNotFoundException { 510 511 Class theClass = findLoadedClass(classname); 512 513 if (theClass == null) { 514 theClass = findClass(classname); 515 } 516 517 return theClass; 518 } 519 520 536 public Class forceLoadSystemClass(String classname) 537 throws ClassNotFoundException { 538 539 Class theClass = findLoadedClass(classname); 540 541 if (theClass == null) { 542 theClass = findBaseClass(classname); 543 } 544 545 return theClass; 546 } 547 548 557 public InputStream getResourceAsStream(String name) { 558 559 InputStream resourceStream = null; 560 if (isParentFirst(name)) { 561 resourceStream = loadBaseResource(name); 562 if (resourceStream != null) { 563 565 } else { 566 resourceStream = loadResource(name); 567 if (resourceStream != null) { 568 } 570 } 571 } else { 572 resourceStream = loadResource(name); 573 if (resourceStream != null) { 574 } else { 576 resourceStream = loadBaseResource(name); 577 if (resourceStream != null) { 578 } 580 } 581 } 582 583 if (resourceStream == null) { 584 } 586 587 return resourceStream; 588 } 589 590 599 private InputStream loadResource(String name) { 600 InputStream stream = null; 603 604 Enumeration e = pathComponents.elements(); 605 while (e.hasMoreElements() && stream == null) { 606 File pathComponent = (File ) e.nextElement(); 607 stream = getResourceStream(pathComponent, name); 608 } 609 return stream; 610 } 611 612 622 private InputStream loadBaseResource(String name) { 623 if (parent == null) { 624 return getSystemResourceAsStream(name); 625 } else { 626 return parent.getResourceAsStream(name); 627 } 628 } 629 630 642 private InputStream getResourceStream(File file, String resourceName) { 643 try { 644 if (!file.exists()) { 645 return null; 646 } 647 648 if (file.isDirectory()) { 649 File resource = new File (file, resourceName); 650 651 if (resource.exists()) { 652 return new FileInputStream (resource); 653 } 654 } else { 655 ZipFile zipFile = (ZipFile ) zipFiles.get(file); 657 if (zipFile == null) { 658 zipFile = new ZipFile (file); 659 zipFiles.put(file, zipFile); 660 } 661 ZipEntry entry = zipFile.getEntry(resourceName); 662 if (entry != null) { 663 return zipFile.getInputStream(entry); 664 } 665 } 666 } catch (Exception e) { 667 } 669 670 return null; 671 } 672 673 685 private boolean isParentFirst(String resourceName) { 686 691 693 boolean useParentFirst = parentFirst; 694 695 for (Enumeration e = systemPackages.elements(); e.hasMoreElements();) { 696 String packageName = (String ) e.nextElement(); 697 if (resourceName.startsWith(packageName)) { 698 useParentFirst = true; 699 break; 700 } 701 } 702 703 for (Enumeration e = loaderPackages.elements(); e.hasMoreElements();) { 704 String packageName = (String ) e.nextElement(); 705 if (resourceName.startsWith(packageName)) { 706 useParentFirst = false; 707 break; 708 } 709 } 710 711 return useParentFirst; 712 } 713 714 726 public URL getResource(String name) { 727 URL url = null; 730 if (isParentFirst(name)) { 731 url = (parent == null) ? super.getResource(name) 732 : parent.getResource(name); 733 } 734 735 if (url != null) { 736 } else { 738 Enumeration e = pathComponents.elements(); 741 while (e.hasMoreElements() && url == null) { 742 File pathComponent = (File ) e.nextElement(); 743 url = getResourceURL(pathComponent, name); 744 if (url != null) { 745 } 747 } 748 } 749 750 if (url == null && !isParentFirst(name)) { 751 753 url = (parent == null) ? super.getResource(name) 754 : parent.getResource(name); 755 if (url != null) { 756 } 758 } 759 760 if (url == null) { 761 } 763 764 return url; 765 } 766 767 776 protected Enumeration findResources(String name) throws IOException { 777 return new ResourceEnumeration(name); 778 } 779 780 792 protected URL getResourceURL(File file, String resourceName) { 793 try { 794 if (!file.exists()) { 795 return null; 796 } 797 798 if (file.isDirectory()) { 799 File resource = new File (file, resourceName); 800 801 if (resource.exists()) { 802 try { 803 return new URL ("file:" + resource.toString()); 804 } catch (MalformedURLException ex) { 805 return null; 806 } 807 } 808 } else { 809 ZipFile zipFile = (ZipFile ) zipFiles.get(file); 810 if (zipFile == null) { 811 zipFile = new ZipFile (file); 812 zipFiles.put(file, zipFile); 813 } 814 815 ZipEntry entry = zipFile.getEntry(resourceName); 816 if (entry != null) { 817 try { 818 return new URL ("jar:file:" + file.toString() 819 + "!/" + entry); 820 } catch (MalformedURLException ex) { 821 return null; 822 } 823 } 824 } 825 } catch (Exception e) { 826 e.printStackTrace(); 827 } 828 829 return null; 830 } 831 832 852 protected synchronized Class loadClass(String classname, boolean resolve) 853 throws ClassNotFoundException { 854 858 Class theClass = findLoadedClass(classname); 859 if (theClass != null) { 860 return theClass; 861 } 862 863 if (isParentFirst(classname)) { 864 try { 865 theClass = findBaseClass(classname); 866 } catch (ClassNotFoundException cnfe) { 868 theClass = findClass(classname); 869 } 871 } else { 872 try { 873 theClass = findClass(classname); 874 } catch (ClassNotFoundException cnfe) { 876 if (ignoreBase) { 877 throw cnfe; 878 } 879 theClass = findBaseClass(classname); 880 } 882 } 883 884 if (resolve) { 885 resolveClass(theClass); 886 } 887 888 return theClass; 889 } 890 891 900 private String getClassFilename(String classname) { 901 return classname.replace('.', '/') + ".class"; 902 } 903 904 905 921 private Class getClassFromStream(InputStream stream, String classname, 922 File container) 923 throws IOException , SecurityException { 924 ByteArrayOutputStream baos = new ByteArrayOutputStream (); 925 int bytesRead = -1; 926 byte[] buffer = new byte[BUFFER_SIZE]; 927 928 while ((bytesRead = stream.read(buffer, 0, BUFFER_SIZE)) != -1) { 929 baos.write(buffer, 0, bytesRead); 930 } 931 932 byte[] classData = baos.toByteArray(); 933 return defineClass(classname, classData, 0, classData.length); 934 } 935 936 947 public Class findClass(String name) throws ClassNotFoundException { 948 Class c = findClassInComponents(name); 949 950 return c; 951 } 952 953 960 protected boolean isInPath(File component) { 961 for (Enumeration e = pathComponents.elements(); e.hasMoreElements();) { 962 File pathComponent = (File ) e.nextElement(); 963 if (pathComponent.equals(component)) { 964 return true; 965 } 966 } 967 return false; 968 } 969 970 971 982 private Class findClassInComponents(String name) 983 throws ClassNotFoundException { 984 InputStream stream = null; 987 String classFilename = getClassFilename(name); 988 try { 989 Enumeration e = pathComponents.elements(); 990 while (e.hasMoreElements()) { 991 File pathComponent = (File ) e.nextElement(); 992 try { 993 stream = getResourceStream(pathComponent, classFilename); 994 if (stream != null) { 995 return getClassFromStream(stream, name, pathComponent); 996 } 997 } catch (SecurityException se) { 998 throw se; 999 } catch (IOException ioe) { 1000 throw new ClassNotFoundException ("Failed to read file", ioe); 1001 } 1002 } 1003 1004 throw new ClassNotFoundException (name); 1005 } finally { 1006 try { 1007 if (stream != null) { 1008 stream.close(); 1009 } 1010 } catch (IOException e) { 1011 } 1013 } 1014 } 1015 1016 1031 private Class findBaseClass(String name) throws ClassNotFoundException { 1032 if (parent == null) { 1033 return findSystemClass(name); 1034 } else { 1035 return parent.loadClass(name); 1036 } 1037 } 1038 1039 1043 public synchronized void cleanup() { 1044 for (Enumeration e = zipFiles.elements(); e.hasMoreElements();) { 1045 ZipFile zipFile = (ZipFile ) e.nextElement(); 1046 try { 1047 zipFile.close(); 1048 } catch (IOException ioe) { 1049 } 1051 } 1052 zipFiles = new Hashtable (); 1053 } 1054 1055 1060 public String getPath() { 1061 String pathSeparator = System.getProperty("path.separator"); 1062 StringBuffer classpath = new StringBuffer (); 1063 if (parent != null && parent instanceof ArooaClassLoader) { 1064 classpath.append(((ArooaClassLoader) parent).getPath()); 1065 } 1066 Enumeration e = pathComponents.elements(); 1067 while (e.hasMoreElements()) { 1068 if (classpath.length() > 0) { 1069 classpath.append(pathSeparator); 1070 } 1071 File pathComponent = (File ) e.nextElement(); 1072 classpath.append(pathComponent.getPath()); 1073 } 1074 return classpath.toString(); 1075 } 1076} 1077 | Popular Tags |