tons of changes
[org.ibex.jinetd.git] / src / org / ibex / jinetd / TreeClassLoader.java
diff --git a/src/org/ibex/jinetd/TreeClassLoader.java b/src/org/ibex/jinetd/TreeClassLoader.java
new file mode 100644 (file)
index 0000000..e9f901f
--- /dev/null
@@ -0,0 +1,115 @@
+// Copyright 2000-2005 the Contributors, as shown in the revision logs.
+// Licensed under the Apache Public Source License 2.0 ("the License").
+// You may not use this file except in compliance with the License.
+
+package org.ibex.jinetd;
+import org.ibex.io.*;
+import org.ibex.util.*;
+import java.io.*;
+import java.util.*;
+import java.text.*;
+import java.net.*;
+import java.util.zip.*;
+
+public class TreeClassLoader extends URLClassLoader {
+
+    private final File root;
+    private final File lib;
+    private Hashtable cache = new Hashtable();
+
+    public TreeClassLoader(File root, ClassLoader parent) {
+        super(new URL[] { }, parent);
+        this.root = root;
+        this.lib = new File(root.getAbsolutePath() + File.separatorChar + "lib");
+    }
+
+    // Classloading //////////////////////////////////////////////////////////////////////////////
+
+    public URL[] getURLs() {
+        try {
+            Vec v = new Vec();
+            if (getParent() != null && getParent() instanceof URLClassLoader) {
+                URL[] parentUrls = ((URLClassLoader)getParent()).getURLs();
+                for(int i=0; i<parentUrls.length; i++) v.addElement(parentUrls[i]);
+            }
+            String vmClasspath =
+                System.getProperty("java.class.path") +
+                File.pathSeparatorChar +
+                System.getProperty("sun.boot.class.path");
+            StringTokenizer st = new StringTokenizer(vmClasspath, File.pathSeparatorChar+"");
+            while(st.hasMoreTokens()) v.addElement(new URL("file:" + st.nextToken()));
+            v.addElement(new URL("file:" + root.getAbsolutePath()));
+            v.addElement(new URL("file:" + root.getAbsolutePath() + File.separatorChar + "classes"));
+            for(Enumeration e = enumerateJarFiles(); e.hasMoreElements(); )
+                v.addElement(new URL("file:" + ((File)e.nextElement()).getAbsolutePath()));
+            return (URL[])v.copyInto(new URL[v.size()]);
+        } catch (MalformedURLException e) {
+            Log.error(this, e);
+            return null;
+        }
+    }
+
+    private synchronized Class defineClass(String name) throws ClassNotFoundException {
+        InputStream is = null;
+        try {
+            is = getClassInputStream(name);
+            if (is == null) return null;
+            byte[] b = InputStreamToByteArray.convert(is);
+            Class ret = defineClass(b, 0, b.length);
+            cache.put(name, ret);
+            return ret;
+        } catch (Exception e) {
+            Log.error(this, e);
+            throw new ClassNotFoundException();
+        } finally {
+            if (is != null) try { is.close(); } catch (Exception e) { Log.error(this, e); }
+        }
+    }
+
+    public synchronized Class findClass(String name) throws ClassNotFoundException {
+        Class c = (Class)cache.get(name);
+        if (c==null) c = defineClass(name);
+        if (c==null) throw new ClassNotFoundException(name);
+        return c;
+    }
+
+    // Filesystem Methods //////////////////////////////////////////////////////////////////////////////
+
+    private static final FilenameFilter jarFilter =
+        new FilenameFilter() { public boolean accept(File f, String s) {return s.endsWith(".jar");}};
+    public Enumeration enumerateJarFiles() {
+        Enumeration rootJars =
+            new Misc.ArrayEnumeration(root.list(jarFilter)) {
+                public Object nextElement() { return new File(root.getAbsolutePath()+File.separatorChar+super.nextElement()); } };
+        Enumeration libJars =
+            new Misc.ArrayEnumeration(lib.list(jarFilter)) {
+                public Object nextElement() { return new File(lib.getAbsolutePath()+File.separatorChar+super.nextElement()); } };
+        return new Misc.JoinEnumeration(rootJars, libJars);
+    }
+
+    public InputStream getResourceAsStream(String name) {
+        InputStream ret = getInputStream(name);
+        if (ret == null) ret = getParent().getResourceAsStream(name);
+        return ret;
+    }
+
+    public InputStream getClassInputStream(String classname) { return getInputStream(classname.replace('.', '/')+".class"); }
+    public InputStream getInputStream(String name) {
+        try {
+            File f = new File(root.getAbsolutePath() + File.separatorChar + name);
+            if (f.exists()) return new FileInputStream(f);
+        } catch (IOException e) { /* DELIBERATE */ }
+        try {
+            File f = new File("classes" + File.separatorChar + root.getAbsolutePath() + File.separatorChar + name);
+            if (f.exists()) return new FileInputStream(f);
+        } catch (IOException e) { /* DELIBERATE */ }
+        for(Enumeration e = enumerateJarFiles(); e.hasMoreElements();) try {
+            ZipFile zf = new ZipFile((File)e.nextElement());
+            ZipEntry ze = zf.getEntry(name);
+            if (ze != null) return zf.getInputStream(ze);
+            zf.close();
+        } catch (Exception ex) { Log.warn(this, ex); }
+        return null;
+    }
+
+}