001: // serverClassLoader.java
002: // -----------------------
003: // (C) by Michael Peter Christen; mc@anomic.de
004: // first published on http://www.anomic.de
005: // Frankfurt, Germany, 2004
006: // last major change: 11.07.2004
007: //
008: // This program is free software; you can redistribute it and/or modify
009: // it under the terms of the GNU General Public License as published by
010: // the Free Software Foundation; either version 2 of the License, or
011: // (at your option) any later version.
012: //
013: // This program is distributed in the hope that it will be useful,
014: // but WITHOUT ANY WARRANTY; without even the implied warranty of
015: // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
016: // GNU General Public License for more details.
017: //
018: // You should have received a copy of the GNU General Public License
019: // along with this program; if not, write to the Free Software
020: // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
021: //
022: // Using this software in any meaning (reading, learning, copying, compiling,
023: // running) means that you agree that the Author(s) is (are) not responsible
024: // for cost, loss of data or any harm that may be caused directly or indirectly
025: // by usage of this softare or this documentation. The usage of this software
026: // is on your own risk. The installation and usage (starting/running) of this
027: // software may allow other people or application to access your computer and
028: // any attached devices and is highly dependent on the configuration of the
029: // software which must be done by the user of the software; the author(s) is
030: // (are) also not responsible for proper configuration and usage of the
031: // software, even if provoked by documentation provided together with
032: // the software.
033: //
034: // Any changes to this file according to the GPL as documented in the file
035: // gpl.txt aside this file in the shipment you received can be done to the
036: // lines that follows this copyright notice here, but changes must not be
037: // done inside the copyright notive above. A re-distribution must contain
038: // the intact and unchanged copyright notice.
039: // Contributions and changes to the program code must be marked as such.
040:
041: package de.anomic.server;
042:
043: import java.io.File;
044: import java.io.IOException;
045: import java.util.HashMap;
046:
047: public final class serverClassLoader extends ClassLoader {
048:
049: private final HashMap<File, Class<?>> classes;
050:
051: public serverClassLoader() {
052: //super(ClassLoader.getSystemClassLoader());
053: super (Thread.currentThread().getContextClassLoader());
054: this .classes = new HashMap<File, Class<?>>();
055: }
056:
057: public serverClassLoader(ClassLoader parent) {
058: super (parent);
059: classes = new HashMap<File, Class<?>>();
060: }
061:
062: public Package[] packages() {
063: return super .getPackages();
064: }
065:
066: public Class<?> loadClass(File classfile)
067: throws ClassNotFoundException {
068: // we consider that the classkey can either be only the name of a class, or a partial or
069: // complete path to a class file
070:
071: // normalize classkey: strip off '.class'
072: //if (classkey.endsWith(".class")) classkey = classkey.substring(0, classkey.length() - 6);
073:
074: String classFileName = null;
075: try {
076: classFileName = classfile.getCanonicalPath();
077: } catch (IOException e) {
078: throw new ClassNotFoundException(
079: "Unable to resolve the classfile path");
080: }
081:
082: // try to load the class
083: synchronized (classFileName.intern()) {
084: // first try: take the class out of the cache, denoted by the classname
085: Class<?> c = (Class<?>) this .classes.get(classfile);
086: if (c != null)
087: return c;
088:
089: // consider classkey as a file and extract the file name
090: //File classfile = new File(classkey);
091: // this file cannot exist for real, since we stripped off the .class
092: // we constructed the classfile for the only purpose to strip off the name:
093:
094: // get the class name out of the classfile
095: String classname = classfile.getName();
096: int p = classname.indexOf(".");
097: classname = classname.substring(0, p);
098:
099: // now that we have the name, we can create the real class file
100: //classfile = new File(classkey + ".class");
101:
102: // This code doesn't work properly if there are multiple classes with the same name
103: // This is because we havn't definded package names in our servlets
104: //
105: // try {
106: // c = findLoadedClass(classname);
107: // if (c == null) {
108: // // second try: ask the system
109: // c = findSystemClass(classname);
110: // }
111: // if (c == null) {
112: // // third try
113: // throw new ClassNotFoundException("internal trigger");
114: // }
115: // } catch (ClassNotFoundException e) {
116: //System.out.println("INTERNAL ERROR1 in cachedClassLoader: " + e.getMessage());
117:
118: // third try: load the file from the file system
119: byte[] b;
120: try {
121: b = serverFileUtils.read(classfile);
122: // now make a class out of the stream
123: // System.out.println("loading class " + classname + " from file " + classfile.toString());
124: c = this .defineClass(null, b, 0, b.length);
125: resolveClass(c);
126: this .classes.put(classfile, c);
127: } catch (LinkageError ee) {
128: c = findLoadedClass(classname);
129: if (c != null)
130: return c;
131: } catch (IOException ee) {
132: //System.out.println("INTERNAL ERROR2 in cachedClassLoader: " + ee.getMessage());
133: throw new ClassNotFoundException(classfile.toString());
134: }
135: // }
136: return c;
137: }
138: }
139:
140: }
|