001: // GeneratedClassLoader.java
002: // $Id: GeneratedClassLoader.java,v 1.4 2000/08/16 21:37:42 ylafon Exp $
003: // (c) COPYRIGHT MIT and INRIA, 1998.
004: // Please first read the full copyright statement in file COPYRIGHT.html
005:
006: package org.w3c.jigsaw.pagecompile;
007:
008: import java.io.BufferedInputStream;
009: import java.io.ByteArrayOutputStream;
010: import java.io.File;
011: import java.io.FileInputStream;
012: import java.io.FilterInputStream;
013: import java.io.IOException;
014: import java.io.InputStream;
015: import java.io.PrintStream;
016:
017: import java.net.MalformedURLException;
018: import java.net.URL;
019: import java.net.URLConnection;
020:
021: import java.util.Hashtable;
022:
023: class ClassEntry {
024:
025: long classStamp = 0;
026: Class generatedClass = null;
027: File classFile = null;
028: boolean systemClass = false;
029:
030: public boolean isModified() {
031: if (!systemClass)
032: return (classFile.lastModified() > classStamp);
033: return false;
034: }
035:
036: public void update() {
037: if (!systemClass)
038: classStamp = classFile.lastModified();
039: }
040:
041: public ClassEntry(Class generatedClass) {
042: this .generatedClass = generatedClass;
043: this .systemClass = true;
044: }
045:
046: public ClassEntry(File classFile, Class generatedClass) {
047: this .classFile = classFile;
048: this .generatedClass = generatedClass;
049: if (classFile != null)
050: this .classStamp = classFile.lastModified();
051: this .systemClass = false;
052: }
053:
054: }
055:
056: /**
057: * @version $Revision: 1.4 $
058: * @author Benoît Mahé (bmahe@w3.org)
059: */
060: public class GeneratedClassLoader extends ClassLoader {
061: private static final boolean debug = false;
062: private Hashtable classes = null;
063: private int CLASSES_DEFAULT_SIZE = 13;
064: private File generatedClassDirectory = null;
065:
066: private void trace(String msg) {
067: trace(msg, true);
068: }
069:
070: private void trace(String msg, boolean display) {
071: if (display)
072: System.out.println(msg);
073: }
074:
075: private String removeSpace(String string) {
076: int start = -1;
077: int end = string.length();
078: boolean spaces = false;
079: while (string.charAt(++start) == ' ') {
080: spaces = true;
081: }
082: ;
083: while (string.charAt(--end) == ' ') {
084: spaces = true;
085: }
086: ;
087: if (spaces)
088: return string.substring(start, ++end);
089: else
090: return new String(string);
091: }
092:
093: private String packaged(String name) {
094: String cname = removeSpace(name);
095: try {
096: if (cname.endsWith(".class")) {
097: int idx = cname.lastIndexOf('.');
098: if (idx != -1)
099: cname = cname.substring(0, idx);
100: }
101: return cname.replace('.', '/') + ".class";
102: } catch (Exception ex) {
103: return name;
104: }
105: }
106:
107: private String noext(String name) {
108: int idx = name.lastIndexOf(".class");
109: if (idx != -1) {
110: return name.substring(0, idx);
111: }
112: return name;
113: }
114:
115: protected boolean classChanged(String name) {
116: ClassEntry entry = (ClassEntry) classes.get(noext(name));
117: if (entry != null) {
118: if (debug) {
119: System.out.println("entry : " + name);
120: if (!entry.systemClass) {
121: System.out.println("file : "
122: + entry.classFile.getAbsolutePath());
123: System.out
124: .println("Stamp : " + entry.classStamp);
125: }
126: System.out.println("System : " + entry.systemClass);
127: System.out.println("modified : " + entry.isModified());
128: }
129: return entry.isModified();
130: }
131: return false; //true
132: }
133:
134: /**
135: * Get a cached class.
136: * @return a Class instance
137: * @exception ClassNotFoundException if the Class can't be found
138: */
139: protected final Class getCachedClass(String name, boolean resolve)
140: throws ClassNotFoundException {
141: ClassEntry entry = (ClassEntry) classes.get(noext(name));
142: if (entry != null) {
143: if (!entry.isModified()) {
144: trace(name + ": not modified", debug);
145: return entry.generatedClass;
146: } else if (!entry.systemClass) {
147: entry.generatedClass = loadClassFile(entry.classFile);
148: if (resolve)
149: resolveClass(entry.generatedClass);
150: entry.update();
151: trace(name + ": reloaded", debug);
152: return entry.generatedClass;
153: }
154: }
155: return null;
156: }
157:
158: protected void checkPackageAccess(String name) {
159: SecurityManager s = System.getSecurityManager();
160: if (s != null) {
161: int i = name.lastIndexOf('.');
162: if (i >= 0)
163: s.checkPackageAccess(name.substring(0, i));
164: }
165: }
166:
167: /**
168: * Given the class name, return its File name.
169: * @param name The class to be loaded.
170: * @return The File for the class.
171: */
172: protected File locateClass(String name) {
173: File classfile = null;
174: File base = generatedClassDirectory;
175: String cname = null;
176:
177: cname = packaged(name);
178: classfile = new File(base, cname);
179:
180: if (classfile != null)
181: if (classfile.exists())
182: return classfile;
183:
184: return null;
185: }
186:
187: /**
188: * Load a Class from its class file..
189: * @return a Class instance
190: * @exception ClassNotFoundException if the Class can't be found
191: */
192: protected Class loadClassFile(File file)
193: throws ClassNotFoundException {
194: byte data[] = null;
195: if (file == null)
196: throw new ClassNotFoundException("invalid class base");
197: trace("located at " + file, debug);
198: try {
199: BufferedInputStream in = new BufferedInputStream(
200: new FileInputStream(file));
201: ByteArrayOutputStream out = new ByteArrayOutputStream(512);
202: byte buf[] = new byte[512];
203: for (int got = 0; (got = in.read(buf)) > 0;)
204: out.write(buf, 0, got);
205: data = out.toByteArray();
206: in.close();
207: } catch (Exception ex) {
208: if (debug)
209: ex.printStackTrace();
210: throw new ClassNotFoundException(file.getAbsolutePath());
211: }
212: // Define the class:
213: return defineClass(data, 0, data.length);
214: }
215:
216: /**
217: * Get a new class.
218: * @return a Class instance
219: * @exception ClassNotFoundException if the Class can't be found
220: */
221: protected final Class getNewClass(File classfile, String name,
222: boolean resolve) throws ClassNotFoundException {
223: Class c = null;
224: c = loadClassFile(classfile);
225: if (resolve)
226: resolveClass(c);
227: classes.put(noext(name), new ClassEntry(classfile, c));
228: trace(name + ": loading new class done.", debug);
229: return c;
230: }
231:
232: /**
233: * Load a class.
234: * @return a Class instance
235: * @exception ClassNotFoundException if the Class can't be found
236: */
237: protected Class loadClass(String name, boolean resolve)
238: throws ClassNotFoundException {
239: Class c = null;
240: trace(name + ": loading class", debug);
241: // Look for a cached class first:
242: c = getCachedClass(name, resolve);
243: if (c != null)
244: return c;
245:
246: checkPackageAccess(name);
247:
248: File file = locateClass(name);
249:
250: if (file == null) {
251: // Then look for a system class:
252: try {
253: if ((c = findSystemClass(name)) != null) {
254: trace(name + ": system class", debug);
255: classes.put(noext(name), new ClassEntry(c));
256: return c;
257: } else
258: throw new ClassNotFoundException(name);
259: } catch (Exception ex) {
260: throw new ClassNotFoundException(name);
261: }
262: }
263:
264: // load the class
265: return getNewClass(file, name, resolve);
266: }
267:
268: public URL getResource(String name) {
269: URL resource = getSystemResource(name);
270: if (resource != null)
271: return resource;
272: String url = generatedClassDirectory.getAbsolutePath();
273: // Return the location of that resource (name resolved by j.l.Class)
274: if (File.separatorChar != '/')
275: url = url.replace(File.separatorChar, '/');
276: File file = new File(url, name);
277: if (!file.exists())
278: return null;
279: try {
280: return new URL("file", "localhost", url + "/" + name);
281: } catch (MalformedURLException ex) {
282: // Shouldn't fall here
283: return null;
284: }
285: }
286:
287: /**
288: * Get a resource as a stream.
289: * @param name The name of the resource to locate.
290: */
291:
292: public InputStream getResourceAsStream(String name) {
293: InputStream in = getSystemResourceAsStream(name);
294: if (in != null)
295: return in;
296: URL resource = getResource(name);
297: if (resource == null)
298: return null;
299: try {
300: URLConnection c = resource.openConnection();
301: return c.getInputStream();
302: } catch (IOException ex) {
303: return null;
304: }
305: }
306:
307: protected GeneratedClassLoader(GeneratedClassLoader loader) {
308: super ();
309: this .generatedClassDirectory = loader.generatedClassDirectory;
310: this .classes = loader.classes;
311: }
312:
313: protected GeneratedClassLoader(File generatedClassDirectory) {
314: super ();
315: this .generatedClassDirectory = generatedClassDirectory;
316: this .classes = new Hashtable(CLASSES_DEFAULT_SIZE);
317: }
318: }
|