import java.io.*;
import java.net.*;
-public class Shell extends Env {
+import org.ibex.js.*;
+import org.ibex.util.*;
+
+public class Shell {
public static void main(String[] args) throws Exception {
if (args.length == 0 || args.length > 2|| !args[0].startsWith("http://")) {
System.out.println("Usage: xish url [command]");
}
- /** URL of server. */
- protected URL server;
- /** Server cookie. Reduces server load. */
- private String cookie = null;
+ /** Supported commands. */
+ private Command[] commands;
+
+ /** Root context. */
+ private final JS root;
+
+ /** Current JS context for the shell. */
+ private JS scope;
+
+ /** Current path to <tt>scope</tt> in <tt>root</tt>. */
+ private Object[] path;
+
+ /** Returns the object represented by the given path,
+ * ignoring the current shell path context.*/
+ public Object getFromPath(Object[] path) throws BadPathException, JSExn {
+ if (path.length == 0) return root;
+
+ if (root instanceof JSRemote) {
+ // JSRemote will automatically process its keys for '.' seperators
+ StringBuffer sb = new StringBuffer(path[0].toString());
+ for (int i=1; i < path.length; i++) {
+ sb.append('.'); sb.append(path[i].toString());
+ }
+ return root.get(sb.toString());
+ } else {
+ JS cur = root;
+ for (int i=0; i < path.length - 1; i++) {
+ Object o = cur.get(path[i]);
+ if (o == null || !(o instanceof JS)) throw new Shell.BadPathException();
+ cur = (JS)o;
+ }
+ return cur.get(path[path.length - 1]);
+ }
+ }
+
+ public void transaction(JS t) {
+ if (root instanceof JSRemote) {
+ ((JSRemote)root).transaction(
+ JS.cloneWithNewParentScope(t, new JSScope(null)));
+ } else {
+ // FIXME JS.eval(JS.cloneWithNewParentScope(t, root));
+ }
+ }
+
+ /** Set the current path of the shell, modifiying the result of getScope(). */
+ public void setPath(Object[] s) throws BadPathException {
+ JS cur = root;
+ if (s == null) s = new Object[0];
+ for (int i=0; i < s.length; i++) {
+ Object o;
+ try { o = cur.get(s[i]); } catch (JSExn e) { throw new BadPathException(); }
+ if (o == null || !(o instanceof JS)) throw new BadPathException();
+ cur = (JS)o;
+ }
+ scope = cur;
+ path = s;
+ }
+
+ /** Returns the current path of the shell. */
+ public Object[] getPath() { return path; }
+
+ /** Returns String represntation of path, using '/' as a seperator. */
+ public String getPathAsString() {
+ if (path.length == 0) return "/";
+ StringBuffer sb = new StringBuffer();
+ for (int i=0; i < path.length; i++) {
+ sb.append('/'); sb.append(path[i].toString());
+ }
+ return sb.toString();
+ }
+
+ /** Returns the context matching the current path. */
+ public JS getScope() { return scope; }
+
+ /** Returns the context matching the current path. */
+ public JS getRootScope() { return root; }
+
+ /** Returns all supported commands. */
+ public Command[] getCommands() { return commands; }
+
+ /** Returns the command matching the given name. */
+ public Command getCommand(String name) {
+ for (int i=0; i < commands.length; i++)
+ if (commands[i].name().equals(name)) return commands[i];
+ return null;
+ }
/** Create a new Shell using the given url for the server. */
public Shell(URL url) {
- server = url;
+ root = scope = new JSRemote(url);
+ path = new String[0];
commands = new Command[] {
- new Command.Ls(),
- new Command.Pwd(),
- new Command.Cd(),
- new Command.Rm(),
- new Command.Help()
+ new Command.Ls(this),
+ new Command.Pwd(this),
+ new Command.Cd(this),
+ new Command.Rm(this),
+ new Command.Replace(this),
+ new Command.Mkdir(this),
+ new Command.Help(this)
};
}
PrintWriter out = new PrintWriter(w);
out.println("ibex xt shell: type help or exit");
- out.print("xt: ");
+ out.print("xt:"); out.print(getPathAsString()); out.print("# ");
out.flush();
String line;
String buffer = "";
+ int countBraceOpen = 0, countBraceClose = 0;
+ int countBracketOpen = 0, countBracketClose = 0;
+ int countSQBracketOpen = 0, countSQBracketClose = 0;
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;
+
+ for (int i=0; i < line.length(); i++) {
+ switch (line.charAt(i)) {
+ case '{': countBraceOpen++; break;
+ case '}': countBraceClose++; break;
+ case '(': countBracketOpen++; break;
+ case ')': countBracketClose++; break;
+ case '[': countSQBracketOpen++; break;
+ case ']': countSQBracketClose++; break;
+ }
}
+ boolean nonendchar = line.charAt(line.length() - 1) == '\\';
+ if (nonendchar) line = line.substring(0, line.length() - 1);
buffer += line;
+
+ if (nonendchar ||
+ countBracketOpen != countBracketClose ||
+ countBraceOpen != countBraceClose ||
+ countSQBracketOpen != countSQBracketClose) {
+ out.print('>');
+ out.flush(); continue;
+ }
}
if (buffer.length() > 0) {
String[] c = buffer.split(" ");
- Command cmd = command(c[0]);
+ Command cmd = getCommand(c[0]);
if (cmd == null) {
out.write(c[0]);
w.write(": command not found\n");
- } else cmd.execute(out, c, this);
+ } else cmd.execute(out, c);
buffer = "";
}
- out.print("xt: ");
+ out.print("xt:"); out.print(getPathAsString()); out.print("# ");
out.flush();
}
}
- public Request.Response send(Request request) throws IOException {
- URLConnection c = server.openConnection();
- ((HttpURLConnection)c).setRequestMethod("POST");
- c.setDoOutput(true);
- if (cookie != null) c.setRequestProperty("Cookie", cookie);
-
- c.connect();
-
- ObjectOutputStream out = new ObjectOutputStream(c.getOutputStream());
- out.writeObject(request);
- out.close();
-
- String cook = c.getHeaderField("Set-Cookie");
- if (cook != null && !cook.equals("")) cookie = cook.substring(0, cook.indexOf(';'));
-
- try {
- Object o = new ObjectInputStream(c.getInputStream()).readObject();
- if (o == null) {
- throw new IOException("unexpected null object returned");
- } else if (!(o instanceof Request.Response)) {
- throw new IOException("unexpected object returned: "+o.getClass().getName());
- } else {
- return (Request.Response)o;
- }
- } catch (ClassNotFoundException e) {
- e.printStackTrace();
- throw new IOException("unexpected ClassNotFoundException");
- }
+ public static class BadPathException extends Exception {
+ public BadPathException() {}
+ public BadPathException(String msg) { super(msg); }
}
}