Implemented issue: #56
This commit is contained in:
@@ -83,20 +83,15 @@ public class JmeIoLib extends IoLib {
|
||||
}
|
||||
|
||||
protected File openFile( String filename, boolean readMode, boolean appendMode, boolean updateMode, boolean binaryMode ) throws IOException {
|
||||
if ( appendMode || updateMode ) {
|
||||
throw new IOException("unsupported mode");
|
||||
}
|
||||
String url = "file:///" + filename;
|
||||
int mode = readMode? Connector.READ: Connector.READ_WRITE;
|
||||
StreamConnection conn = (StreamConnection) Connector.open( url, mode );
|
||||
File f = readMode?
|
||||
new FileImpl(conn, conn.openInputStream(), null):
|
||||
new FileImpl(conn, conn.openInputStream(), conn.openOutputStream());
|
||||
/*
|
||||
if ( appendMode ) {
|
||||
f.seek("end",0);
|
||||
} else {
|
||||
if ( ! readMode )
|
||||
conn.truncate(0);
|
||||
}
|
||||
*/
|
||||
new FileImpl(conn, null, conn.openOutputStream());
|
||||
return f;
|
||||
}
|
||||
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -84,14 +84,14 @@ public class JseIoLib extends IoLib {
|
||||
}
|
||||
|
||||
protected File openFile( String filename, boolean readMode, boolean appendMode, boolean updateMode, boolean binaryMode ) throws IOException {
|
||||
RandomAccessFile f = new RandomAccessFile(filename,readMode? "r": "rw");
|
||||
RandomAccessFile f = new RandomAccessFile(filename, readMode && !updateMode ? "r": "rw");
|
||||
if ( appendMode ) {
|
||||
f.seek(f.length());
|
||||
} else {
|
||||
if ( ! readMode )
|
||||
f.setLength(0);
|
||||
}
|
||||
return new FileImpl( f );
|
||||
return new FileImpl( f, readMode || updateMode, !readMode || updateMode, appendMode );
|
||||
}
|
||||
|
||||
protected File openProgram(String prog, String mode) throws IOException {
|
||||
@@ -104,7 +104,7 @@ public class JseIoLib extends IoLib {
|
||||
protected File tmpFile() throws IOException {
|
||||
java.io.File f = java.io.File.createTempFile(".luaj","bin");
|
||||
f.deleteOnExit();
|
||||
return new FileImpl( new RandomAccessFile(f,"rw") );
|
||||
return new FileImpl( new RandomAccessFile(f,"rw"), true, true, false );
|
||||
}
|
||||
|
||||
private static void notimplemented() {
|
||||
@@ -116,21 +116,27 @@ public class JseIoLib extends IoLib {
|
||||
private final RandomAccessFile file;
|
||||
private final InputStream is;
|
||||
private final OutputStream os;
|
||||
private final boolean readable;
|
||||
private final boolean writable;
|
||||
private final boolean append;
|
||||
private boolean closed = false;
|
||||
private boolean nobuffer = false;
|
||||
private FileImpl( RandomAccessFile file, InputStream is, OutputStream os ) {
|
||||
private FileImpl( RandomAccessFile file, InputStream is, OutputStream os, boolean readable, boolean writable, boolean append ) {
|
||||
this.file = file;
|
||||
this.is = is!=null? is.markSupported()? is: new BufferedInputStream(is): null;
|
||||
this.os = os;
|
||||
this.readable = readable;
|
||||
this.writable = writable;
|
||||
this.append = append;
|
||||
}
|
||||
private FileImpl( RandomAccessFile f ) {
|
||||
this( f, null, null );
|
||||
private FileImpl( RandomAccessFile f, boolean readable, boolean writable, boolean append ) {
|
||||
this( f, null, null, readable, writable, append );
|
||||
}
|
||||
private FileImpl( InputStream i ) {
|
||||
this( null, i, null );
|
||||
this( null, i, null, true, false, false );
|
||||
}
|
||||
private FileImpl( OutputStream o ) {
|
||||
this( null, null, o );
|
||||
this( null, null, o, false, true, false );
|
||||
}
|
||||
public String tojstring() {
|
||||
return "file (" + (this.closed ? "closed" : String.valueOf(this.hashCode())) + ")";
|
||||
@@ -149,11 +155,15 @@ public class JseIoLib extends IoLib {
|
||||
os.flush();
|
||||
}
|
||||
public void write(LuaString s) throws IOException {
|
||||
if ( ! writable )
|
||||
throw new IOException("file is not writable");
|
||||
if ( os != null )
|
||||
os.write( s.m_bytes, s.m_offset, s.m_length );
|
||||
else if ( file != null )
|
||||
else if ( file != null ) {
|
||||
if ( append )
|
||||
file.seek(file.length());
|
||||
file.write( s.m_bytes, s.m_offset, s.m_length );
|
||||
else
|
||||
} else
|
||||
notimplemented();
|
||||
if ( nobuffer )
|
||||
flush();
|
||||
@@ -181,11 +191,15 @@ public class JseIoLib extends IoLib {
|
||||
|
||||
// get length remaining to read
|
||||
public int remaining() throws IOException {
|
||||
if ( ! readable )
|
||||
throw new IOException("file is not readable");
|
||||
return file!=null? (int) (file.length()-file.getFilePointer()): -1;
|
||||
}
|
||||
|
||||
// peek ahead one character
|
||||
public int peek() throws IOException {
|
||||
if ( ! readable )
|
||||
throw new IOException("file is not readable");
|
||||
if ( is != null ) {
|
||||
is.mark(1);
|
||||
int c = is.read();
|
||||
@@ -203,6 +217,8 @@ public class JseIoLib extends IoLib {
|
||||
|
||||
// return char if read, -1 if eof, throw IOException on other exception
|
||||
public int read() throws IOException {
|
||||
if ( ! readable )
|
||||
throw new IOException("file is not readable");
|
||||
if ( is != null )
|
||||
return is.read();
|
||||
else if ( file != null ) {
|
||||
@@ -214,6 +230,8 @@ public class JseIoLib extends IoLib {
|
||||
|
||||
// return number of bytes read if positive, -1 if eof, throws IOException
|
||||
public int read(byte[] bytes, int offset, int length) throws IOException {
|
||||
if ( ! readable )
|
||||
throw new IOException("file is not readable");
|
||||
if (file!=null) {
|
||||
return file.read(bytes, offset, length);
|
||||
} else if (is!=null) {
|
||||
|
||||
@@ -21,6 +21,9 @@
|
||||
******************************************************************************/
|
||||
package org.luaj.vm2;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
import java.io.StringReader;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
@@ -236,6 +239,98 @@ public class FragmentsTest extends TestSuite {
|
||||
runFragment(LuaValue.valueOf(7), "return 1 | 2 & 6\n");
|
||||
}
|
||||
|
||||
public void testIoOpenReadModeDisallowsWrite() throws Exception {
|
||||
File file = writeTempFile("read-mode", "hello");
|
||||
try {
|
||||
Globals globals = JsePlatform.standardGlobals();
|
||||
try {
|
||||
globals.load("local f = io.open(" + quote(file.getAbsolutePath()) + ", 'r') f:write('x')", "io_r.lua").call();
|
||||
fail("expected write on read-only file to fail");
|
||||
} catch (LuaError e) {
|
||||
assertTrue(e.getMessage().indexOf("not writable") >= 0);
|
||||
}
|
||||
} finally {
|
||||
file.delete();
|
||||
}
|
||||
}
|
||||
|
||||
public void testIoOpenWriteModeDisallowsRead() throws Exception {
|
||||
File file = File.createTempFile("luaj-io", ".txt");
|
||||
try {
|
||||
Globals globals = JsePlatform.standardGlobals();
|
||||
try {
|
||||
globals.load("local f = io.open(" + quote(file.getAbsolutePath()) + ", 'w') return f:read('*a')", "io_w.lua").call();
|
||||
fail("expected read on write-only file to fail");
|
||||
} catch (LuaError e) {
|
||||
assertTrue(e.getMessage().indexOf("not readable") >= 0);
|
||||
}
|
||||
} finally {
|
||||
file.delete();
|
||||
}
|
||||
}
|
||||
|
||||
public void testIoOpenUpdateModesSupportReadWrite() throws Exception {
|
||||
File file = writeTempFile("update-mode", "abc");
|
||||
try {
|
||||
Globals globals = JsePlatform.standardGlobals();
|
||||
Varargs result = globals.load(
|
||||
"local f = assert(io.open(" + quote(file.getAbsolutePath()) + ", 'r+'))\n" +
|
||||
"local before = f:read('*a')\n" +
|
||||
"f:seek('set', 0)\n" +
|
||||
"f:write('xyz')\n" +
|
||||
"f:seek('set', 0)\n" +
|
||||
"local after = f:read('*a')\n" +
|
||||
"f:close()\n" +
|
||||
"return before, after\n",
|
||||
"io_rplus.lua").invoke();
|
||||
assertEquals("abc", result.arg1().tojstring());
|
||||
assertEquals("xyz", result.arg(2).tojstring());
|
||||
} finally {
|
||||
file.delete();
|
||||
}
|
||||
}
|
||||
|
||||
public void testIoOpenAppendPreservesExistingContent() throws Exception {
|
||||
File file = writeTempFile("append-mode", "abc");
|
||||
try {
|
||||
Globals globals = JsePlatform.standardGlobals();
|
||||
LuaValue result = globals.load(
|
||||
"local f = assert(io.open(" + quote(file.getAbsolutePath()) + ", 'a'))\n" +
|
||||
"f:write('xyz')\n" +
|
||||
"f:close()\n" +
|
||||
"local g = assert(io.open(" + quote(file.getAbsolutePath()) + ", 'r'))\n" +
|
||||
"local contents = g:read('*a')\n" +
|
||||
"g:close()\n" +
|
||||
"return contents\n",
|
||||
"io_a.lua").call();
|
||||
assertEquals("abcxyz", result.tojstring());
|
||||
} finally {
|
||||
file.delete();
|
||||
}
|
||||
}
|
||||
|
||||
public void testIoOpenAppendUpdateAppendsOnWriteAfterSeek() throws Exception {
|
||||
File file = writeTempFile("append-update", "abc");
|
||||
try {
|
||||
Globals globals = JsePlatform.standardGlobals();
|
||||
Varargs result = globals.load(
|
||||
"local f = assert(io.open(" + quote(file.getAbsolutePath()) + ", 'a+'))\n" +
|
||||
"f:seek('set', 0)\n" +
|
||||
"local before = f:read('*a')\n" +
|
||||
"f:seek('set', 0)\n" +
|
||||
"f:write('xyz')\n" +
|
||||
"f:seek('set', 0)\n" +
|
||||
"local after = f:read('*a')\n" +
|
||||
"f:close()\n" +
|
||||
"return before, after\n",
|
||||
"io_aplus.lua").invoke();
|
||||
assertEquals("abc", result.arg1().tojstring());
|
||||
assertEquals("abcxyz", result.arg(2).tojstring());
|
||||
} finally {
|
||||
file.delete();
|
||||
}
|
||||
}
|
||||
|
||||
public void testTableMove() {
|
||||
runFragment(
|
||||
LuaValue.varargsOf(new LuaValue[] {
|
||||
@@ -844,5 +939,20 @@ public class FragmentsTest extends TestSuite {
|
||||
+ "return v1, v2, v3");
|
||||
|
||||
}
|
||||
|
||||
private static File writeTempFile(String prefix, String contents) throws IOException {
|
||||
File file = File.createTempFile(prefix, ".txt");
|
||||
FileOutputStream out = new FileOutputStream(file);
|
||||
try {
|
||||
out.write(contents.getBytes("UTF-8"));
|
||||
} finally {
|
||||
out.close();
|
||||
}
|
||||
return file;
|
||||
}
|
||||
|
||||
private static String quote(String value) {
|
||||
return "'" + value.replace("\\", "\\\\").replace("'", "\\'") + "'";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user