001: /*
002: * Janino - An embedded Java[TM] compiler
003: *
004: * Copyright (c) 2001-2007, Arno Unkrig
005: * All rights reserved.
006: *
007: * Redistribution and use in source and binary forms, with or without
008: * modification, are permitted provided that the following conditions
009: * are met:
010: *
011: * 1. Redistributions of source code must retain the above copyright
012: * notice, this list of conditions and the following disclaimer.
013: * 2. Redistributions in binary form must reproduce the above
014: * copyright notice, this list of conditions and the following
015: * disclaimer in the documentation and/or other materials
016: * provided with the distribution.
017: * 3. The name of the author may not be used to endorse or promote
018: * products derived from this software without specific prior
019: * written permission.
020: *
021: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
022: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
023: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
024: * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
025: * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
026: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
027: * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
028: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
029: * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
030: * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
031: * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
032: */
033:
034: package org.codehaus.janino.util;
035:
036: import java.io.*;
037:
038: import org.codehaus.janino.tools.Disassembler;
039: import org.codehaus.janino.util.resource.*;
040:
041: /**
042: * A {@link ClassLoader} that uses a {@link org.codehaus.janino.util.resource.ResourceFinder}
043: * to find ".class" files.
044: */
045: public class ResourceFinderClassLoader extends ClassLoader {
046: private final static boolean DEBUG = false;
047:
048: private final ResourceFinder resourceFinder;
049:
050: public ResourceFinderClassLoader(ResourceFinder resourceFinder,
051: ClassLoader parent) {
052: super (parent);
053: this .resourceFinder = resourceFinder;
054: }
055:
056: public ResourceFinder getResourceFinder() {
057: return this .resourceFinder;
058: }
059:
060: /**
061: * @throws ClassNotFoundException
062: */
063: protected Class findClass(String className)
064: throws ClassNotFoundException {
065:
066: // Find the resource containing the class bytecode.
067: Resource classFileResource = this .resourceFinder
068: .findResource(ClassFile
069: .getClassFileResourceName(className));
070: if (classFileResource == null)
071: throw new ClassNotFoundException(className);
072:
073: // Open the class file resource.
074: InputStream is;
075: try {
076: is = classFileResource.open();
077: } catch (IOException ex) {
078: throw new RuntimeException("Opening class file resource \""
079: + classFileResource.getFileName() + "\": "
080: + ex.getMessage());
081: }
082:
083: // Read bytecode from the resource into a byte array.
084: ByteArrayOutputStream baos = new ByteArrayOutputStream();
085: try {
086: byte[] buffer = new byte[4096];
087: for (;;) {
088: int bytesRead = is.read(buffer);
089: if (bytesRead == -1)
090: break;
091: baos.write(buffer, 0, bytesRead);
092: }
093: } catch (IOException ex) {
094: throw new ClassNotFoundException(
095: "Reading class file from \"" + classFileResource
096: + "\"", ex);
097: } finally {
098: try {
099: is.close();
100: } catch (IOException ex) {
101: }
102: }
103: byte[] ba = baos.toByteArray();
104:
105: // Disassemble the the class bytecode(for debugging).
106: if (ResourceFinderClassLoader.DEBUG) {
107: System.out.println("*** Disassembly of class \""
108: + className + "\":");
109: try {
110: new Disassembler().disasm(new ByteArrayInputStream(ba));
111: System.out.flush();
112: } catch (IOException ex) {
113: throw new RuntimeException(
114: "SNO: IOException despite ByteArrayInputStream");
115: }
116: }
117:
118: // Define the class in this ClassLoader.
119: Class clazz = super .defineClass(null, ba, 0, ba.length);
120:
121: if (!clazz.getName().equals(className)) {
122:
123: // This is a really complicated case: We may find a class file on
124: // the class path that seemingly defines the class we are looking
125: // for, but doesn't. This is possible if the underlying file system
126: // has case-insensitive file names and/or file names that are
127: // limited in length (e.g. DOS 8.3).
128: throw new ClassNotFoundException(className);
129: }
130:
131: return clazz;
132: }
133: }
|