tons of changes
[org.ibex.jinetd.git] / src / org / ibex / jinetd / TreeClassLoader.java
1 // Copyright 2000-2005 the Contributors, as shown in the revision logs.
2 // Licensed under the Apache Public Source License 2.0 ("the License").
3 // You may not use this file except in compliance with the License.
4
5 package org.ibex.jinetd;
6 import org.ibex.io.*;
7 import org.ibex.util.*;
8 import java.io.*;
9 import java.util.*;
10 import java.text.*;
11 import java.net.*;
12 import java.util.zip.*;
13
14 public class TreeClassLoader extends URLClassLoader {
15
16     private final File root;
17     private final File lib;
18     private Hashtable cache = new Hashtable();
19
20     public TreeClassLoader(File root, ClassLoader parent) {
21         super(new URL[] { }, parent);
22         this.root = root;
23         this.lib = new File(root.getAbsolutePath() + File.separatorChar + "lib");
24     }
25
26     // Classloading //////////////////////////////////////////////////////////////////////////////
27
28     public URL[] getURLs() {
29         try {
30             Vec v = new Vec();
31             if (getParent() != null && getParent() instanceof URLClassLoader) {
32                 URL[] parentUrls = ((URLClassLoader)getParent()).getURLs();
33                 for(int i=0; i<parentUrls.length; i++) v.addElement(parentUrls[i]);
34             }
35             String vmClasspath =
36                 System.getProperty("java.class.path") +
37                 File.pathSeparatorChar +
38                 System.getProperty("sun.boot.class.path");
39             StringTokenizer st = new StringTokenizer(vmClasspath, File.pathSeparatorChar+"");
40             while(st.hasMoreTokens()) v.addElement(new URL("file:" + st.nextToken()));
41             v.addElement(new URL("file:" + root.getAbsolutePath()));
42             v.addElement(new URL("file:" + root.getAbsolutePath() + File.separatorChar + "classes"));
43             for(Enumeration e = enumerateJarFiles(); e.hasMoreElements(); )
44                 v.addElement(new URL("file:" + ((File)e.nextElement()).getAbsolutePath()));
45             return (URL[])v.copyInto(new URL[v.size()]);
46         } catch (MalformedURLException e) {
47             Log.error(this, e);
48             return null;
49         }
50     }
51
52     private synchronized Class defineClass(String name) throws ClassNotFoundException {
53         InputStream is = null;
54         try {
55             is = getClassInputStream(name);
56             if (is == null) return null;
57             byte[] b = InputStreamToByteArray.convert(is);
58             Class ret = defineClass(b, 0, b.length);
59             cache.put(name, ret);
60             return ret;
61         } catch (Exception e) {
62             Log.error(this, e);
63             throw new ClassNotFoundException();
64         } finally {
65             if (is != null) try { is.close(); } catch (Exception e) { Log.error(this, e); }
66         }
67     }
68
69     public synchronized Class findClass(String name) throws ClassNotFoundException {
70         Class c = (Class)cache.get(name);
71         if (c==null) c = defineClass(name);
72         if (c==null) throw new ClassNotFoundException(name);
73         return c;
74     }
75
76     // Filesystem Methods //////////////////////////////////////////////////////////////////////////////
77
78     private static final FilenameFilter jarFilter =
79         new FilenameFilter() { public boolean accept(File f, String s) {return s.endsWith(".jar");}};
80     public Enumeration enumerateJarFiles() {
81         Enumeration rootJars =
82             new Misc.ArrayEnumeration(root.list(jarFilter)) {
83                 public Object nextElement() { return new File(root.getAbsolutePath()+File.separatorChar+super.nextElement()); } };
84         Enumeration libJars =
85             new Misc.ArrayEnumeration(lib.list(jarFilter)) {
86                 public Object nextElement() { return new File(lib.getAbsolutePath()+File.separatorChar+super.nextElement()); } };
87         return new Misc.JoinEnumeration(rootJars, libJars);
88     }
89
90     public InputStream getResourceAsStream(String name) {
91         InputStream ret = getInputStream(name);
92         if (ret == null) ret = getParent().getResourceAsStream(name);
93         return ret;
94     }
95
96     public InputStream getClassInputStream(String classname) { return getInputStream(classname.replace('.', '/')+".class"); }
97     public InputStream getInputStream(String name) {
98         try {
99             File f = new File(root.getAbsolutePath() + File.separatorChar + name);
100             if (f.exists()) return new FileInputStream(f);
101         } catch (IOException e) { /* DELIBERATE */ }
102         try {
103             File f = new File("classes" + File.separatorChar + root.getAbsolutePath() + File.separatorChar + name);
104             if (f.exists()) return new FileInputStream(f);
105         } catch (IOException e) { /* DELIBERATE */ }
106         for(Enumeration e = enumerateJarFiles(); e.hasMoreElements();) try {
107             ZipFile zf = new ZipFile((File)e.nextElement());
108             ZipEntry ze = zf.getEntry(name);
109             if (ze != null) return zf.getInputStream(ze);
110             zf.close();
111         } catch (Exception ex) { Log.warn(this, ex); }
112         return null;
113     }
114
115 }