1 package org.ibex.jinetd;
2 import org.ibex.util.*;
7 import java.util.zip.*;
9 public class Port extends Loader {
11 final InetAddress bindTo;
14 private static Hash cache = new Hash();
15 public static Port newPort(String path, InetAddress bindTo, int port) throws IOException {
16 String canonical = new File(path).getCanonicalPath();
17 Port p = (Port)cache.get(canonical);
18 if (p == null) cache.put(canonical, p = new Port(path, bindTo, port));
19 else Log.warn(Port.class, " sharing " + bindTo+":"+port+" -> "+ (p.bindTo+":"+p.port));
20 p.spawn(bindTo, port);
24 void spawn(InetAddress bindTo, int port) { new PortThread(bindTo, port).start(); }
25 private Port(String path, InetAddress bindTo, int port) {
31 public void changed(Watched w) {
32 //Log.warn(this, "Port: noticed change in " + w);
36 boolean dispatch(final Connection conn) throws Exception {
38 String[] list = list();
39 for(int i=0; i<list.length; i++) {
40 if (!list[i].endsWith(".jar")) continue;
41 //Log.warn(this, "checking " + (this.path + File.separatorChar + list[i]));
42 File f = new File(this.path + File.separatorChar + list[i]);
43 FileInputStream fis = null;
45 fis = new FileInputStream(f);
46 ZipInputStream zis = new ZipInputStream(fis);
47 for(ZipEntry ze = zis.getNextEntry(); ze != null; ze = zis.getNextEntry()) {
48 String name = ze.getName();
49 if (name.endsWith(".class"))
50 if (dispatch(conn, name.substring(0, name.length() - ".class".length()).replace('/', '.')))
53 } finally { if (fis != null) fis.close(); }
55 if (check(conn, new File(getAbsolutePath() + File.separatorChar + "BIN"))) return true;
59 boolean check(Connection conn, File f) throws Exception {
60 if (!f.exists()) return false;
61 if (!f.isDirectory()) {
62 if (!f.getAbsolutePath().endsWith(".class")) return false;
63 String name = f.getAbsolutePath().substring(getAbsolutePath().length() + 5);
64 name = name.substring(0, name.length() - ".class".length()).replace(File.separatorChar, '.');
65 if (dispatch(conn, name)) return true;
67 String[] list = f.list();
68 for(int i=0; i<list.length; i++)
69 if (check(conn, new File(f.getAbsolutePath() + File.separatorChar + list[i])))
75 boolean dispatch(final Connection conn, String name) throws Exception {
77 final ClassLoader cl = getClassLoader();
78 final Class c = cl.loadClass(name);
79 if (c == null) return false;
80 if (!(Listener.class.isAssignableFrom(c) && c != Listener.class)) return false;
81 Log.info(this, "dispatching connection on port " + port + " to " + c.getName());
82 new Thread(tg, new Runnable() { public void run() {
84 Thread.currentThread().setContextClassLoader(cl);
86 Listener l = (Listener)c.newInstance();
88 } catch (Exception e) {
89 Log.error(c, "Listener threw exception");
96 } catch (Exception e) { Log.error(this, e); }
100 private class PortThread extends Thread {
103 public PortThread(InetAddress bindTo, int port) { this.bindTo = bindTo; this.port = port; }
106 Log.warn(this, "Now listening on address " + (bindTo == null ? "all interfaces" : bindTo.toString()) +
108 ServerSocket ss = bindTo == null ? new ServerSocket(port) : new ServerSocket(port, 0, bindTo);
109 for(Socket s = ss.accept(); ; s = ss.accept()) try {
110 if (!dispatch(new Connection(s, "megacz.com"))) {
111 Log.warn(this, "no handler for connection on port " + port);
114 } catch (Exception e) { Log.warn(Port.class, e); }
115 } catch (Exception e) { Log.error(Port.class, e);
116 } catch (Throwable t) {
117 Log.error(this, "serious error, aborting VM");