import sun.tools.javac.Main; import java.io.*; import java.net.*; class ExitSecurityException extends SecurityException { public int exitcode; public ExitSecurityException(int c) { exitcode = c; } } /** The main problem in reusing sun.tools.javac.Main is that it calls System.exit() when done. So we install this SecurityManager to trap the call to System.exit(). This also gives us some cool information on what system calls javac makes. */ class CompileSecurityManager extends java.lang.SecurityManager { PrintStream err; CompileSecurityManager(PrintStream e) { err = e; } public void checkAccept(String host, int port) { } public void checkAccess(Thread g) { return; } public void checkConnect(String host, int port) { //err.println("Connecting to " + host + ":" + port); } public void checkCreateClassLoader() { err.println("Create Class Loader"); } public void checkLink(String lib) { err.println("Loading library: " + lib); } public void checkListen(int port) { err.println("Listening on port " + port); } public void checkPackageAccess(String pkg) { err.println("Using package: " + pkg); } public void checkExec(String cmd) { if (!cmd.equals("setio")) super.checkExec(cmd); //err.println("Exec " + cmd); } public void checkPropertiesAccess() { return; } public void checkPropertyAccess(String key) { return; } public void checkRead(FileDescriptor fd) { return; } public void checkRead(String file) { //err.println("Reading file `" + file + "'"); } public void checkSetFactory() { return; } public void checkWrite(FileDescriptor fd) { return; } public void checkWrite(String file) { err.println("Writing file `" + file + "'"); } public void checkExit(int code) { throw new ExitSecurityException(code); } } class CompileServer { private ServerSocket listen; // listener port private Socket sock; // current request connection private DataInputStream instream; public void close() throws IOException { if (sock != null) { instream = null; try { sock.close(); } finally { sock = null; } } if (listen != null) { listen.close(); listen = null; } } protected void finalize() { try { close(); } catch (IOException err) { } } public CompileServer(int port) throws IOException { listen = new ServerSocket(port); } public String[] getRequest() throws IOException { if (listen == null) return null; if (sock != null) sock.close(); sock = listen.accept(); InetAddress saddr = sock.getInetAddress(); String host = saddr.getHostName(); int port = sock.getPort(); PrintStream so = new PrintStream(sock.getOutputStream()); System.setOut(so); // compiler output System.setErr(so); // compiler errs System.err.println("Accepting call from " + host + ":" + port); instream = new DataInputStream(sock.getInputStream()); String[] res = null; try { int cnt = instream.readShort(); res = new String[cnt]; for (int i = 0; i < cnt; ++i) res[i] = instream.readUTF(); } catch (EOFException e) { sock.close(); sock = null; } return res; } public static void main(String[] args) { PrintStream err = System.out; try { CompileServer server = new CompileServer(2009); CompileSecurityManager sm = new CompileSecurityManager(System.err); System.setSecurityManager(sm); for (;;) { String[] nargs = server.getRequest(); if (nargs == null) break; try { System.out.print("javac"); for (int i = 0; i < nargs.length; ++i) System.out.print(" " + nargs[i]); System.out.println(); try { Main.main(nargs); } catch (ExitSecurityException e) { System.out.println("Exit " + e.exitcode); } catch (SecurityException e) { System.err.println(e); System.out.println("Exit 2"); } } catch (Exception e) { System.err.println(e); System.out.println("Exit 1"); } } } catch (Exception e) { e.printStackTrace(); } } }