basically a total restructuring
[org.ibex.jinetd.git] / src / org / ibex / jinetd / Port.java
1 package org.ibex.jinetd;
2 import org.ibex.util.*;
3 import org.ibex.io.*;
4 import java.io.*;
5 import java.util.*;
6 import java.net.*;
7 import java.util.zip.*;
8
9 public class Port extends Loader {
10
11     private final InetAddress bindTo;
12     private final int port;
13     private final Thread listener;
14
15     public Port(String path, InetAddress bindTo, int port) {
16         super(path);
17         this.bindTo = bindTo;
18         this.port = port;
19         this.listener = new PortThread();
20         listener.start();
21     }
22
23     public void changed(Watched w) {
24         //Log.warn(this, "Port: noticed change in " + w);
25         super.changed(w);
26     }
27
28     boolean dispatch(final Connection conn) throws Exception {
29         getClassLoader();
30         String[] list = list();
31         for(int i=0; i<list.length; i++) {
32             if (!list[i].endsWith(".jar")) continue;
33             //Log.warn(this, "checking " + (this.path + File.separatorChar + list[i]));
34             File f = new File(this.path + File.separatorChar + list[i]);
35             FileInputStream fis = null;
36             try {
37                 fis = new FileInputStream(f);
38                 ZipInputStream zis = new ZipInputStream(fis);
39                 for(ZipEntry ze = zis.getNextEntry(); ze != null; ze = zis.getNextEntry()) {
40                     String name = ze.getName();
41                     if (name.endsWith(".class"))
42                         if (dispatch(conn, name.substring(0, name.length() - ".class".length()).replace('/', '.')))
43                             return true;
44                 }
45             } finally { if (fis != null) fis.close(); }
46         }
47         if (check(conn, new File(getAbsolutePath() + File.separatorChar + "BIN"))) return true;
48         return false;
49     }
50
51     boolean check(Connection conn, File f) throws Exception {
52         if (!f.exists()) return false;
53         if (!f.isDirectory()) {
54             if (!f.getAbsolutePath().endsWith(".class")) return false;
55             String name = f.getAbsolutePath().substring(getAbsolutePath().length() + 5);
56             name = name.substring(0, name.length() - ".class".length()).replace(File.separatorChar, '.');
57             if (dispatch(conn, name)) return true;
58         } else {
59             String[] list = f.list();
60             for(int i=0; i<list.length; i++) 
61                 if (check(conn, new File(f.getAbsolutePath() + File.separatorChar + list[i])))
62                     return true;
63         }
64         return false;
65     }
66
67     boolean dispatch(final Connection conn, String name) throws Exception {
68         try {
69             final ClassLoader cl = getClassLoader();
70             final Class c = cl.loadClass(name);
71             if (c == null) return false;
72             if (!(Listener.class.isAssignableFrom(c) && c != Listener.class)) return false;
73             Log.info(this, "dispatching connection on port " + port + " to " + c.getName());
74             new Thread() { public void run() {
75                 Log.clearnotes();
76                 Thread.currentThread().setContextClassLoader(cl);
77                 try {
78                     Listener l = (Listener)c.newInstance();
79                     l.accept(conn);
80                 } catch (Exception e) {
81                     Log.error(c, "Listener threw exception");
82                     Log.error(c, e);
83                 } finally {
84                     conn.close();
85                 }
86             } }.start();
87             return true;
88         } catch (Exception e) { Log.error(this, e); }
89         return false;
90     }
91
92     private class PortThread extends Thread {
93         public void run() {
94             try {
95                 Log.warn(this, "Now listening on address " + (bindTo == null ? "all interfaces" : bindTo.toString()) +
96                          ", port " + port);
97                 ServerSocket ss = bindTo == null ? new ServerSocket(port) : new ServerSocket(port, 0, bindTo);
98                 for(Socket s = ss.accept(); ; s = ss.accept()) try {
99                     if (!dispatch(new Connection(s, "megacz.com"))) {
100                         Log.warn(this, "no handler for connection on port " + port);
101                         s.close();
102                     }
103                 } catch (Exception e) { Log.warn(Port.class, e); }
104             } catch (Exception e) { Log.error(Port.class, e);
105             } catch (Throwable t) {
106                 Log.error(this, "serious error, aborting VM");
107                 Log.error(this, t);
108                 Root.reboot();
109             }
110         }
111     }
112 }