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.
5 package org.ibex.jinetd;
7 import org.ibex.util.*;
12 import java.util.zip.*;
14 public class TreeClassLoader extends URLClassLoader {
16 private final File root;
17 private final File lib;
18 private Hashtable cache = new Hashtable();
20 public TreeClassLoader(File root, ClassLoader parent) {
21 super(new URL[] { }, parent);
22 System.out.println("TreeClassLoader("+root.getAbsolutePath()+")");
24 this.lib = new File(root.getAbsolutePath() + File.separatorChar + "lib");
27 public Enumeration getLoadedClassNames() { return cache.keys(); }
29 // Classloading //////////////////////////////////////////////////////////////////////////////
31 public URL[] getURLs() {
34 if (getParent() != null && getParent() instanceof URLClassLoader) {
35 URL[] parentUrls = ((URLClassLoader)getParent()).getURLs();
36 for(int i=0; i<parentUrls.length; i++) v.addElement(parentUrls[i]);
39 System.getProperty("java.class.path") +
40 File.pathSeparatorChar +
41 System.getProperty("sun.boot.class.path");
42 StringTokenizer st = new StringTokenizer(vmClasspath, File.pathSeparatorChar+"");
43 while(st.hasMoreTokens()) v.addElement(new URL("file:" + st.nextToken()));
44 v.addElement(new URL("file:" + root.getAbsolutePath()));
45 v.addElement(new URL("file:" + root.getAbsolutePath() + File.separatorChar + "classes"));
46 for(Enumeration e = enumerateJarFiles(); e.hasMoreElements(); )
47 v.addElement(new URL("file:" + ((File)e.nextElement()).getAbsolutePath()));
48 return (URL[])v.copyInto(new URL[v.size()]);
49 } catch (MalformedURLException e) {
55 private synchronized Class defineClass(String name) throws ClassNotFoundException {
56 InputStream is = null;
58 is = getClassInputStream(name);
59 if (is == null) return null;
60 byte[] b = InputStreamToByteArray.convert(is);
61 Class ret = defineClass(b, 0, b.length);
64 } catch (Exception e) {
66 throw new ClassNotFoundException();
68 if (is != null) try { is.close(); } catch (Exception e) { Log.error(this, e); }
72 public synchronized Class findClass(String name) throws ClassNotFoundException {
73 Class c = (Class)cache.get(name);
74 if (c==null) c = defineClass(name);
75 if (c==null) throw new ClassNotFoundException(name);
79 // Filesystem Methods //////////////////////////////////////////////////////////////////////////////
81 private static final FilenameFilter jarFilter =
82 new FilenameFilter() { public boolean accept(File f, String s) {return s.endsWith(".jar");}};
83 public Enumeration enumerateJarFiles() {
84 Enumeration rootJars =
85 new Misc.ArrayEnumeration(root.list(jarFilter)) {
86 public Object nextElement() { return new File(root.getAbsolutePath()+File.separatorChar+super.nextElement()); } };
88 new Misc.ArrayEnumeration(lib.list(jarFilter)) {
89 public Object nextElement() { return new File(lib.getAbsolutePath()+File.separatorChar+super.nextElement()); } };
90 return new Misc.JoinEnumeration(rootJars, libJars);
93 public InputStream getResourceAsStream(String name) {
94 InputStream ret = getInputStream(name);
95 if (ret == null) ret = getParent().getResourceAsStream(name);
99 public InputStream getClassInputStream(String classname) { return getInputStream(classname.replace('.', '/')+".class"); }
100 public InputStream getInputStream(String name) {
102 File f = new File(root.getAbsolutePath() + File.separatorChar + name);
103 if (f.exists()) return new FileInputStream(f);
104 } catch (IOException e) { /* DELIBERATE */ }
106 File f = new File("classes" + File.separatorChar + root.getAbsolutePath() + File.separatorChar + name);
107 if (f.exists()) return new FileInputStream(f);
108 } catch (IOException e) { /* DELIBERATE */ }
109 for(Enumeration e = enumerateJarFiles(); e.hasMoreElements();) try {
110 ZipFile zf = new ZipFile((File)e.nextElement());
111 ZipEntry ze = zf.getEntry(name);
112 if (ze != null) return zf.getInputStream(ze);
114 } catch (Exception ex) { Log.warn(this, ex); }
118 // Experimental //////////////////////////////////////////////////////////////////////////////
120 protected ThreadGroup tg = null;
121 private void nuke() {
122 if (tg.activeCount() == 0) return;
123 Log.info(this, "killing all threads for: " + root.getAbsolutePath());
124 Log.info(this, " thread count before interrupt: " + tg.activeCount());
126 try { Thread.sleep(3000); } catch (Exception e) { Log.error(this, e); }
127 Log.info(this, " thread count before kill: " + tg.activeCount());
128 Thread[] all = new Thread[tg.activeCount()];
129 tg.enumerate(all, true);
130 for(int i=0; i<all.length; i++) Stream.kill(all[i]);
131 try { Thread.sleep(3000); } catch (Exception e) { Log.error(this, e); }
132 Log.info(this, " thread count after kill: " + tg.activeCount());
133 if (tg.activeCount() > 0) {
134 Log.warn(this, " annoying threads:");
135 Thread[] annoying = new Thread[tg.activeCount()];
136 tg.enumerate(annoying, true);
137 for(int i=0; i<annoying.length; i++) {
138 Log.warn(this, " " + annoying[i]);
139 StackTraceElement[] stack = annoying[i].getStackTrace();
140 for(int j=0; j<stack.length; j++) Log.warn(this, " " + stack[j]);