basically a total restructuring
authoradam <adam@megacz.com>
Tue, 3 Aug 2004 07:26:42 +0000 (07:26 +0000)
committeradam <adam@megacz.com>
Tue, 3 Aug 2004 07:26:42 +0000 (07:26 +0000)
darcs-hash:20040803072642-5007d-6f6631bb227cc73addfe64a36289624ff8823bb0.gz

src/org/ibex/jinetd/Host.java
src/org/ibex/jinetd/Loader.java
src/org/ibex/jinetd/Port.java
src/org/ibex/jinetd/Root.java
src/org/ibex/jinetd/Watcher.java

index ade17d3..c5ae337 100644 (file)
@@ -11,7 +11,7 @@ public class Host extends Loader {
 
     public void changed(Watched w) {
         super.changed(w);
-        Log.error(this, "changed(" + w + ")");
+        Log.debug(this, "changed(" + w + ")");
         try {
             ClassLoader cl = getClassLoader();
             if (cl == null) return;
index 0d6ca14..b166df6 100644 (file)
@@ -2,24 +2,40 @@ package org.ibex.jinetd;
 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;
     }
@@ -35,19 +51,30 @@ public class Loader extends Watcher {
                 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");
@@ -55,10 +82,8 @@ public class Loader extends Watcher {
             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");
@@ -81,6 +106,33 @@ public class Loader extends Watcher {
         } 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
@@ -95,77 +147,64 @@ public class Loader extends Watcher {
     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
@@ -174,19 +213,15 @@ public class Loader extends Watcher {
         }
 
         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;
         }
+        */
     }
 }
index f00e0de..037a801 100644 (file)
@@ -25,73 +25,81 @@ public class Port extends Loader {
         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) {
index 6b5467d..d8ccc36 100644 (file)
@@ -30,24 +30,24 @@ public class Root extends Loader {
 
     public void changed(Watched w) {
         if (w.part.equals("host")) {
-            Log.warn(this, "/host changed");
+            Log.debug(this, "/host changed");
         } else if (w.part.equals("port")) {
-            Log.warn(this, "/port changed");
+            Log.debug(this, "/port changed");
         } else if (w.getAbsolutePath().startsWith(Root.root + "/LIB/")) {
             if (w.lastModifiedAtLastScan != -1) {
                 Log.error(this, "jinetd upgraded; bouncing the JVM....");
                 reboot();
             }
         } else {
-            Log.info(this, "unknown directory " + w.part + " changed");
+            Log.debug(this, "unknown directory " + w.part + " changed");
         }
     }
 
     private static class PortDir extends Watched {
         public PortDir(String path) { super(path); }
         public Watched slash(String part) {
-            String ipaddr  = part.indexOf(':') == -1 ? null : part.substring(0, part.indexOf(':'));
-            String portnum = part.indexOf(':') == -1 ? part : part.substring(part.indexOf(':') + 1);
+            String ipaddr  = part.indexOf('_') == -1 ? null : part.substring(0, part.indexOf('_'));
+            String portnum = part.indexOf('_') == -1 ? part : part.substring(part.indexOf('_') + 1);
             try {
                 return new Port(this.path + File.separatorChar + part,
                                 ipaddr == null ? null : InetAddress.getByName(ipaddr),
index 86b1958..39edb17 100644 (file)
@@ -5,6 +5,7 @@ import java.util.*;
 
 public abstract class Watcher extends Watched {
     protected Watcher(String path) { super(path); }
-    public abstract void changed(Watched w);
     public Watcher watcher() { return this; }
+    public abstract void changed(Watched w);
+    public synchronized void scan() throws IOException { super.scan(); }
 }