/////////////////////////////////////////////////////////////////////// // VerbLearn System // // A crosslinguistic bodily-grounded hand-action // verb semantics acquisition system. // // David Bailey 1/97 // Converted from Sather 1.1 // // File: Jack.java // // Description: Interface to Jack animation package. // THIS OUGHT TO BE CONVERTED TO JAVA 1.1's RMI. // // Classes: Jack, JackStub, JackTest import java.io.*; import java.net.*; /////////////////////////////////////////////////////////////////////// // Interface to Jack running on a SGI machine, for the visualization // of x-schema execution and in order to compute linking Fstructs // resulting from action. class Jack { private static final String JACK_HOST = "montoya.icsi.berkeley.edu"; private static final int MAX_SOCKET_TRIES = 10; private static final long SOCKET_RETRY_INTERVAL = 1000; // in milliseconds static final int JACK_PORT = 6666; public static final String ABSOLUTE_BASE_DIR = "/u/dbailey/thesis/src/"; private static ObjectInputStream sIn; private static ObjectOutputStream sOut; private static Process jackstub; private static boolean started = false; // Initialize Jack system, including startup of remote processes // PERHAPS THIS COULD EVENTUALLY BE DONE VIA A CGI-SCRIPT, ALLOWING IT // TO RUN EVEN THROUGH NETSCAPE. public static void start(boolean debug) throws InterruptedException { if (started) { System.err.println("Jack: Already started, can't do it again."); System.exit(1); } try { // Start up the Jackstub program on the SGI machine: jackstub = Runtime.getRuntime() .exec("rsh " + JACK_HOST + "'cd " + ABSOLUTE_BASE_DIR + "java; java JackStub" + (debug ? " -debug" : "") + "'"); } catch (Exception e) { System.err.println("Jack: Died trying to run JackStub: " + e.getMessage()); System.exit(1); } // Make a socket connection to Jackstub: int numTries = 0; String errMsg = ""; Socket s = null; while (s == null && numTries < MAX_SOCKET_TRIES) { try { s = new Socket(JACK_HOST, JACK_PORT); } catch (IOException e) { errMsg = e.getMessage(); Thread.currentThread().sleep(SOCKET_RETRY_INTERVAL); } numTries += 1; } if (s == null) { System.err.println("Jack: Died trying to create socket: " + errMsg); System.exit(1); } try { sIn = new ObjectInputStream(s.getInputStream()); sOut = new ObjectOutputStream(s.getOutputStream()); } catch (Exception e) { System.err.println("Jack: Died trying to get streams of socket: " + e.getMessage()); System.exit(1); } try { // Await confirmation string from Jackstub: if (!((String)sIn.readObject()).equals("STARTED")) { System.err.println("Jack: JackStub didn't send confirmation."); System.exit(1); } } catch (Exception e) { System.err.println("Jack: Died trying read confirmation on socket: " + e.getMessage()); System.exit(1); } started = true; } // Blocking send of a JCL command. Returns true if successful. public static boolean send(String cmd) { if (!started) { System.err.println("Jack: Tried to send commands before starting Jack"); return false; } try { sOut.writeObject(cmd); String status = (String)sIn.readObject(); return status.equals("SUCCESS"); } catch (Exception e) { System.err.println("Died trying to use socket to JackStub: " + e.getMessage()); System.exit(1); } return false; // this line to satisfy compiler... } public static void finish() { jackstub.destroy(); started = false; } } /////////////////////////////////////////////////////////////////////// // Pass commands sent via socket to Jack, and return results. class JackStub { // Number of times to retry C API connection to Jack. About 1 // retry per second. Allows for Jack startup time. private static final int RETRIES = 25; // File to pass to Jack upon startup. private static final String JACK_STARTUP_FILE = "jack/VL_init.jcl"; private static ObjectInputStream sIn; private static ObjectOutputStream sOut; private static Process jack; public static void main(String[] args) throws IOException, InterruptedException { // Parse command line: if (!(args.length == 0 || (args.length == 1 && args[0].equals("-debug")))) { System.err.println("JackStub: Format is java JackStub [-debug]."); System.exit(1); } boolean debug = (args.length == 1); try { // Make a socket connection to VerbLearn: if (debug) { System.err.println("JackStub: Creating server socket."); } Socket s = new ServerSocket(Jack.JACK_PORT).accept(); sIn = new ObjectInputStream(s.getInputStream()); sOut = new ObjectOutputStream(s.getOutputStream()); // Start Jack: if (debug) System.err.println("JackStub: Starting Jack."); jack = Runtime.getRuntime() .exec("cd " + Jack.ABSOLUTE_BASE_DIR + "; " + "DISPLAY=localhost:0; export DISPLAY; " + "jack -w " + JACK_STARTUP_FILE); // How to check if OK? // Start C API: if (debug) System.err.println("JackStub: Starting Jack C API"); int status = JACKrpc_init(null, RETRIES, (debug ? "JackStub: Retrying RPC connection" : "")); if (status != 1) { System.err.println("JackStub: Failed to start Jack C API."); shutdown(1); } // Send confirmation message to VerbLearn if (debug) System.err.println("JackStub: Startup complete."); sOut.writeObject("STARTED"); // Enter command processing loop: if (debug) System.err.println("JackStub: Entering command loop."); String cmd; do { cmd = (String)sIn.readObject(); if (debug) System.err.println("JackStub: Received command " + cmd); status = JACKjcl(cmd, 0); if (status != 1) { System.err.println("JackStub: Jack command failed, sending ack."); sOut.writeObject("FAILURE"); } else { if (debug) { System.err.println("JackStub: Completed command, sending ack."); } sOut.writeObject("SUCCESS"); } } while (!cmd.substring(0, 5).equals("quit(")); // Try to clean up: shutdown(0); } catch (Exception e) { System.err.println("JackStub: Died w/Exception during setup: " + e.getMessage()); shutdown(1); } } // Quit, trying to kill the jack process too. private static void shutdown(int code) throws IOException, InterruptedException { if (jack != null) { // Shotgun approach here... Runtime.getRuntime().exec("killname 'jack -w'").waitFor(); jack.destroy(); } System.exit(code); } native static int JACKrpc_init(String servernm, int retries, String msg); native static int JACKjcl(String cmd, int correctErrors); } /////////////////////////////////////////////////////////////////////// // Test socket-based interface to JackStub and Jack running on an SGI machine. class JackTest { public static void main(String[] args) throws IOException, InterruptedException { // Parse command line: if (!(args.length == 0 || (args.length == 1 && args[0].equals("-debug")))) { System.err.println("JackTest: Format is java JackTest [-debug]."); System.exit(1); } boolean debug = (args.length == 1); System.out.println("JackTest: Starting JackStub."); Jack.start(debug); BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); while (true) { System.out.print("Enter JCL command:"); String cmd = br.readLine(); if (cmd.equals("")) break; System.out.println("Command is " + cmd); boolean success = Jack.send(cmd); if (success) System.out.print("Succeeded"); else System.out.print("Failed"); } Jack.finish(); } }