import org.ibex.util.*;
import java.io.*;
import java.util.*;
+import java.text.*;
+import java.net.*;
import java.util.zip.*;
/** represents a file or directory which is scanned for updates */
public class Loader extends Watcher {
+ ClassLoader parentClassLoader = null;
+ static final ClassLoader mycl = Loader.class.getClassLoader();
public Loader(String path) { super(path); }
+ //public Loader(String path, ClassLoader pcl) { super(path); this.parentClassLoader = pcl; }
- private TreeClassLoader classloader = new TreeClassLoader();
- public ClassLoader getClassLoader() {
+ private TreeClassLoader classloader = null;
+ public synchronized ClassLoader getClassLoader() {
ClassLoader classloader = this.classloader;
if (classloader == null) {
- classloader = this.classloader = new TreeClassLoader();
- Log.warn(this, "getting classloader...");
+ String s = getClassPath();
+ StringTokenizer st = new StringTokenizer(s, File.pathSeparatorChar+"");
+ URL[] urls = new URL[st.countTokens()];
try {
- compileSource();
- } catch (Exception e) {
+ for(int i=0; i<urls.length; i++) {
+ String us = st.nextToken();
+ //if (us.endsWith(".jar")) us = "jar:file:"+us+"!/";
+ if (us.endsWith(".jar")) us = "file:"+us;
+ else us = "file:"+us+"/";
+ urls[i] = new URL(us);
+ Log.warn("[classpath]", urls[i].toString());
+ }
+ } catch (MalformedURLException e) {
Log.error(this, e);
+ return null;
}
+ classloader = this.classloader = new TreeClassLoader(urls/*, parentClassLoader*/);
+ try { compileSource(); } catch (Exception e) { Log.error(this, e); }
}
return classloader;
}
fill(vec, new File(dir.getAbsolutePath() + File.separatorChar + list[i]));
}
}
+
+ public String getClassPath() {
+ String classpath = System.getProperty("java.class.path");
+ String [] l = new File(Root.root + "/LIB/").list();
+ for(int i=0; i<l.length; i++) {
+ if (!l[i].endsWith(".jar")) continue;
+ classpath += File.pathSeparatorChar;
+ classpath += Root.root + "/LIB/" + l[i];
+ }
+ l = new File(this.path + File.separatorChar + "LIB").list();
+ for(int i=0; l!=null && i<l.length; i++) {
+ if (!l[i].endsWith(".jar")) continue;
+ classpath += File.pathSeparatorChar;
+ classpath += this.path + "/LIB/" + l[i];
+ }
+ return classpath + File.pathSeparatorChar + this.path + "/BIN";
+ }
+
private void compileSource() throws Exception {
File srcdir = new File(this.path + File.separatorChar + "SRC");
if (!srcdir.exists()) return;
+ /*
if (new File("/usr/bin/jikes").exists()) {
File bindir = new File(this.path + File.separatorChar + "BIN"); bindir.mkdirs();
- File libdir = new File(this.path + File.separatorChar + "LIB");
- String classpath = System.getProperty("java.class.path");
- String [] l = new File(Root.root + "/LIB/").list();
- for(int i=0; i<l.length; i++) {
- if (!l[i].endsWith(".jar")) continue;
- classpath += File.pathSeparatorChar;
- classpath += Root.root + "/LIB/" + l[i];
- }
String bootclasspath = System.getProperty("sun.boot.class.path", "");
Vec args = new Vec();
args.addElement("/usr/bin/jikes");
args.addElement("-nowarn");
args.addElement("-bootclasspath");
args.addElement(bootclasspath);
- args.addElement("-extdirs");
- args.addElement(libdir.getAbsolutePath());
args.addElement("-classpath");
- args.addElement(classpath);
+ args.addElement(getClassPath());
args.addElement("-sourcepath");
args.addElement(srcdir.getAbsolutePath());
args.addElement("-d");
} else {
Log.error(this, "ACK! jikes not found, javac not (yet) supported");
}
+ */
+
+ File bindir = new File(this.path + File.separatorChar + "BIN"); bindir.mkdirs();
+ Vec args = new Vec();
+ args.addElement("/usr/bin/javac");
+ args.addElement("-nowarn");
+ args.addElement("-classpath");
+ args.addElement(getClassPath());
+ args.addElement("-sourcepath");
+ args.addElement(srcdir.getAbsolutePath());
+ args.addElement("-d");
+ args.addElement(bindir.getAbsolutePath());
+ fill(args, srcdir);
+ String[] all = new String[args.size()];
+ args.copyInto(all);
+ Log.info(this, "invoking javac for " + srcdir.getAbsolutePath());
+ final Process javac = Runtime.getRuntime().exec(all);
+ final BufferedReader out = new BufferedReader(new InputStreamReader(javac.getInputStream()));
+ final BufferedReader err = new BufferedReader(new InputStreamReader(javac.getErrorStream()));
+ new Thread() { public void run() {
+ try { for(String s = out.readLine(); s != null; s = out.readLine()) Log.info("javac [stdout]", s); }
+ catch (Exception e) { Log.warn("javac", e); } } }.start();
+ new Thread() { public void run() {
+ try { for(String s = err.readLine(); s != null; s = err.readLine()) Log.info("javac [stderr]", s); }
+ catch (Exception e) { Log.warn("javac", e); } } }.start();
+ javac.waitFor();
+
}
// only watch SRC and LIB for changes
public void changed(Watched w) {
if (w.path.indexOf("BIN") != -1) return;
if (classloader != null) {
- Log.info(this, "Reloading all classes: " + path);
+ Log.info(this, "scheduling classes for reload due to change in: " + w.path);
classloader = null;
}
}
- private class TreeClassLoader extends ClassLoader {
- private Hashtable cache = new Hashtable();
+ public class TreeClassLoader extends java.net.URLClassLoader {
+
+ public String getClassPath() { return Loader.this.getClassPath(); }
+
+ public TreeClassLoader(java.net.URL[] urls) { super(urls); }
+ //private Hashtable cache = new Hashtable();
+ /*
+ public InputStream getResourceAsStream(String name) { return getInputStream(name); }
private synchronized Class defineClass(String name) {
- // first see if it's just sitting there
- File classFile = slash("BIN").slash(name.replace('.', File.separatorChar) + ".class");
- if (classFile.exists()) {
+ try {
+ InputStream is = null;
+ byte[] b = null;
try {
- FileInputStream fis = new FileInputStream(classFile);
- byte[] b = InputStreamToByteArray.convert(fis);
- fis.close();
- Log.debug(this, " loading " + name + " from " + classFile.getAbsolutePath());
- return defineClass(b, 0, b.length);
- } catch (Exception e) {
- Log.warn(this, e);
- }
+ is = getInputStream(name.replace('.', File.separatorChar) + ".class");
+ if (is == null) return null;
+ b = InputStreamToByteArray.convert(is);
+ } finally { if (is != null) is.close(); }
+ return defineClass(b, 0, b.length);
+ } catch (Exception e) {
+ Log.error(this, e);
+ return null;
}
+ }
+
+ private InputStream getInputStream(String name) {
+ // first see if it's just sitting there
+ File classFile = slash("BIN").slash(name);
+ if (classFile.exists()) try {
+ return new FileInputStream(classFile);
+ } catch (Exception e) { Log.warn(this, e); }
// then scan the jarfiles for it
File lib = slash("LIB");
- if (lib.exists() && lib.isDirectory()) {
- try {
- String[] paths = lib.list();
+ if (lib.exists() && lib.isDirectory()) try {
+ boolean first = true;
+ while(true) {
+ String[] paths = first ? lib.list() : list();
for(int i=0; i<paths.length; i++) {
if (paths[i].endsWith(".jar")) {
File f = new File(getAbsolutePath()+File.separatorChar+"LIB"+File.separatorChar+paths[i]);
- //Log.debug(this, " scanning " + f.getAbsolutePath());
+ Log.debug(this, " scanning " + f.getAbsolutePath() + " for " + name);
ZipFile zf = new ZipFile(f);
- ZipEntry ze = zf.getEntry(name.replace('.', File.separatorChar) + ".class");
- if (ze != null) {
- byte[] b = InputStreamToByteArray.convert(zf.getInputStream(ze));
- Log.debug(this, " loading " + name + " from " + f.getAbsolutePath());
- zf.close();
- return defineClass(b, 0, b.length);
- }
+ ZipEntry ze = zf.getEntry(name);
+ if (ze != null) return zf.getInputStream(ze);
zf.close();
}
}
- } catch (Exception e) {
- Log.warn(this, e);
+ if (!first) break;
+ first = false;
}
+ } catch (Exception e) { Log.warn(this, e); }
- // finally scan ourselves
- try {
- String[] paths = list();
- for(int i=0; i<paths.length; i++) {
- if (paths[i].endsWith(".jar")) {
- File f = new File(getAbsolutePath()+File.separatorChar+paths[i]);
- //Log.debug(this, " scanning " + f.getAbsolutePath());
- ZipFile zf = new ZipFile(f);
- ZipEntry ze = zf.getEntry(name.replace('.', File.separatorChar) + ".class");
- if (ze != null) {
- byte[] b = InputStreamToByteArray.convert(zf.getInputStream(ze));
- Log.debug(this, " loading " + name + " from " + f.getAbsolutePath());
- zf.close();
- return defineClass(b, 0, b.length);
- }
- zf.close();
- }
- }
- } catch (Exception e) {
- Log.warn(this, e);
- }
-
- }
-
// finally, resort to compiling it if we have to
//File src = new File(getAbsolutePath() + File.separatorChar + "SRC");
// FIXME
}
public synchronized Class loadClass(String name, boolean resolve) throws ClassNotFoundException {
- try {
- Class c = findSystemClass(name);
- if (c != null) { if (resolve) resolveClass(c); return c; }
- } catch (ClassNotFoundException e) { /* DELIBERATE */ }
Class c = (Class)cache.get(name);
- if (c == null) {
- //Log.info(this, "looking for class " + name);
- c = defineClass(name);
- if (c == null) throw new ClassNotFoundException();
- cache.put(name, c);
- }
+ if (c == null) try { c = findSystemClass(name); } catch (ClassNotFoundException cfe) { }
+ if (c == null) try { c = Class.forName(name); } catch (ClassNotFoundException cfe) { }
+ if (c == null) c = defineClass(name);
+ if (c == null) throw new ClassNotFoundException();
+ cache.put(name, c);
if (resolve) resolveClass(c);
return c;
}
+ */
}
}
super.changed(w);
}
- void dispatch(final Connection conn) throws Exception {
+ boolean dispatch(final Connection conn) throws Exception {
getClassLoader();
String[] list = list();
for(int i=0; i<list.length; i++) {
if (!list[i].endsWith(".jar")) continue;
//Log.warn(this, "checking " + (this.path + File.separatorChar + list[i]));
File f = new File(this.path + File.separatorChar + list[i]);
- ZipInputStream zis = new ZipInputStream(new FileInputStream(f));
- for(ZipEntry ze = zis.getNextEntry(); ze != null; ze = zis.getNextEntry()) {
- String name = ze.getName();
- if (name.endsWith(".class"))
- dispatch(conn, name.substring(0, name.length() - ".class".length()).replace('/', '.'));
- }
+ FileInputStream fis = null;
+ try {
+ fis = new FileInputStream(f);
+ ZipInputStream zis = new ZipInputStream(fis);
+ for(ZipEntry ze = zis.getNextEntry(); ze != null; ze = zis.getNextEntry()) {
+ String name = ze.getName();
+ if (name.endsWith(".class"))
+ if (dispatch(conn, name.substring(0, name.length() - ".class".length()).replace('/', '.')))
+ return true;
+ }
+ } finally { if (fis != null) fis.close(); }
}
- check(conn, new File(getAbsolutePath() + File.separatorChar + "BIN"));
+ if (check(conn, new File(getAbsolutePath() + File.separatorChar + "BIN"))) return true;
+ return false;
}
- void check(Connection conn, File f) throws Exception {
- //Log.warn(this, "check(" + f.getAbsolutePath() + ")");
- if (!f.exists()) return;
+ boolean check(Connection conn, File f) throws Exception {
+ if (!f.exists()) return false;
if (!f.isDirectory()) {
- if (!f.getAbsolutePath().endsWith(".class")) return;
+ if (!f.getAbsolutePath().endsWith(".class")) return false;
String name = f.getAbsolutePath().substring(getAbsolutePath().length() + 5);
name = name.substring(0, name.length() - ".class".length()).replace(File.separatorChar, '.');
- dispatch(conn, name);
+ if (dispatch(conn, name)) return true;
} else {
String[] list = f.list();
- for(int i=0; i<list.length; i++) check(conn, new File(f.getAbsolutePath() + File.separatorChar + list[i]));
+ for(int i=0; i<list.length; i++)
+ if (check(conn, new File(f.getAbsolutePath() + File.separatorChar + list[i])))
+ return true;
}
+ return false;
}
- void dispatch(final Connection conn, String name) throws Exception {
- //Log.info(this, "attempting class " + name);
+
+ boolean dispatch(final Connection conn, String name) throws Exception {
try {
- Class c = getClassLoader().loadClass(name);
- if (c != null) {
- if (Listener.class.isAssignableFrom(c)) {
- Log.error(this, "dispatching connection on port " + port + " to " +
- c.getName());
- final Listener l = (Listener)c.newInstance();
- new Thread() { public void run() {
- Log.clearnotes();
- try {
- l.accept(conn);
- } catch (Exception e) {
- Log.error(l.getClass(), "Listener threw exception");
- Log.error(l.getClass(), e);
- } finally {
- conn.close();
- }
- } }.start();
- return;
+ final ClassLoader cl = getClassLoader();
+ final Class c = cl.loadClass(name);
+ if (c == null) return false;
+ if (!(Listener.class.isAssignableFrom(c) && c != Listener.class)) return false;
+ Log.info(this, "dispatching connection on port " + port + " to " + c.getName());
+ new Thread() { public void run() {
+ Log.clearnotes();
+ Thread.currentThread().setContextClassLoader(cl);
+ try {
+ Listener l = (Listener)c.newInstance();
+ l.accept(conn);
+ } catch (Exception e) {
+ Log.error(c, "Listener threw exception");
+ Log.error(c, e);
+ } finally {
+ conn.close();
}
- }
- } catch (Exception e) {
- Log.error(this, e);
- }
+ } }.start();
+ return true;
+ } catch (Exception e) { Log.error(this, e); }
+ return false;
}
private class PortThread extends Thread {
public void run() {
try {
- Log.warn(this, "Now listening on address " + bindTo + ", port " + port);
+ Log.warn(this, "Now listening on address " + (bindTo == null ? "all interfaces" : bindTo.toString()) +
+ ", port " + port);
ServerSocket ss = bindTo == null ? new ServerSocket(port) : new ServerSocket(port, 0, bindTo);
for(Socket s = ss.accept(); ; s = ss.accept()) try {
- Log.warn(this, "accepted connection on port " + port);
- dispatch(new Connection(s, "megacz.com"));
- Log.warn(this, "done searching for service on port " + port);
+ if (!dispatch(new Connection(s, "megacz.com"))) {
+ Log.warn(this, "no handler for connection on port " + port);
+ s.close();
+ }
} catch (Exception e) { Log.warn(Port.class, e); }
} catch (Exception e) { Log.error(Port.class, e);
} catch (Throwable t) {