001: /*
002: * Janino - An embedded Java[TM] compiler
003: *
004: * Copyright (c) 2006, 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.util.resource.*;
039:
040: /**
041: * A {@link ClassLoader} that uses a {@link org.codehaus.janino.util.resource.ResourceFinder}
042: * to find ".class" files.
043: */
044: public class ResourceFinderClassLoader extends ClassLoader {
045: private final ResourceFinder resourceFinder;
046:
047: public ResourceFinderClassLoader(ResourceFinder resourceFinder,
048: ClassLoader parent) {
049: super (parent);
050: this .resourceFinder = resourceFinder;
051: }
052:
053: public ResourceFinder getResourceFinder() {
054: return this .resourceFinder;
055: }
056:
057: /**
058: * @throws ClassNotFoundException
059: */
060: protected Class findClass(String className)
061: throws ClassNotFoundException {
062:
063: // Find the resource containing the class bytecode.
064: Resource classFileResource = this .resourceFinder
065: .findResource(ClassFile
066: .getClassFileResourceName(className));
067: if (classFileResource == null)
068: throw new ClassNotFoundException(className);
069:
070: // Open the class file resource.
071: InputStream is;
072: try {
073: is = classFileResource.open();
074: } catch (IOException ex) {
075: throw new RuntimeException("Opening class file resource \""
076: + classFileResource.getFileName() + "\": "
077: + ex.getMessage());
078: }
079:
080: // Read bytecode from the resource into a byte array.
081: ByteArrayOutputStream baos = new ByteArrayOutputStream();
082: try {
083: byte[] buffer = new byte[4096];
084: for (;;) {
085: int bytesRead = is.read(buffer);
086: if (bytesRead == -1)
087: break;
088: baos.write(buffer, 0, bytesRead);
089: }
090: } catch (IOException ex) {
091: throw new ClassNotFoundException(
092: "Reading class file from \"" + classFileResource
093: + "\"", ex);
094: } finally {
095: try {
096: is.close();
097: } catch (IOException ex) {
098: }
099: }
100: byte[] ba = baos.toByteArray();
101:
102: // Define the class in this ClassLoader.
103: Class clazz = super .defineClass(null, ba, 0, ba.length);
104:
105: if (!clazz.getName().equals(className)) {
106:
107: // This is a really complicated case: We may find a class file on
108: // the class path that seemingly defines the class we are looking
109: // for, but doesn't. This is possible if the underlying file system
110: // has case-insensitive file names and/or file names that are
111: // limited in length (e.g. DOS 8.3).
112: throw new ClassNotFoundException(className);
113: }
114:
115: return clazz;
116: }
117: }
|