X-Git-Url: http://git.megacz.com/?p=org.ibex.xt-crawshaw.git;a=blobdiff_plain;f=src%2Fjava%2Forg%2Fibex%2Fxt%2FShell.java;fp=src%2Fjava%2Forg%2Fibex%2Fxt%2FShell.java;h=0f228abb75656e3430a0f18804af158f5edcd0c4;hp=0000000000000000000000000000000000000000;hb=934297f510d5d8c584a83635f328273a6cfd7000;hpb=d55d42a0b70f398fd424010ca2cb6301016c4449 diff --git a/src/java/org/ibex/xt/Shell.java b/src/java/org/ibex/xt/Shell.java new file mode 100644 index 0000000..0f228ab --- /dev/null +++ b/src/java/org/ibex/xt/Shell.java @@ -0,0 +1,218 @@ +package org.ibex.xt; + +import java.io.*; +import java.net.*; +import java.util.*; +import java.util.regex.*; +import javax.servlet.*; +import javax.servlet.http.*; + +import org.ibex.util.*; +import org.ibex.util.Collections; +import org.ibex.js.*; + +import org.prevayler.*; + +public class Shell { + + public static void main(String[] args) throws Exception { + if (args.length == 0 || args.length > 2|| !args[0].startsWith("http://")) { + printUsage(); return; + } + Shell shell = new Shell(new URL(args[0])); + + if (args.length == 2) { + System.out.println(shell.execute(args[1])); + } else { + shell.listen(new InputStreamReader(System.in), new OutputStreamWriter(System.out)); + } + } + + private static void printUsage() { + System.out.println("Usage: xish url [command]"); + } + + /** URL of server. */ + private URL server; + + /** Current JS path using '.' as a seperator. */ + private String pwd = "."; + + /** Create a new Shell using the given url for the server. */ + public Shell(URL url) { server = url; } + + public void listen(Reader r, Writer w) throws IOException { + LineNumberReader in = new LineNumberReader(r); + PrintWriter out = new PrintWriter(w); + + out.println("Ibex xt shell. Type help or exit."); + out.print("xt: "); + out.flush(); + + String line; + String buffer = ""; + while ((line = in.readLine()) != null) { + if (line.length() > 0) { + if (line.startsWith("exit")) return; + if (line.charAt(line.length() - 1) == '\\') { + buffer += line.substring(0, line.length() - 1); + out.print('>'); + out.flush(); continue; + } + + buffer += line; + } + + if (buffer.length() > 0) { + execute(buffer, out); + buffer = ""; + } else { + out.println(""); + } + out.print("xt: "); + out.flush(); + } + } + + public String execute(String cmd) throws IOException { + StringWriter s = new StringWriter(); + execute(cmd, s); + return s.toString(); + } + + public void execute(String cmd, Writer w) throws IOException { + if (cmd == null || cmd.length() == 0) return; + String[] c = cmd.split(" "); + + //#switch(c[0]) + case "ls": + if (c.length > 2) { w.write("usage: ls [path]\n"); return; } + String path = pwd; + String matcher = ".*"; + if (c.length == 2) { + int pos = c[1].lastIndexOf('/'); + path += c[1].substring(0, pos); + path.replaceAll("/", "\\."); + if (pos + 1 < c[1].length()) { + matcher = c[1].substring(pos + 1); + matcher.replaceAll("\\.", "\\."); + matcher.replaceAll("\\*", ".*"); + } + } + + Object ret = send(new KeyRequest(path, matcher)); + if (ret == null) { + error(w, "returned object is null"); return; + } else if (ret instanceof JSExn) { + error(w, (JSExn)ret); return; + } else if (ret instanceof List) { + List l = (List)ret; Collections.sort(l); + Iterator i = l.iterator(); while (i.hasNext()) { + w.write(" "); + w.write(i.next().toString()); + w.write("\n"); + } + return; + } else { + error(w, "returned object of unknown type: "+ret.getClass().getName());return; + } + case "pwd": + w.write(pwd.replace('.', '/')); + w.write("\n"); + case "cd": + throw new Error("not yet implemented"); + case "help": + w.write("Available commands:\n"); + w.write(" ls - list entries in current object\n"); + w.write(" pwd - path of current object\n"); + w.write(" help - this message\n"); + w.write(" exit - close xt shell\n"); + //#end + } + + public void error(Writer w, String s) throws IOException { + w.write("Unexpected error: "); + w.write(s); + w.write("\n"); + } + + public void error(Writer w, JSExn e) throws IOException { + w.write("\nerror: "); + w.write(e.getMessage()); + w.write('\n'); + } + + public Object send(Request request) throws IOException { + URLConnection c = server.openConnection(); + ((HttpURLConnection)c).setRequestMethod("POST"); + c.setDoOutput(true); + c.connect(); + + ObjectOutputStream out = new ObjectOutputStream(c.getOutputStream()); + out.writeObject(request); + out.close(); + + try { + return new ObjectInputStream(c.getInputStream()).readObject(); + } catch (ClassNotFoundException e) { + e.printStackTrace(); + throw new IOException("unexpected ClassNotFoundException"); + } + } + + public static abstract class Request implements Serializable { + public abstract Object process(JSScope root) throws JSExn; + } + + public static class KeyRequest extends Request { + private String path, matcher; + public KeyRequest() {} + public KeyRequest(String path, String matcher) { + this.path = path; this.matcher = matcher; + } + + /** Returns a List. */ + public Object process(JSScope root) throws JSExn { + String p = path == null ? "" : path.replaceAll("\\.+", "\\."); + if (p.length() > 0 && p.charAt(0) == '.') p = p.substring(1); + if (p.length() > 0 && p.charAt(p.length() - 1) == '.') p = p.substring(0, p.length() - 1); + System.out.println("searching path '"+p+"' for pattern '"+matcher+"'"); + + Object o = p.equals("") ? root : root.get(p); + if (o == null || o instanceof JSDate || + o instanceof JSArray || + !(o instanceof JS)) { + System.out.println("hit bad object: "+o+", class="+ + (o == null ? null : o.getClass().getName())); + throw new JSExn("path /" + p + " does not exist"); + } else { + Pattern pat = Pattern.compile(matcher); + List keys = new ArrayList(); + + Iterator i = ((JS)o).keys().iterator(); while(i.hasNext()) { + String k = i.next().toString(); + if (pat.matcher(k).matches()) keys.add(k); + } + + return keys; + } + } + } + + public static class ExecRequest extends Request { + private JS exec; + public ExecRequest() {} + public ExecRequest(JS exec) { this.exec = exec; } + public ExecRequest(String source) throws IOException, JSExn { + this(new StringReader(source)); + } + public ExecRequest(Reader source) throws IOException, JSExn { + exec = JS.fromReader("xsh", 0, source); + } + + /** Returns the result of JS.eval(). */ + public Object process(JSScope root) throws JSExn { + return JS.eval(JS.cloneWithNewParentScope(exec, root)); + } + } +}