1 package org.ibex.jinetd;
2 import org.ibex.util.*;
7 import java.util.zip.*;
9 /** represents a file or directory which is scanned for updates */
10 public class Loader extends Watcher {
12 ClassLoader parentClassLoader = null;
13 static final ClassLoader mycl = Loader.class.getClassLoader();
14 public Loader(String path) { super(path); }
15 //public Loader(String path, ClassLoader pcl) { super(path); this.parentClassLoader = pcl; }
17 private TreeClassLoader classloader = null;
18 public synchronized ClassLoader getClassLoader() {
19 ClassLoader classloader = this.classloader;
20 if (classloader == null) {
21 String s = getClassPath();
22 StringTokenizer st = new StringTokenizer(s, File.pathSeparatorChar+"");
23 URL[] urls = new URL[st.countTokens()];
25 for(int i=0; i<urls.length; i++) {
26 String us = st.nextToken();
27 //if (us.endsWith(".jar")) us = "jar:file:"+us+"!/";
28 if (us.endsWith(".jar")) us = "file:"+us;
29 else us = "file:"+us+"/";
30 urls[i] = new URL(us);
31 Log.warn("[classpath]", urls[i].toString());
33 } catch (MalformedURLException e) {
37 classloader = this.classloader = new TreeClassLoader(urls/*, parentClassLoader*/);
38 try { compileSource(); } catch (Exception e) { Log.error(this, e); }
43 private void fill(Vec vec, File dir) {
44 if (!dir.exists()) return;
45 if (!dir.isDirectory()) {
46 if (!dir.getPath().endsWith(".java")) return;
47 vec.addElement(dir.getAbsolutePath());
49 String[] list = dir.list();
50 for(int i=0; i<list.length; i++)
51 fill(vec, new File(dir.getAbsolutePath() + File.separatorChar + list[i]));
55 public String getClassPath() {
56 String classpath = System.getProperty("java.class.path");
57 String [] l = new File(Root.root + "/LIB/").list();
58 for(int i=0; i<l.length; i++) {
59 if (!l[i].endsWith(".jar")) continue;
60 classpath += File.pathSeparatorChar;
61 classpath += Root.root + "/LIB/" + l[i];
63 l = new File(this.path + File.separatorChar + "LIB").list();
64 for(int i=0; l!=null && i<l.length; i++) {
65 if (!l[i].endsWith(".jar")) continue;
66 classpath += File.pathSeparatorChar;
67 classpath += this.path + "/LIB/" + l[i];
69 return classpath + File.pathSeparatorChar + this.path + "/BIN";
72 private void compileSource() throws Exception {
73 File srcdir = new File(this.path + File.separatorChar + "SRC");
74 if (!srcdir.exists()) return;
76 if (new File("/usr/bin/jikes").exists()) {
77 File bindir = new File(this.path + File.separatorChar + "BIN"); bindir.mkdirs();
78 String bootclasspath = System.getProperty("sun.boot.class.path", "");
80 args.addElement("/usr/bin/jikes");
81 args.addElement("+E");
82 args.addElement("-nowarn");
83 args.addElement("-bootclasspath");
84 args.addElement(bootclasspath);
85 args.addElement("-classpath");
86 args.addElement(getClassPath());
87 args.addElement("-sourcepath");
88 args.addElement(srcdir.getAbsolutePath());
89 args.addElement("-d");
90 args.addElement(bindir.getAbsolutePath());
92 String[] all = new String[args.size()];
94 Log.info(this, "invoking jikes");
95 for(int i=0; i<all.length; i++) Log.info(this, " " + all[i]);
96 final Process jikes = Runtime.getRuntime().exec(all);
97 final BufferedReader out = new BufferedReader(new InputStreamReader(jikes.getInputStream()));
98 final BufferedReader err = new BufferedReader(new InputStreamReader(jikes.getErrorStream()));
99 new Thread() { public void run() {
100 try { for(String s = out.readLine(); s != null; s = out.readLine()) Log.info("jikes[stdout]", s); }
101 catch (Exception e) { Log.warn("jikes", e); } } }.start();
102 new Thread() { public void run() {
103 try { for(String s = err.readLine(); s != null; s = err.readLine()) Log.info("jikes[stderr]", s); }
104 catch (Exception e) { Log.warn("jikes", e); } } }.start();
107 Log.error(this, "ACK! jikes not found, javac not (yet) supported");
111 File bindir = new File(this.path + File.separatorChar + "BIN"); bindir.mkdirs();
112 Vec args = new Vec();
113 args.addElement("/usr/bin/javac");
114 args.addElement("-nowarn");
115 args.addElement("-classpath");
116 args.addElement(getClassPath());
117 args.addElement("-sourcepath");
118 args.addElement(srcdir.getAbsolutePath());
119 args.addElement("-d");
120 args.addElement(bindir.getAbsolutePath());
122 String[] all = new String[args.size()];
124 Log.info(this, "invoking javac for " + srcdir.getAbsolutePath());
125 final Process javac = Runtime.getRuntime().exec(all);
126 final BufferedReader out = new BufferedReader(new InputStreamReader(javac.getInputStream()));
127 final BufferedReader err = new BufferedReader(new InputStreamReader(javac.getErrorStream()));
128 new Thread() { public void run() {
129 try { for(String s = out.readLine(); s != null; s = out.readLine()) Log.info("javac [stdout]", s); }
130 catch (Exception e) { Log.warn("javac", e); } } }.start();
131 new Thread() { public void run() {
132 try { for(String s = err.readLine(); s != null; s = err.readLine()) Log.info("javac [stderr]", s); }
133 catch (Exception e) { Log.warn("javac", e); } } }.start();
138 // only watch SRC and LIB for changes
139 public Watched slash(String path) {
140 return (path.equals("LIB") ||
141 path.equals("BIN") ||
142 path.equals("SRC") ||
143 path.endsWith(".jar") ) ? super.slash(path) : null; }
146 // dump the classloader if anything changes
147 public void changed(Watched w) {
148 if (w.path.indexOf("BIN") != -1) return;
149 if (classloader != null) {
150 Log.info(this, "scheduling classes for reload due to change in: " + w.path);
155 public class TreeClassLoader extends java.net.URLClassLoader {
157 public String getClassPath() { return Loader.this.getClassPath(); }
159 public TreeClassLoader(java.net.URL[] urls) { super(urls); }
160 //private Hashtable cache = new Hashtable();
162 public InputStream getResourceAsStream(String name) { return getInputStream(name); }
164 private synchronized Class defineClass(String name) {
166 InputStream is = null;
169 is = getInputStream(name.replace('.', File.separatorChar) + ".class");
170 if (is == null) return null;
171 b = InputStreamToByteArray.convert(is);
172 } finally { if (is != null) is.close(); }
173 return defineClass(b, 0, b.length);
174 } catch (Exception e) {
180 private InputStream getInputStream(String name) {
181 // first see if it's just sitting there
182 File classFile = slash("BIN").slash(name);
183 if (classFile.exists()) try {
184 return new FileInputStream(classFile);
185 } catch (Exception e) { Log.warn(this, e); }
187 // then scan the jarfiles for it
188 File lib = slash("LIB");
189 if (lib.exists() && lib.isDirectory()) try {
190 boolean first = true;
192 String[] paths = first ? lib.list() : list();
193 for(int i=0; i<paths.length; i++) {
194 if (paths[i].endsWith(".jar")) {
195 File f = new File(getAbsolutePath()+File.separatorChar+"LIB"+File.separatorChar+paths[i]);
196 Log.debug(this, " scanning " + f.getAbsolutePath() + " for " + name);
197 ZipFile zf = new ZipFile(f);
198 ZipEntry ze = zf.getEntry(name);
199 if (ze != null) return zf.getInputStream(ze);
206 } catch (Exception e) { Log.warn(this, e); }
208 // finally, resort to compiling it if we have to
209 //File src = new File(getAbsolutePath() + File.separatorChar + "SRC");
211 //if (!sourcebuilt) buildSource();
215 public synchronized Class loadClass(String name, boolean resolve) throws ClassNotFoundException {
216 Class c = (Class)cache.get(name);
217 if (c == null) try { c = findSystemClass(name); } catch (ClassNotFoundException cfe) { }
218 if (c == null) try { c = Class.forName(name); } catch (ClassNotFoundException cfe) { }
219 if (c == null) c = defineClass(name);
220 if (c == null) throw new ClassNotFoundException();
222 if (resolve) resolveClass(c);