Implement redirection for pluggable scripting contexts

This commit is contained in:
James Roseborough
2013-02-03 01:29:46 +00:00
parent 8a93c061f7
commit 424e80900a
4 changed files with 162 additions and 21 deletions

View File

@@ -97,7 +97,7 @@ public class ScriptEngineSample {
"print(\"string written using 'print'\")\n" + "print(\"string written using 'print'\")\n" +
"io.write(\"string written using 'io.write()'\\n\")\n" + "io.write(\"string written using 'io.write()'\\n\")\n" +
"io.stdout:write(\"string written using 'io.stdout:write()'\\n\")\n" + "io.stdout:write(\"string written using 'io.stdout:write()'\\n\")\n" +
"io.stderr:write(\"string written using 'io.stderr:write()'\\n\")\n" + "io.stderr:write(\"string written using 'io.stderr:write(), hit return to continue...'\\n\")\n" +
"io.write([[string read using 'io.stdin:read(\"*l\")':]]..io.stdin:read(\"*l\")..\"\\n\")\n"; "io.write([[string read using 'io.stdin:read(\"*l\")':]]..io.stdin:read(\"*l\")..\"\\n\")\n";
System.out.println("Evaluating script with redirection set."); System.out.println("Evaluating script with redirection set.");
@@ -114,7 +114,7 @@ public class ScriptEngineSample {
e.getContext().setReader(null); e.getContext().setReader(null);
e.getContext().setWriter(null); e.getContext().setWriter(null);
e.getContext().setErrorWriter(null); e.getContext().setErrorWriter(null);
e.eval(script); e.eval(script); // Will wait for a line from the user at this step!
System.out.println("output::>"+output+"<::output"); System.out.println("output::>"+output+"<::output");
System.out.println("errors::>"+errors+"<::errors"); System.out.println("errors::>"+errors+"<::errors");

View File

@@ -111,6 +111,14 @@ public class IoLib extends OneArgFunction {
} }
} }
/** Enumerated value representing stdin */
protected static final int FTYPE_STDIN = 0;
/** Enumerated value representing stdout */
protected static final int FTYPE_STDOUT = 1;
/** Enumerated value representing stderr */
protected static final int FTYPE_STDERR = 2;
/** Enumerated value representing a file type for a named file */
protected static final int FTYPE_NAMED = 3;
/** /**
* Wrap the standard input. * Wrap the standard input.
@@ -126,6 +134,13 @@ public class IoLib extends OneArgFunction {
*/ */
abstract protected File wrapStdout() throws IOException; abstract protected File wrapStdout() throws IOException;
/**
* Wrap the standard error output.
* @return File
* @throws IOException
*/
abstract protected File wrapStderr() throws IOException;
/** /**
* Open a file in a particular mode. * Open a file in a particular mode.
* @param filename * @param filename
@@ -295,7 +310,7 @@ public class IoLib extends OneArgFunction {
} }
private File input() { private File input() {
return infile!=null? infile: (infile=ioopenfile("-","r")); return infile!=null? infile: (infile=ioopenfile(FTYPE_STDIN, "-","r"));
} }
// io.flush() -> bool // io.flush() -> bool
@@ -320,7 +335,7 @@ public class IoLib extends OneArgFunction {
// io.input([file]) -> file // io.input([file]) -> file
public Varargs _io_input(LuaValue file) { public Varargs _io_input(LuaValue file) {
infile = file.isnil()? input(): infile = file.isnil()? input():
file.isstring()? ioopenfile(file.checkjstring(),"r"): file.isstring()? ioopenfile(FTYPE_NAMED, file.checkjstring(),"r"):
checkfile(file); checkfile(file);
return infile; return infile;
} }
@@ -328,7 +343,7 @@ public class IoLib extends OneArgFunction {
// io.output(filename) -> file // io.output(filename) -> file
public Varargs _io_output(LuaValue filename) { public Varargs _io_output(LuaValue filename) {
outfile = filename.isnil()? output(): outfile = filename.isnil()? output():
filename.isstring()? ioopenfile(filename.checkjstring(),"w"): filename.isstring()? ioopenfile(FTYPE_NAMED, filename.checkjstring(),"w"):
checkfile(filename); checkfile(filename);
return outfile; return outfile;
} }
@@ -348,12 +363,12 @@ public class IoLib extends OneArgFunction {
// io.open(filename, [mode]) -> file | nil,err // io.open(filename, [mode]) -> file | nil,err
public Varargs _io_open(String filename, String mode) throws IOException { public Varargs _io_open(String filename, String mode) throws IOException {
return rawopenfile(filename, mode); return rawopenfile(FTYPE_NAMED, filename, mode);
} }
// io.lines(filename) -> iterator // io.lines(filename) -> iterator
public Varargs _io_lines(String filename) { public Varargs _io_lines(String filename) {
infile = filename==null? input(): ioopenfile(filename,"r"); infile = filename==null? input(): ioopenfile(FTYPE_NAMED, filename,"r");
checkopen(infile); checkopen(infile);
return lines(infile); return lines(infile);
} }
@@ -420,16 +435,16 @@ public class IoLib extends OneArgFunction {
} }
private File output() { private File output() {
return outfile!=null? outfile: (outfile=ioopenfile("-","w")); return outfile!=null? outfile: (outfile=ioopenfile(FTYPE_STDOUT,"-","w"));
} }
private File errput() { private File errput() {
return errfile!=null? errfile: (errfile=ioopenfile("-","w")); return errfile!=null? errfile: (errfile=ioopenfile(FTYPE_STDERR,"-","w"));
} }
private File ioopenfile(String filename, String mode) { private File ioopenfile(int filetype, String filename, String mode) {
try { try {
return rawopenfile(filename, mode); return rawopenfile(filetype, filename, mode);
} catch ( Exception e ) { } catch ( Exception e ) {
error("io error: "+e.getMessage()); error("io error: "+e.getMessage());
return null; return null;
@@ -517,15 +532,14 @@ public class IoLib extends OneArgFunction {
error("attempt to use a closed file"); error("attempt to use a closed file");
return file; return file;
} }
private File rawopenfile(String filename, String mode) throws IOException { private File rawopenfile(int filetype, String filename, String mode) throws IOException {
boolean isstdfile = "-".equals(filename); switch (filetype) {
boolean isreadmode = mode.startsWith("r"); case FTYPE_STDIN: return wrapStdin();
if ( isstdfile ) { case FTYPE_STDOUT: return wrapStdout();
return isreadmode? case FTYPE_STDERR: return wrapStderr();
wrapStdin():
wrapStdout();
} }
boolean isreadmode = mode.startsWith("r");
boolean isappend = mode.startsWith("a"); boolean isappend = mode.startsWith("a");
boolean isupdate = mode.indexOf("+") > 0; boolean isupdate = mode.indexOf("+") > 0;
boolean isbinary = mode.endsWith("b"); boolean isbinary = mode.endsWith("b");

View File

@@ -75,6 +75,10 @@ public class JmeIoLib extends IoLib {
return new FileImpl(globals.STDOUT); return new FileImpl(globals.STDOUT);
} }
protected File wrapStderr() throws IOException {
return new FileImpl(globals.STDERR);
}
protected File openFile( String filename, boolean readMode, boolean appendMode, boolean updateMode, boolean binaryMode ) throws IOException { protected File openFile( String filename, boolean readMode, boolean appendMode, boolean updateMode, boolean binaryMode ) throws IOException {
String url = "file:///" + filename; String url = "file:///" + filename;
int mode = readMode? Connector.READ: Connector.READ_WRITE; int mode = readMode? Connector.READ: Connector.READ_WRITE;

View File

@@ -23,9 +23,11 @@ package org.luaj.vm2.lib.jse;
import java.io.BufferedInputStream; import java.io.BufferedInputStream;
import java.io.EOFException;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.io.PrintStream;
import java.io.RandomAccessFile; import java.io.RandomAccessFile;
import org.luaj.vm2.LuaError; import org.luaj.vm2.LuaError;
@@ -68,11 +70,15 @@ import org.luaj.vm2.lib.LibFunction;
public class JseIoLib extends IoLib { public class JseIoLib extends IoLib {
protected File wrapStdin() throws IOException { protected File wrapStdin() throws IOException {
return new FileImpl(globals.STDIN); return new StdinFile();
} }
protected File wrapStdout() throws IOException { protected File wrapStdout() throws IOException {
return new FileImpl(globals.STDOUT); return new StdoutFile(FTYPE_STDOUT);
}
protected File wrapStderr() throws IOException {
return new StdoutFile(FTYPE_STDERR);
} }
protected File openFile( String filename, boolean readMode, boolean appendMode, boolean updateMode, boolean binaryMode ) throws IOException { protected File openFile( String filename, boolean readMode, boolean appendMode, boolean updateMode, boolean binaryMode ) throws IOException {
@@ -103,6 +109,7 @@ public class JseIoLib extends IoLib {
throw new LuaError("not implemented"); throw new LuaError("not implemented");
} }
private final class FileImpl extends File { private final class FileImpl extends File {
private final RandomAccessFile file; private final RandomAccessFile file;
private final InputStream is; private final InputStream is;
@@ -215,4 +222,120 @@ public class JseIoLib extends IoLib {
return length; return length;
} }
} }
private final class StdoutFile extends File {
private final int file_type;
private StdoutFile(int file_type) {
this.file_type = file_type;
}
public String tojstring() {
return "file ("+this.hashCode()+")";
}
private final PrintStream getPrintStream() {
return file_type == FTYPE_STDERR?
globals.STDERR:
globals.STDOUT;
}
public void write(LuaString string) throws IOException {
getPrintStream().write(string.m_bytes, string.m_offset, string.m_length);
}
public void flush() throws IOException {
getPrintStream().flush();
}
public boolean isstdfile() {
return true;
}
public void close() throws IOException {
// do not close std files.
}
public boolean isclosed() {
return false;
}
public int seek(String option, int bytecount) throws IOException {
return 0;
}
public void setvbuf(String mode, int size) {
}
public int remaining() throws IOException {
return 0;
}
public int peek() throws IOException, EOFException {
return 0;
}
public int read() throws IOException, EOFException {
return 0;
}
public int read(byte[] bytes, int offset, int length)
throws IOException {
return 0;
}
}
private final class StdinFile extends File {
private StdinFile() {
}
public String tojstring() {
return "file ("+this.hashCode()+")";
}
public void write(LuaString string) throws IOException {
}
public void flush() throws IOException {
}
public boolean isstdfile() {
return true;
}
public void close() throws IOException {
// do not close std files.
}
public boolean isclosed() {
return false;
}
public int seek(String option, int bytecount) throws IOException {
return 0;
}
public void setvbuf(String mode, int size) {
}
public int remaining() throws IOException {
return 0;
}
public int peek() throws IOException, EOFException {
globals.STDIN.mark(1);
int c = globals.STDIN.read();
globals.STDIN.reset();
return c;
}
public int read() throws IOException, EOFException {
return globals.STDIN.read();
}
public int read(byte[] bytes, int offset, int length)
throws IOException {
return globals.STDIN.read(bytes, offset, length);
}
}
} }