bogus patch
[org.ibex.mail.git] / src / org / ibex / jinetd / Loader.java
1 package org.ibex.jinetd;
2 import org.ibex.util.*;
3 import java.io.*;
4 import java.util.*;
5 import java.util.zip.*;
6
7 /** represents a file or directory which is scanned for updates */
8 public class Loader extends Watcher {
9
10     public Loader(String path) { super(path); }
11     
12     private TreeClassLoader classloader = new TreeClassLoader();
13     public ClassLoader getClassLoader() {
14         ClassLoader classloader = this.classloader;
15         if (classloader == null) {
16             classloader = this.classloader = new TreeClassLoader();
17             Log.warn(this, "getting classloader...");
18             try {
19                 compileSource();
20             } catch (Exception e) {
21                 Log.error(this, e);
22             }
23         }
24         return classloader;
25     }
26
27     private void fill(Vec vec, File dir) {
28         if (!dir.exists()) return;
29         if (!dir.isDirectory()) {
30             if (!dir.getPath().endsWith(".java")) return;
31             vec.addElement(dir.getAbsolutePath());
32         } else {
33             String[] list = dir.list();
34             for(int i=0; i<list.length; i++)
35                 fill(vec, new File(dir.getAbsolutePath() + File.separatorChar + list[i]));
36         }
37     }
38     private void compileSource() throws Exception {
39         File srcdir = new File(this.path + File.separatorChar + "SRC");
40         if (!srcdir.exists()) return;
41         if (new File("/usr/bin/jikes").exists()) {
42             File bindir = new File(this.path + File.separatorChar + "BIN");  bindir.mkdirs();
43             File libdir = new File(this.path + File.separatorChar + "LIB");
44             String classpath = System.getProperty("java.class.path");
45             String [] l = new File("/jinetd/LIB/").list();
46             for(int i=0; i<l.length; i++) {
47                 if (!l[i].endsWith(".jar")) continue;
48                 classpath += File.pathSeparatorChar;
49                 classpath += "/jinetd/LIB/" + l[i];
50             }
51             String bootclasspath = System.getProperty("sun.boot.class.path", "");
52             Vec args = new Vec();
53             args.addElement("/usr/bin/jikes");
54             args.addElement("+E");
55             args.addElement("-nowarn");
56             args.addElement("-bootclasspath");
57             args.addElement(bootclasspath);
58             args.addElement("-extdirs");
59             args.addElement(libdir.getAbsolutePath());
60             args.addElement("-classpath");
61             args.addElement(classpath);
62             args.addElement("-sourcepath");
63             args.addElement(srcdir.getAbsolutePath());
64             args.addElement("-d");
65             args.addElement(bindir.getAbsolutePath());
66             fill(args, srcdir);
67             String[] all = new String[args.size()];
68             args.copyInto(all);
69             Log.info(this, "invoking jikes");
70             for(int i=0; i<all.length; i++) Log.info(this, "   " + all[i]);
71             final Process jikes = Runtime.getRuntime().exec(all);
72             final BufferedReader out = new BufferedReader(new InputStreamReader(jikes.getInputStream()));
73             final BufferedReader err = new BufferedReader(new InputStreamReader(jikes.getErrorStream()));
74             new Thread() { public void run() {
75                 try { for(String s = out.readLine(); s != null; s = out.readLine()) Log.info("jikes[stdout]", s); }
76                 catch (Exception e) { Log.warn("jikes", e); } } }.start();
77             new Thread() { public void run() {
78                 try { for(String s = err.readLine(); s != null; s = err.readLine()) Log.info("jikes[stderr]", s); }
79                 catch (Exception e) { Log.warn("jikes", e); } } }.start();
80             jikes.waitFor();
81         } else {
82             Log.error(this, "ACK! jikes not found, javac not (yet) supported");
83         }
84     }
85
86     // only watch SRC and LIB for changes
87     public Watched slash(String path) {
88         return (path.equals("LIB") ||
89                 path.equals("BIN") ||
90                 path.equals("SRC") ||
91                 path.endsWith(".jar") ) ? super.slash(path) : null; }
92
93
94     // dump the classloader if anything changes
95     public void changed(Watched w) {
96         if (w.path.indexOf("BIN") != -1) return;
97         if (classloader != null) {
98             Log.info(this, "Reloading all classes: " + path);
99             classloader = null;
100         }
101     }
102     
103     private class TreeClassLoader extends ClassLoader {
104         private Hashtable cache = new Hashtable();
105
106         private synchronized Class defineClass(String name) {
107             // first see if it's just sitting there
108             File classFile = slash("BIN").slash(name.replace('.', File.separatorChar) + ".class");
109             if (classFile.exists()) {
110                 try {
111                     byte[] b = InputStreamToByteArray.convert(new FileInputStream(classFile));
112                     Log.debug(this, "  loading " + name + " from " + classFile.getAbsolutePath());
113                     return defineClass(b, 0, b.length);
114                 } catch (Exception e) {
115                     Log.warn(this, e);
116                 }
117             }
118
119             // then scan the jarfiles for it
120             File lib = slash("LIB");
121             if (lib.exists() && lib.isDirectory()) {
122                 try {
123                     String[] paths = lib.list();
124                     for(int i=0; i<paths.length; i++) {
125                         if (paths[i].endsWith(".jar")) {
126                             File f = new File(getAbsolutePath()+File.separatorChar+"LIB"+File.separatorChar+paths[i]);
127                             //Log.debug(this, "  scanning " + f.getAbsolutePath());
128                             ZipFile zf = new ZipFile(f);
129                             ZipEntry ze = zf.getEntry(name.replace('.', File.separatorChar) + ".class");
130                             if (ze != null) {
131                                 byte[] b = InputStreamToByteArray.convert(zf.getInputStream(ze));
132                                 Log.debug(this, "    loading " + name + " from " + f.getAbsolutePath());
133                                 return defineClass(b, 0, b.length);
134                             }
135                         }
136                     }
137                 } catch (Exception e) {
138                     Log.warn(this, e);
139                 }
140
141             // finally scan ourselves
142                 try {
143                     String[] paths = list();
144                     for(int i=0; i<paths.length; i++) {
145                         if (paths[i].endsWith(".jar")) {
146                             File f = new File(getAbsolutePath()+File.separatorChar+paths[i]);
147                             //Log.debug(this, "  scanning " + f.getAbsolutePath());
148                             ZipFile zf = new ZipFile(f);
149                             ZipEntry ze = zf.getEntry(name.replace('.', File.separatorChar) + ".class");
150                             if (ze != null) {
151                                 byte[] b = InputStreamToByteArray.convert(zf.getInputStream(ze));
152                                 Log.debug(this, "    loading " + name + " from " + f.getAbsolutePath());
153                                 return defineClass(b, 0, b.length);
154                             }
155                         }
156                     }
157                 } catch (Exception e) {
158                     Log.warn(this, e);
159                 }
160
161             }
162                 
163             // finally, resort to compiling it if we have to
164             //File src = new File(getAbsolutePath() + File.separatorChar + "SRC");
165             // FIXME
166             //if (!sourcebuilt) buildSource();
167             return null;
168         }
169
170         public synchronized Class loadClass(String name, boolean resolve) throws ClassNotFoundException {
171             try {
172                 Class c = findSystemClass(name);
173                 if (c != null) { if (resolve) resolveClass(c); return c; }
174             } catch (ClassNotFoundException e) { /* DELIBERATE */ }
175             Class c = (Class)cache.get(name);
176             if (c == null) {
177                 //Log.info(this, "looking for class " + name);
178                 c = defineClass(name);
179                 if (c == null) throw new ClassNotFoundException();
180                 cache.put(name, c);
181             }
182             if (resolve) resolveClass(c);
183             return c;
184         }
185     }
186 }