mirror of
https://github.com/SquidDev-CC/CC-Tweaked
synced 2025-01-20 22:16:57 +00:00
Merge pull request #238 from SquidDev-CC/feature/binary-handles
Refactor the filesystem and HTTP code
This commit is contained in:
commit
ba4b1e21fe
@ -7,15 +7,17 @@
|
|||||||
package dan200.computercraft.core.apis;
|
package dan200.computercraft.core.apis;
|
||||||
|
|
||||||
import dan200.computercraft.api.lua.ILuaContext;
|
import dan200.computercraft.api.lua.ILuaContext;
|
||||||
import dan200.computercraft.api.lua.ILuaObject;
|
|
||||||
import dan200.computercraft.api.lua.LuaException;
|
import dan200.computercraft.api.lua.LuaException;
|
||||||
|
import dan200.computercraft.core.apis.handles.BinaryInputHandle;
|
||||||
|
import dan200.computercraft.core.apis.handles.BinaryOutputHandle;
|
||||||
|
import dan200.computercraft.core.apis.handles.EncodedInputHandle;
|
||||||
|
import dan200.computercraft.core.apis.handles.EncodedOutputHandle;
|
||||||
import dan200.computercraft.core.filesystem.FileSystem;
|
import dan200.computercraft.core.filesystem.FileSystem;
|
||||||
import dan200.computercraft.core.filesystem.FileSystemException;
|
import dan200.computercraft.core.filesystem.FileSystemException;
|
||||||
import dan200.computercraft.core.filesystem.IMountedFileBinary;
|
|
||||||
import dan200.computercraft.core.filesystem.IMountedFileNormal;
|
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
import java.io.IOException;
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
@ -259,33 +261,33 @@ public class FSAPI implements ILuaAPI
|
|||||||
try {
|
try {
|
||||||
if( mode.equals( "r" ) ) {
|
if( mode.equals( "r" ) ) {
|
||||||
// Open the file for reading, then create a wrapper around the reader
|
// Open the file for reading, then create a wrapper around the reader
|
||||||
IMountedFileNormal reader = m_fileSystem.openForRead( path );
|
InputStream reader = m_fileSystem.openForRead( path );
|
||||||
return wrapBufferedReader( reader );
|
return new Object[] { new EncodedInputHandle( reader ) };
|
||||||
|
|
||||||
} else if( mode.equals( "w" ) ) {
|
} else if( mode.equals( "w" ) ) {
|
||||||
// Open the file for writing, then create a wrapper around the writer
|
// Open the file for writing, then create a wrapper around the writer
|
||||||
IMountedFileNormal writer = m_fileSystem.openForWrite( path, false );
|
OutputStream writer = m_fileSystem.openForWrite( path, false );
|
||||||
return wrapBufferedWriter( writer );
|
return new Object[] { new EncodedOutputHandle( writer ) };
|
||||||
|
|
||||||
} else if( mode.equals( "a" ) ) {
|
} else if( mode.equals( "a" ) ) {
|
||||||
// Open the file for appending, then create a wrapper around the writer
|
// Open the file for appending, then create a wrapper around the writer
|
||||||
IMountedFileNormal writer = m_fileSystem.openForWrite( path, true );
|
OutputStream writer = m_fileSystem.openForWrite( path, true );
|
||||||
return wrapBufferedWriter( writer );
|
return new Object[] { new EncodedOutputHandle( writer ) };
|
||||||
|
|
||||||
} else if( mode.equals( "rb" ) ) {
|
} else if( mode.equals( "rb" ) ) {
|
||||||
// Open the file for binary reading, then create a wrapper around the reader
|
// Open the file for binary reading, then create a wrapper around the reader
|
||||||
IMountedFileBinary reader = m_fileSystem.openForBinaryRead( path );
|
InputStream reader = m_fileSystem.openForRead( path );
|
||||||
return wrapInputStream( reader );
|
return new Object[] { new BinaryInputHandle( reader ) };
|
||||||
|
|
||||||
} else if( mode.equals( "wb" ) ) {
|
} else if( mode.equals( "wb" ) ) {
|
||||||
// Open the file for binary writing, then create a wrapper around the writer
|
// Open the file for binary writing, then create a wrapper around the writer
|
||||||
IMountedFileBinary writer = m_fileSystem.openForBinaryWrite( path, false );
|
OutputStream writer = m_fileSystem.openForWrite( path, false );
|
||||||
return wrapOutputStream( writer );
|
return new Object[] { new BinaryOutputHandle( writer ) };
|
||||||
|
|
||||||
} else if( mode.equals( "ab" ) ) {
|
} else if( mode.equals( "ab" ) ) {
|
||||||
// Open the file for binary appending, then create a wrapper around the reader
|
// Open the file for binary appending, then create a wrapper around the reader
|
||||||
IMountedFileBinary writer = m_fileSystem.openForBinaryWrite( path, true );
|
OutputStream writer = m_fileSystem.openForWrite( path, true );
|
||||||
return wrapOutputStream( writer );
|
return new Object[] { new BinaryOutputHandle( writer ) };
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
throw new LuaException( "Unsupported mode" );
|
throw new LuaException( "Unsupported mode" );
|
||||||
@ -368,288 +370,4 @@ public class FSAPI implements ILuaAPI
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Object[] wrapBufferedReader( final IMountedFileNormal reader )
|
|
||||||
{
|
|
||||||
return new Object[] { new ILuaObject() {
|
|
||||||
private boolean open = true;
|
|
||||||
|
|
||||||
@Nonnull
|
|
||||||
@Override
|
|
||||||
public String[] getMethodNames()
|
|
||||||
{
|
|
||||||
return new String[] {
|
|
||||||
"readLine",
|
|
||||||
"readAll",
|
|
||||||
"close"
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object[] callMethod( @Nonnull ILuaContext context, int method, @Nonnull Object[] args ) throws LuaException
|
|
||||||
{
|
|
||||||
switch( method )
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
{
|
|
||||||
// readLine
|
|
||||||
if( !open ) throw new LuaException( "attempt to use a closed file" );
|
|
||||||
try {
|
|
||||||
String line = reader.readLine();
|
|
||||||
if( line != null ) {
|
|
||||||
return new Object[] { line };
|
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
} catch( IOException e ) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case 1:
|
|
||||||
{
|
|
||||||
// readAll
|
|
||||||
if( !open ) throw new LuaException( "attempt to use a closed file" );
|
|
||||||
try {
|
|
||||||
StringBuilder result = new StringBuilder( "" );
|
|
||||||
String line = reader.readLine();
|
|
||||||
while( line != null ) {
|
|
||||||
result.append( line );
|
|
||||||
line = reader.readLine();
|
|
||||||
if( line != null ) {
|
|
||||||
result.append( "\n" );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return new Object[] { result.toString() };
|
|
||||||
} catch( IOException e ) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case 2:
|
|
||||||
{
|
|
||||||
// close
|
|
||||||
try {
|
|
||||||
reader.close();
|
|
||||||
open = false;
|
|
||||||
return null;
|
|
||||||
} catch( IOException e ) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} };
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Object[] wrapBufferedWriter( final IMountedFileNormal writer )
|
|
||||||
{
|
|
||||||
return new Object[] { new ILuaObject() {
|
|
||||||
private boolean open = true;
|
|
||||||
|
|
||||||
@Nonnull
|
|
||||||
@Override
|
|
||||||
public String[] getMethodNames()
|
|
||||||
{
|
|
||||||
return new String[] {
|
|
||||||
"write",
|
|
||||||
"writeLine",
|
|
||||||
"close",
|
|
||||||
"flush"
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object[] callMethod( @Nonnull ILuaContext context, int method, @Nonnull Object[] args ) throws LuaException
|
|
||||||
{
|
|
||||||
switch( method )
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
{
|
|
||||||
// write
|
|
||||||
if( !open ) throw new LuaException( "attempt to use a closed file" );
|
|
||||||
String text;
|
|
||||||
if( args.length > 0 && args[0] != null ) {
|
|
||||||
text = args[0].toString();
|
|
||||||
} else {
|
|
||||||
text = "";
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
writer.write( text, 0, text.length(), false );
|
|
||||||
return null;
|
|
||||||
} catch( IOException e ) {
|
|
||||||
throw new LuaException( e.getMessage() );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case 1:
|
|
||||||
{
|
|
||||||
// writeLine
|
|
||||||
if( !open ) throw new LuaException( "attempt to use a closed file" );
|
|
||||||
|
|
||||||
String text;
|
|
||||||
if( args.length > 0 && args[0] != null ) {
|
|
||||||
text = args[0].toString();
|
|
||||||
} else {
|
|
||||||
text = "";
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
writer.write( text, 0, text.length(), true );
|
|
||||||
return null;
|
|
||||||
} catch( IOException e ) {
|
|
||||||
throw new LuaException( e.getMessage() );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case 2:
|
|
||||||
{
|
|
||||||
// close
|
|
||||||
try {
|
|
||||||
writer.close();
|
|
||||||
open = false;
|
|
||||||
return null;
|
|
||||||
} catch( IOException e ) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case 3:
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
if( !open ) throw new LuaException( "attempt to use a closed file" );
|
|
||||||
writer.flush();
|
|
||||||
return null;
|
|
||||||
} catch ( IOException e ) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
assert( false );
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} };
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Object[] wrapInputStream( final IMountedFileBinary reader )
|
|
||||||
{
|
|
||||||
|
|
||||||
return new Object[] { new ILuaObject() {
|
|
||||||
private boolean open = true;
|
|
||||||
|
|
||||||
@Nonnull
|
|
||||||
@Override
|
|
||||||
public String[] getMethodNames() {
|
|
||||||
return new String[] {
|
|
||||||
"read",
|
|
||||||
"close"
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object[] callMethod( @Nonnull ILuaContext context, int method, @Nonnull Object[] args) throws LuaException {
|
|
||||||
switch( method )
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
{
|
|
||||||
// read
|
|
||||||
if( !open ) throw new LuaException( "attempt to use a closed file" );
|
|
||||||
try {
|
|
||||||
int b = reader.read();
|
|
||||||
if( b != -1 ) {
|
|
||||||
return new Object[] { b };
|
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
} catch( IOException e ) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case 1:
|
|
||||||
{
|
|
||||||
//close
|
|
||||||
try {
|
|
||||||
reader.close();
|
|
||||||
open = false;
|
|
||||||
return null;
|
|
||||||
} catch( IOException e ) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
assert( false );
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}};
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Object[] wrapOutputStream( final IMountedFileBinary writer )
|
|
||||||
{
|
|
||||||
|
|
||||||
return new Object[] { new ILuaObject() {
|
|
||||||
private boolean open = true;
|
|
||||||
|
|
||||||
@Nonnull
|
|
||||||
@Override
|
|
||||||
public String[] getMethodNames() {
|
|
||||||
return new String[] {
|
|
||||||
"write",
|
|
||||||
"close",
|
|
||||||
"flush"
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object[] callMethod( @Nonnull ILuaContext context, int method, @Nonnull Object[] args) throws LuaException {
|
|
||||||
switch( method )
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
{
|
|
||||||
// write
|
|
||||||
if( !open ) throw new LuaException( "attempt to use a closed file" );
|
|
||||||
try {
|
|
||||||
if( args.length > 0 && args[0] instanceof Number )
|
|
||||||
{
|
|
||||||
int number = ((Number)args[0]).intValue();
|
|
||||||
writer.write( number );
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
} catch( IOException e ) {
|
|
||||||
throw new LuaException(e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case 1:
|
|
||||||
{
|
|
||||||
//close
|
|
||||||
try {
|
|
||||||
writer.close();
|
|
||||||
open = false;
|
|
||||||
return null;
|
|
||||||
} catch( IOException e ) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case 2:
|
|
||||||
{
|
|
||||||
if( !open ) throw new LuaException( "attempt to use a closed file" );
|
|
||||||
try {
|
|
||||||
writer.flush();
|
|
||||||
return null;
|
|
||||||
} catch ( IOException e ) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
assert( false );
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -9,10 +9,11 @@ package dan200.computercraft.core.apis;
|
|||||||
import dan200.computercraft.api.lua.ILuaContext;
|
import dan200.computercraft.api.lua.ILuaContext;
|
||||||
import dan200.computercraft.api.lua.ILuaObject;
|
import dan200.computercraft.api.lua.ILuaObject;
|
||||||
import dan200.computercraft.api.lua.LuaException;
|
import dan200.computercraft.api.lua.LuaException;
|
||||||
|
import dan200.computercraft.core.apis.handles.BinaryInputHandle;
|
||||||
|
import dan200.computercraft.core.apis.handles.EncodedInputHandle;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
import java.io.BufferedReader;
|
import java.io.InputStream;
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
public class HTTPAPI implements ILuaAPI
|
public class HTTPAPI implements ILuaAPI
|
||||||
@ -52,15 +53,21 @@ public class HTTPAPI implements ILuaAPI
|
|||||||
final String url = h.getURL();
|
final String url = h.getURL();
|
||||||
if( h.wasSuccessful() ) {
|
if( h.wasSuccessful() ) {
|
||||||
// Queue the "http_success" event
|
// Queue the "http_success" event
|
||||||
final BufferedReader contents = h.getContents();
|
InputStream contents = h.getContents();
|
||||||
final Object result = wrapBufferedReader( contents, h.getResponseCode(), h.getResponseHeaders() );
|
Object result = wrapStream(
|
||||||
|
h.isBinary() ? new BinaryInputHandle( contents ) : new EncodedInputHandle( contents, h.getEncoding() ),
|
||||||
|
h.getResponseCode(), h.getResponseHeaders()
|
||||||
|
);
|
||||||
m_apiEnvironment.queueEvent( "http_success", new Object[] { url, result } );
|
m_apiEnvironment.queueEvent( "http_success", new Object[] { url, result } );
|
||||||
} else {
|
} else {
|
||||||
// Queue the "http_failure" event
|
// Queue the "http_failure" event
|
||||||
BufferedReader contents = h.getContents();
|
InputStream contents = h.getContents();
|
||||||
Object result = null;
|
Object result = null;
|
||||||
if( contents != null ) {
|
if( contents != null ) {
|
||||||
result = wrapBufferedReader( contents, h.getResponseCode(), h.getResponseHeaders() );
|
result = wrapStream(
|
||||||
|
h.isBinary() ? new BinaryInputHandle( contents ) : new EncodedInputHandle( contents, h.getEncoding() ),
|
||||||
|
h.getResponseCode(), h.getResponseHeaders()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
m_apiEnvironment.queueEvent( "http_failure", new Object[]{ url, "Could not connect", result } );
|
m_apiEnvironment.queueEvent( "http_failure", new Object[]{ url, "Could not connect", result } );
|
||||||
}
|
}
|
||||||
@ -70,79 +77,39 @@ public class HTTPAPI implements ILuaAPI
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ILuaObject wrapBufferedReader( final BufferedReader reader, final int responseCode, final Map<String, String> responseHeaders )
|
private static ILuaObject wrapStream( final ILuaObject reader, final int responseCode, final Map<String, String> responseHeaders )
|
||||||
{
|
{
|
||||||
return new ILuaObject() {
|
String[] oldMethods = reader.getMethodNames();
|
||||||
private boolean open = true;
|
final int methodOffset = oldMethods.length;
|
||||||
|
|
||||||
|
final String[] newMethods = Arrays.copyOf( oldMethods, oldMethods.length + 2 );
|
||||||
|
newMethods[ methodOffset + 0 ] = "getResponseCode";
|
||||||
|
newMethods[ methodOffset + 1 ] = "getResponseHeaders";
|
||||||
|
|
||||||
|
return new ILuaObject()
|
||||||
|
{
|
||||||
@Nonnull
|
@Nonnull
|
||||||
@Override
|
@Override
|
||||||
public String[] getMethodNames()
|
public String[] getMethodNames()
|
||||||
{
|
{
|
||||||
return new String[] {
|
return newMethods;
|
||||||
"readLine",
|
|
||||||
"readAll",
|
|
||||||
"close",
|
|
||||||
"getResponseCode",
|
|
||||||
"getResponseHeaders",
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object[] callMethod( @Nonnull ILuaContext context, int method, @Nonnull Object[] args ) throws LuaException
|
public Object[] callMethod( @Nonnull ILuaContext context, int method, @Nonnull Object[] args ) throws LuaException, InterruptedException
|
||||||
{
|
{
|
||||||
switch( method )
|
if( method < methodOffset )
|
||||||
|
{
|
||||||
|
return reader.callMethod( context, method, args );
|
||||||
|
}
|
||||||
|
switch( method - methodOffset )
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
{
|
|
||||||
// readLine
|
|
||||||
if( !open ) throw new LuaException( "attempt to use a closed response" );
|
|
||||||
try {
|
|
||||||
String line = reader.readLine();
|
|
||||||
if( line != null ) {
|
|
||||||
return new Object[] { line };
|
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
} catch( IOException e ) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case 1:
|
|
||||||
{
|
|
||||||
// readAll
|
|
||||||
if( !open ) throw new LuaException( "attempt to use a closed response" );
|
|
||||||
try {
|
|
||||||
StringBuilder result = new StringBuilder( "" );
|
|
||||||
String line = reader.readLine();
|
|
||||||
while( line != null ) {
|
|
||||||
result.append( line );
|
|
||||||
line = reader.readLine();
|
|
||||||
if( line != null ) {
|
|
||||||
result.append( "\n" );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return new Object[] { result.toString() };
|
|
||||||
} catch( IOException e ) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case 2:
|
|
||||||
{
|
|
||||||
// close
|
|
||||||
try {
|
|
||||||
reader.close();
|
|
||||||
open = false;
|
|
||||||
return null;
|
|
||||||
} catch( IOException e ) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case 3:
|
|
||||||
{
|
{
|
||||||
// getResponseCode
|
// getResponseCode
|
||||||
return new Object[] { responseCode };
|
return new Object[] { responseCode };
|
||||||
}
|
}
|
||||||
case 4:
|
case 1:
|
||||||
{
|
{
|
||||||
// getResponseHeaders
|
// getResponseHeaders
|
||||||
return new Object[] { responseHeaders };
|
return new Object[] { responseHeaders };
|
||||||
@ -217,10 +184,17 @@ public class HTTPAPI implements ILuaAPI
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get binary
|
||||||
|
boolean binary = false;
|
||||||
|
if( args.length >= 4 )
|
||||||
|
{
|
||||||
|
binary = args[ 3 ] != null && !args[ 3 ].equals( Boolean.FALSE );
|
||||||
|
}
|
||||||
|
|
||||||
// Make the request
|
// Make the request
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
HTTPRequest request = new HTTPRequest( urlString, postString, headers );
|
HTTPRequest request = new HTTPRequest( urlString, postString, headers, binary );
|
||||||
synchronized( m_httpRequests )
|
synchronized( m_httpRequests )
|
||||||
{
|
{
|
||||||
m_httpRequests.add( request );
|
m_httpRequests.add( request );
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
package dan200.computercraft.core.apis;
|
package dan200.computercraft.core.apis;
|
||||||
|
|
||||||
import com.google.common.base.Joiner;
|
import com.google.common.base.Joiner;
|
||||||
|
import com.google.common.io.ByteStreams;
|
||||||
import dan200.computercraft.ComputerCraft;
|
import dan200.computercraft.ComputerCraft;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
@ -60,11 +61,12 @@ public class HTTPRequest
|
|||||||
return url;
|
return url;
|
||||||
}
|
}
|
||||||
|
|
||||||
public HTTPRequest( String url, final String postText, final Map<String, String> headers ) throws HTTPRequestException
|
public HTTPRequest( String url, final String postText, final Map<String, String> headers, boolean binary ) throws HTTPRequestException
|
||||||
{
|
{
|
||||||
// Parse the URL
|
// Parse the URL
|
||||||
m_urlString = url;
|
m_urlString = url;
|
||||||
m_url = checkURL( m_urlString );
|
m_url = checkURL( m_urlString );
|
||||||
|
m_binary = binary;
|
||||||
|
|
||||||
// Start the thread
|
// Start the thread
|
||||||
m_cancelled = false;
|
m_cancelled = false;
|
||||||
@ -136,53 +138,9 @@ public class HTTPRequest
|
|||||||
is = connection.getErrorStream();
|
is = connection.getErrorStream();
|
||||||
responseSuccess = false;
|
responseSuccess = false;
|
||||||
}
|
}
|
||||||
InputStreamReader isr;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
String contentEncoding = connection.getContentEncoding();
|
|
||||||
if( contentEncoding != null )
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
isr = new InputStreamReader( is, contentEncoding );
|
|
||||||
}
|
|
||||||
catch( UnsupportedEncodingException e )
|
|
||||||
{
|
|
||||||
isr = new InputStreamReader( is, "UTF-8" );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
isr = new InputStreamReader( is, "UTF-8" );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch( UnsupportedEncodingException e )
|
|
||||||
{
|
|
||||||
isr = new InputStreamReader( is );
|
|
||||||
}
|
|
||||||
|
|
||||||
// Download the contents
|
byte[] result = ByteStreams.toByteArray( is );
|
||||||
BufferedReader reader = new BufferedReader( isr );
|
is.close();
|
||||||
StringBuilder result = new StringBuilder();
|
|
||||||
while( true )
|
|
||||||
{
|
|
||||||
synchronized( m_lock )
|
|
||||||
{
|
|
||||||
if( m_cancelled )
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
String line = reader.readLine();
|
|
||||||
if( line == null )
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
result.append( line );
|
|
||||||
result.append( '\n' );
|
|
||||||
}
|
|
||||||
reader.close();
|
|
||||||
|
|
||||||
synchronized( m_lock )
|
synchronized( m_lock )
|
||||||
{
|
{
|
||||||
@ -198,8 +156,9 @@ public class HTTPRequest
|
|||||||
// We completed
|
// We completed
|
||||||
m_complete = true;
|
m_complete = true;
|
||||||
m_success = responseSuccess;
|
m_success = responseSuccess;
|
||||||
m_result = result.toString();
|
m_result = result;
|
||||||
m_responseCode = connection.getResponseCode();
|
m_responseCode = connection.getResponseCode();
|
||||||
|
m_encoding = connection.getContentEncoding();
|
||||||
|
|
||||||
Joiner joiner = Joiner.on( ',' );
|
Joiner joiner = Joiner.on( ',' );
|
||||||
Map<String, String> headers = m_responseHeaders = new HashMap<String, String>();
|
Map<String, String> headers = m_responseHeaders = new HashMap<String, String>();
|
||||||
@ -265,19 +224,28 @@ public class HTTPRequest
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public BufferedReader getContents()
|
public boolean isBinary()
|
||||||
{
|
{
|
||||||
String result;
|
return m_binary;
|
||||||
|
}
|
||||||
|
|
||||||
|
public InputStream getContents()
|
||||||
|
{
|
||||||
|
byte[] result;
|
||||||
synchronized(m_lock) {
|
synchronized(m_lock) {
|
||||||
result = m_result;
|
result = m_result;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( result != null ) {
|
if( result != null ) {
|
||||||
return new BufferedReader( new StringReader( result ) );
|
return new ByteArrayInputStream( result );
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getEncoding() {
|
||||||
|
return m_encoding;
|
||||||
|
}
|
||||||
|
|
||||||
private final Object m_lock = new Object();
|
private final Object m_lock = new Object();
|
||||||
private final URL m_url;
|
private final URL m_url;
|
||||||
private final String m_urlString;
|
private final String m_urlString;
|
||||||
@ -285,7 +253,9 @@ public class HTTPRequest
|
|||||||
private boolean m_complete;
|
private boolean m_complete;
|
||||||
private boolean m_cancelled;
|
private boolean m_cancelled;
|
||||||
private boolean m_success;
|
private boolean m_success;
|
||||||
private String m_result;
|
private String m_encoding;
|
||||||
|
private byte[] m_result;
|
||||||
|
private boolean m_binary;
|
||||||
private int m_responseCode;
|
private int m_responseCode;
|
||||||
private Map<String, String> m_responseHeaders;
|
private Map<String, String> m_responseHeaders;
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,93 @@
|
|||||||
|
package dan200.computercraft.core.apis.handles;
|
||||||
|
|
||||||
|
import com.google.common.io.ByteStreams;
|
||||||
|
import dan200.computercraft.api.lua.ILuaContext;
|
||||||
|
import dan200.computercraft.api.lua.LuaException;
|
||||||
|
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
public class BinaryInputHandle extends HandleGeneric
|
||||||
|
{
|
||||||
|
private final InputStream m_stream;
|
||||||
|
|
||||||
|
public BinaryInputHandle( InputStream reader )
|
||||||
|
{
|
||||||
|
super( reader );
|
||||||
|
this.m_stream = reader;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
|
@Override
|
||||||
|
public String[] getMethodNames()
|
||||||
|
{
|
||||||
|
return new String[] {
|
||||||
|
"read",
|
||||||
|
"readAll",
|
||||||
|
"close",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object[] callMethod( @Nonnull ILuaContext context, int method, @Nonnull Object[] args ) throws LuaException
|
||||||
|
{
|
||||||
|
switch( method )
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
// read
|
||||||
|
checkOpen();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if( args.length > 0 && args[ 0 ] != null )
|
||||||
|
{
|
||||||
|
if( !(args[ 0 ] instanceof Number) )
|
||||||
|
{
|
||||||
|
throw new LuaException( "Expected number" );
|
||||||
|
}
|
||||||
|
|
||||||
|
int count = ((Number) args[ 0 ]).intValue();
|
||||||
|
|
||||||
|
if( count <= 0 || count >= 1024 * 16 )
|
||||||
|
{
|
||||||
|
throw new LuaException( "Count out of range" );
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] bytes = new byte[ count ];
|
||||||
|
count = m_stream.read( bytes );
|
||||||
|
if( count < 0 ) return null;
|
||||||
|
if( count < bytes.length ) bytes = Arrays.copyOf( bytes, count );
|
||||||
|
return new Object[] { bytes };
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int b = m_stream.read();
|
||||||
|
return b == -1 ? null : new Object[] { b };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch( IOException e )
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
case 1:
|
||||||
|
// readAll
|
||||||
|
checkOpen();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
byte[] out = ByteStreams.toByteArray( m_stream );
|
||||||
|
return out == null ? null : new Object[] { out };
|
||||||
|
}
|
||||||
|
catch( IOException e )
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
case 2:
|
||||||
|
//close
|
||||||
|
close();
|
||||||
|
return null;
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,82 @@
|
|||||||
|
package dan200.computercraft.core.apis.handles;
|
||||||
|
|
||||||
|
import dan200.computercraft.api.lua.ILuaContext;
|
||||||
|
import dan200.computercraft.api.lua.LuaException;
|
||||||
|
import dan200.computercraft.shared.util.StringUtil;
|
||||||
|
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
|
||||||
|
public class BinaryOutputHandle extends HandleGeneric
|
||||||
|
{
|
||||||
|
private final OutputStream m_writer;
|
||||||
|
|
||||||
|
public BinaryOutputHandle( OutputStream writer )
|
||||||
|
{
|
||||||
|
super( writer );
|
||||||
|
this.m_writer = writer;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
|
@Override
|
||||||
|
public String[] getMethodNames()
|
||||||
|
{
|
||||||
|
return new String[] {
|
||||||
|
"write",
|
||||||
|
"flush",
|
||||||
|
"close",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object[] callMethod( @Nonnull ILuaContext context, int method, @Nonnull Object[] args ) throws LuaException
|
||||||
|
{
|
||||||
|
switch( method )
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
// write
|
||||||
|
checkOpen();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if( args.length > 0 && args[ 0 ] instanceof Number )
|
||||||
|
{
|
||||||
|
int number = ((Number) args[ 0 ]).intValue();
|
||||||
|
m_writer.write( number );
|
||||||
|
}
|
||||||
|
else if( args.length > 0 && args[ 0 ] instanceof String )
|
||||||
|
{
|
||||||
|
String value = (String) args[ 0 ];
|
||||||
|
m_writer.write( StringUtil.encodeString( value ) );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new LuaException( "Expected number" );
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
catch( IOException e )
|
||||||
|
{
|
||||||
|
throw new LuaException( e.getMessage() );
|
||||||
|
}
|
||||||
|
case 1:
|
||||||
|
// flush
|
||||||
|
checkOpen();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
m_writer.flush();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
catch( IOException e )
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
case 2:
|
||||||
|
//close
|
||||||
|
close();
|
||||||
|
return null;
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,105 @@
|
|||||||
|
package dan200.computercraft.core.apis.handles;
|
||||||
|
|
||||||
|
import dan200.computercraft.api.lua.ILuaContext;
|
||||||
|
import dan200.computercraft.api.lua.LuaException;
|
||||||
|
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
|
import java.io.*;
|
||||||
|
|
||||||
|
public class EncodedInputHandle extends HandleGeneric
|
||||||
|
{
|
||||||
|
private final BufferedReader m_reader;
|
||||||
|
|
||||||
|
public EncodedInputHandle( BufferedReader reader )
|
||||||
|
{
|
||||||
|
super( reader );
|
||||||
|
this.m_reader = reader;
|
||||||
|
}
|
||||||
|
|
||||||
|
public EncodedInputHandle( InputStream stream )
|
||||||
|
{
|
||||||
|
this( stream, "UTF-8" );
|
||||||
|
}
|
||||||
|
|
||||||
|
public EncodedInputHandle( InputStream stream, String encoding )
|
||||||
|
{
|
||||||
|
super( stream );
|
||||||
|
if( encoding == null ) encoding = "UTF-8";
|
||||||
|
InputStreamReader streamReader;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
streamReader = new InputStreamReader( stream, encoding );
|
||||||
|
}
|
||||||
|
catch( UnsupportedEncodingException e )
|
||||||
|
{
|
||||||
|
streamReader = new InputStreamReader( stream );
|
||||||
|
}
|
||||||
|
this.m_reader = new BufferedReader( streamReader );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
|
@Override
|
||||||
|
public String[] getMethodNames()
|
||||||
|
{
|
||||||
|
return new String[] {
|
||||||
|
"readLine",
|
||||||
|
"readAll",
|
||||||
|
"close",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object[] callMethod( @Nonnull ILuaContext context, int method, @Nonnull Object[] args ) throws LuaException
|
||||||
|
{
|
||||||
|
switch( method )
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
// readLine
|
||||||
|
checkOpen();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
String line = m_reader.readLine();
|
||||||
|
if( line != null )
|
||||||
|
{
|
||||||
|
return new Object[] { line };
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch( IOException e )
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
case 1:
|
||||||
|
// readAll
|
||||||
|
checkOpen();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
StringBuilder result = new StringBuilder( "" );
|
||||||
|
String line = m_reader.readLine();
|
||||||
|
while( line != null )
|
||||||
|
{
|
||||||
|
result.append( line );
|
||||||
|
line = m_reader.readLine();
|
||||||
|
if( line != null )
|
||||||
|
{
|
||||||
|
result.append( "\n" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new Object[] { result.toString() };
|
||||||
|
}
|
||||||
|
catch( IOException e )
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
case 2:
|
||||||
|
// close
|
||||||
|
close();
|
||||||
|
return null;
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,124 @@
|
|||||||
|
package dan200.computercraft.core.apis.handles;
|
||||||
|
|
||||||
|
import dan200.computercraft.api.lua.ILuaContext;
|
||||||
|
import dan200.computercraft.api.lua.LuaException;
|
||||||
|
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
|
import java.io.*;
|
||||||
|
|
||||||
|
public class EncodedOutputHandle extends HandleGeneric
|
||||||
|
{
|
||||||
|
private final BufferedWriter m_writer;
|
||||||
|
|
||||||
|
public EncodedOutputHandle( BufferedWriter writer )
|
||||||
|
{
|
||||||
|
super( writer );
|
||||||
|
this.m_writer = writer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public EncodedOutputHandle( OutputStream stream )
|
||||||
|
{
|
||||||
|
this( stream, "UTF-8" );
|
||||||
|
}
|
||||||
|
|
||||||
|
public EncodedOutputHandle( OutputStream stream, String encoding )
|
||||||
|
{
|
||||||
|
super( stream );
|
||||||
|
if( encoding == null ) encoding = "UTF-8";
|
||||||
|
OutputStreamWriter streamWriter;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
streamWriter = new OutputStreamWriter( stream, encoding );
|
||||||
|
}
|
||||||
|
catch( UnsupportedEncodingException e )
|
||||||
|
{
|
||||||
|
streamWriter = new OutputStreamWriter( stream );
|
||||||
|
}
|
||||||
|
this.m_writer = new BufferedWriter( streamWriter );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nonnull
|
||||||
|
@Override
|
||||||
|
public String[] getMethodNames()
|
||||||
|
{
|
||||||
|
return new String[] {
|
||||||
|
"write",
|
||||||
|
"writeLine",
|
||||||
|
"flush",
|
||||||
|
"close",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object[] callMethod( @Nonnull ILuaContext context, int method, @Nonnull Object[] args ) throws LuaException
|
||||||
|
{
|
||||||
|
switch( method )
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
{
|
||||||
|
// write
|
||||||
|
checkOpen();
|
||||||
|
String text;
|
||||||
|
if( args.length > 0 && args[ 0 ] != null )
|
||||||
|
{
|
||||||
|
text = args[ 0 ].toString();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
text = "";
|
||||||
|
}
|
||||||
|
try
|
||||||
|
{
|
||||||
|
m_writer.write( text, 0, text.length() );
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
catch( IOException e )
|
||||||
|
{
|
||||||
|
throw new LuaException( e.getMessage() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case 1:
|
||||||
|
{
|
||||||
|
// writeLine
|
||||||
|
checkOpen();
|
||||||
|
String text;
|
||||||
|
if( args.length > 0 && args[ 0 ] != null )
|
||||||
|
{
|
||||||
|
text = args[ 0 ].toString();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
text = "";
|
||||||
|
}
|
||||||
|
try
|
||||||
|
{
|
||||||
|
m_writer.write( text, 0, text.length() );
|
||||||
|
m_writer.newLine();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
catch( IOException e )
|
||||||
|
{
|
||||||
|
throw new LuaException( e.getMessage() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case 2:
|
||||||
|
// flush
|
||||||
|
checkOpen();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
m_writer.flush();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
catch( IOException e )
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
case 3:
|
||||||
|
// close
|
||||||
|
close();
|
||||||
|
return null;
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,35 @@
|
|||||||
|
package dan200.computercraft.core.apis.handles;
|
||||||
|
|
||||||
|
import dan200.computercraft.api.lua.ILuaObject;
|
||||||
|
import dan200.computercraft.api.lua.LuaException;
|
||||||
|
|
||||||
|
import java.io.Closeable;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
public abstract class HandleGeneric implements ILuaObject
|
||||||
|
{
|
||||||
|
protected final Closeable m_closable;
|
||||||
|
protected boolean m_open = true;
|
||||||
|
|
||||||
|
public HandleGeneric( Closeable m_closable )
|
||||||
|
{
|
||||||
|
this.m_closable = m_closable;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void checkOpen() throws LuaException
|
||||||
|
{
|
||||||
|
if( !m_open ) throw new LuaException( "attempt to use a closed file" );
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void close()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
m_closable.close();
|
||||||
|
m_open = false;
|
||||||
|
}
|
||||||
|
catch( IOException ignored )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -9,6 +9,7 @@ package dan200.computercraft.core.filesystem;
|
|||||||
import dan200.computercraft.ComputerCraft;
|
import dan200.computercraft.ComputerCraft;
|
||||||
import dan200.computercraft.api.filesystem.IMount;
|
import dan200.computercraft.api.filesystem.IMount;
|
||||||
import dan200.computercraft.api.filesystem.IWritableMount;
|
import dan200.computercraft.api.filesystem.IWritableMount;
|
||||||
|
import net.minecraftforge.fml.common.FMLLog;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
@ -291,7 +292,7 @@ public class FileSystem
|
|||||||
}
|
}
|
||||||
|
|
||||||
private final Map<String, MountWrapper> m_mounts = new HashMap<String, MountWrapper>();
|
private final Map<String, MountWrapper> m_mounts = new HashMap<String, MountWrapper>();
|
||||||
private final Set<IMountedFile> m_openFiles = Collections.newSetFromMap( new WeakHashMap<IMountedFile, Boolean>() );
|
private final Set<Closeable> m_openFiles = Collections.newSetFromMap( new WeakHashMap<Closeable, Boolean>() );
|
||||||
|
|
||||||
public FileSystem( String rootLabel, IMount rootMount ) throws FileSystemException
|
public FileSystem( String rootLabel, IMount rootMount ) throws FileSystemException
|
||||||
{
|
{
|
||||||
@ -308,7 +309,7 @@ public class FileSystem
|
|||||||
// Close all dangling open files
|
// Close all dangling open files
|
||||||
synchronized( m_openFiles )
|
synchronized( m_openFiles )
|
||||||
{
|
{
|
||||||
for(IMountedFile file : m_openFiles)
|
for( Closeable file : m_openFiles )
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
file.close();
|
file.close();
|
||||||
@ -647,7 +648,7 @@ public class FileSystem
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private synchronized <T extends IMountedFile> T openFile(T file, Closeable handle) throws FileSystemException
|
private synchronized <T> T openFile( T file, Closeable handle ) throws FileSystemException
|
||||||
{
|
{
|
||||||
synchronized( m_openFiles )
|
synchronized( m_openFiles )
|
||||||
{
|
{
|
||||||
@ -665,195 +666,40 @@ public class FileSystem
|
|||||||
throw new FileSystemException("Too many files already open");
|
throw new FileSystemException("Too many files already open");
|
||||||
}
|
}
|
||||||
|
|
||||||
m_openFiles.add( file );
|
m_openFiles.add( handle );
|
||||||
return file;
|
return file;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private synchronized void closeFile( IMountedFile file, Closeable handle ) throws IOException
|
private synchronized void closeFile( Closeable handle ) throws IOException
|
||||||
{
|
{
|
||||||
synchronized( m_openFiles )
|
synchronized( m_openFiles )
|
||||||
{
|
{
|
||||||
m_openFiles.remove( file );
|
m_openFiles.remove( handle );
|
||||||
if( handle != null )
|
handle.close();
|
||||||
{
|
|
||||||
handle.close();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized IMountedFileNormal openForRead( String path ) throws FileSystemException
|
public synchronized InputStream openForRead( String path ) throws FileSystemException
|
||||||
{
|
{
|
||||||
path = sanitizePath ( path );
|
path = sanitizePath ( path );
|
||||||
MountWrapper mount = getMount( path );
|
MountWrapper mount = getMount( path );
|
||||||
InputStream stream = mount.openForRead( path );
|
InputStream stream = mount.openForRead( path );
|
||||||
if( stream != null )
|
if( stream != null )
|
||||||
{
|
{
|
||||||
InputStreamReader isr;
|
return openFile( new ClosingInputStream( stream ), stream );
|
||||||
try
|
|
||||||
{
|
|
||||||
isr = new InputStreamReader( stream, "UTF-8" );
|
|
||||||
}
|
|
||||||
catch( UnsupportedEncodingException e )
|
|
||||||
{
|
|
||||||
isr = new InputStreamReader( stream );
|
|
||||||
}
|
|
||||||
final BufferedReader reader = new BufferedReader( isr );
|
|
||||||
IMountedFileNormal file = new IMountedFileNormal()
|
|
||||||
{
|
|
||||||
@Override
|
|
||||||
public String readLine() throws IOException
|
|
||||||
{
|
|
||||||
return reader.readLine();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void write(String s, int off, int len, boolean newLine) throws IOException
|
|
||||||
{
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void close() throws IOException
|
|
||||||
{
|
|
||||||
closeFile( this, reader );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void flush() throws IOException
|
|
||||||
{
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
return openFile( file, reader );
|
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized IMountedFileNormal openForWrite( String path, boolean append ) throws FileSystemException
|
public synchronized OutputStream openForWrite( String path, boolean append ) throws FileSystemException
|
||||||
{
|
{
|
||||||
path = sanitizePath ( path );
|
path = sanitizePath ( path );
|
||||||
MountWrapper mount = getMount( path );
|
MountWrapper mount = getMount( path );
|
||||||
OutputStream stream = append ? mount.openForAppend( path ) : mount.openForWrite( path );
|
OutputStream stream = append ? mount.openForAppend( path ) : mount.openForWrite( path );
|
||||||
if( stream != null )
|
if( stream != null )
|
||||||
{
|
{
|
||||||
OutputStreamWriter osw;
|
return openFile( new ClosingOutputStream( stream ), stream );
|
||||||
try
|
|
||||||
{
|
|
||||||
osw = new OutputStreamWriter( stream, "UTF-8" );
|
|
||||||
}
|
|
||||||
catch( UnsupportedEncodingException e )
|
|
||||||
{
|
|
||||||
osw = new OutputStreamWriter( stream );
|
|
||||||
}
|
|
||||||
final BufferedWriter writer = new BufferedWriter( osw );
|
|
||||||
IMountedFileNormal file = new IMountedFileNormal()
|
|
||||||
{
|
|
||||||
@Override
|
|
||||||
public String readLine() throws IOException
|
|
||||||
{
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void write( String s, int off, int len, boolean newLine ) throws IOException
|
|
||||||
{
|
|
||||||
writer.write( s, off, len );
|
|
||||||
if( newLine )
|
|
||||||
{
|
|
||||||
writer.newLine();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void close() throws IOException
|
|
||||||
{
|
|
||||||
closeFile( this, writer );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void flush() throws IOException
|
|
||||||
{
|
|
||||||
writer.flush();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
return openFile( file, writer );
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public synchronized IMountedFileBinary openForBinaryRead( String path ) throws FileSystemException
|
|
||||||
{
|
|
||||||
path = sanitizePath ( path );
|
|
||||||
MountWrapper mount = getMount( path );
|
|
||||||
final InputStream stream = mount.openForRead( path );
|
|
||||||
if( stream != null )
|
|
||||||
{
|
|
||||||
IMountedFileBinary file = new IMountedFileBinary()
|
|
||||||
{
|
|
||||||
@Override
|
|
||||||
public int read() throws IOException
|
|
||||||
{
|
|
||||||
return stream.read();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void write(int i) throws IOException
|
|
||||||
{
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void close() throws IOException
|
|
||||||
{
|
|
||||||
closeFile( this, stream );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void flush() throws IOException
|
|
||||||
{
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
return openFile( file, stream );
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public synchronized IMountedFileBinary openForBinaryWrite( String path, boolean append ) throws FileSystemException
|
|
||||||
{
|
|
||||||
path = sanitizePath ( path );
|
|
||||||
MountWrapper mount = getMount( path );
|
|
||||||
final OutputStream stream = append ? mount.openForAppend( path ) : mount.openForWrite( path );
|
|
||||||
if( stream != null )
|
|
||||||
{
|
|
||||||
IMountedFileBinary file = new IMountedFileBinary()
|
|
||||||
{
|
|
||||||
@Override
|
|
||||||
public int read() throws IOException
|
|
||||||
{
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void write(int i) throws IOException
|
|
||||||
{
|
|
||||||
stream.write(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void close() throws IOException
|
|
||||||
{
|
|
||||||
closeFile( this, stream );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void flush() throws IOException
|
|
||||||
{
|
|
||||||
stream.flush();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
return openFile( file, stream );
|
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -1010,4 +856,34 @@ public class FileSystem
|
|||||||
return local;
|
return local;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class ClosingInputStream extends FilterInputStream
|
||||||
|
{
|
||||||
|
protected ClosingInputStream( InputStream in )
|
||||||
|
{
|
||||||
|
super( in );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() throws IOException
|
||||||
|
{
|
||||||
|
super.close();
|
||||||
|
closeFile( in );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class ClosingOutputStream extends FilterOutputStream
|
||||||
|
{
|
||||||
|
protected ClosingOutputStream( OutputStream out )
|
||||||
|
{
|
||||||
|
super( out );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() throws IOException
|
||||||
|
{
|
||||||
|
super.close();
|
||||||
|
closeFile( out );
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,13 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is part of ComputerCraft - http://www.computercraft.info
|
|
||||||
* Copyright Daniel Ratcliffe, 2011-2017. Do not distribute without permission.
|
|
||||||
* Send enquiries to dratcliffe@gmail.com
|
|
||||||
*/
|
|
||||||
|
|
||||||
package dan200.computercraft.core.filesystem;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
public interface IMountedFile {
|
|
||||||
void close() throws IOException;
|
|
||||||
}
|
|
@ -1,16 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is part of ComputerCraft - http://www.computercraft.info
|
|
||||||
* Copyright Daniel Ratcliffe, 2011-2017. Do not distribute without permission.
|
|
||||||
* Send enquiries to dratcliffe@gmail.com
|
|
||||||
*/
|
|
||||||
|
|
||||||
package dan200.computercraft.core.filesystem;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
public interface IMountedFileBinary extends IMountedFile {
|
|
||||||
int read() throws IOException;
|
|
||||||
void write( int i ) throws IOException;
|
|
||||||
void close() throws IOException;
|
|
||||||
void flush() throws IOException;
|
|
||||||
}
|
|
@ -1,16 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is part of ComputerCraft - http://www.computercraft.info
|
|
||||||
* Copyright Daniel Ratcliffe, 2011-2017. Do not distribute without permission.
|
|
||||||
* Send enquiries to dratcliffe@gmail.com
|
|
||||||
*/
|
|
||||||
|
|
||||||
package dan200.computercraft.core.filesystem;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
public interface IMountedFileNormal extends IMountedFile {
|
|
||||||
String readLine() throws IOException;
|
|
||||||
void write( String s, int off, int len, boolean newLine ) throws IOException;
|
|
||||||
void close() throws IOException;
|
|
||||||
void flush() throws IOException;
|
|
||||||
}
|
|
@ -24,6 +24,7 @@ import org.luaj.vm2.lib.jse.JsePlatform;
|
|||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.IdentityHashMap;
|
import java.util.IdentityHashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@ -520,6 +521,11 @@ public class LuaJLuaMachine implements ILuaMachine
|
|||||||
String s = object.toString();
|
String s = object.toString();
|
||||||
return LuaValue.valueOf( s );
|
return LuaValue.valueOf( s );
|
||||||
}
|
}
|
||||||
|
else if( object instanceof byte[] )
|
||||||
|
{
|
||||||
|
byte[] b = (byte[]) object;
|
||||||
|
return LuaValue.valueOf( Arrays.copyOf( b, b.length ) );
|
||||||
|
}
|
||||||
else if( object instanceof Map )
|
else if( object instanceof Map )
|
||||||
{
|
{
|
||||||
// Table:
|
// Table:
|
||||||
|
@ -41,4 +41,17 @@ public class StringUtil
|
|||||||
{
|
{
|
||||||
return net.minecraft.util.text.translation.I18n.translateToLocalFormatted( key, format );
|
return net.minecraft.util.text.translation.I18n.translateToLocalFormatted( key, format );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static byte[] encodeString( String string )
|
||||||
|
{
|
||||||
|
byte[] chars = new byte[ string.length() ];
|
||||||
|
|
||||||
|
for( int i = 0; i < chars.length; ++i )
|
||||||
|
{
|
||||||
|
char c = string.charAt( i );
|
||||||
|
chars[ i ] = c < 256 ? (byte) c : 63;
|
||||||
|
}
|
||||||
|
|
||||||
|
return chars;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -639,8 +639,8 @@ end
|
|||||||
if http then
|
if http then
|
||||||
local nativeHTTPRequest = http.request
|
local nativeHTTPRequest = http.request
|
||||||
|
|
||||||
local function wrapRequest( _url, _post, _headers )
|
local function wrapRequest( _url, _post, _headers, _binary )
|
||||||
local ok, err = nativeHTTPRequest( _url, _post, _headers )
|
local ok, err = nativeHTTPRequest( _url, _post, _headers, _binary )
|
||||||
if ok then
|
if ok then
|
||||||
while true do
|
while true do
|
||||||
local event, param1, param2, param3 = os.pullEvent()
|
local event, param1, param2, param3 = os.pullEvent()
|
||||||
@ -654,16 +654,16 @@ if http then
|
|||||||
return nil, err
|
return nil, err
|
||||||
end
|
end
|
||||||
|
|
||||||
http.get = function( _url, _headers )
|
http.get = function( _url, _headers, _binary)
|
||||||
return wrapRequest( _url, nil, _headers )
|
return wrapRequest( _url, nil, _headers, _binary)
|
||||||
end
|
end
|
||||||
|
|
||||||
http.post = function( _url, _post, _headers )
|
http.post = function( _url, _post, _headers, _binary)
|
||||||
return wrapRequest( _url, _post or "", _headers )
|
return wrapRequest( _url, _post or "", _headers, _binary)
|
||||||
end
|
end
|
||||||
|
|
||||||
http.request = function( _url, _post, _headers )
|
http.request = function( _url, _post, _headers, _binary )
|
||||||
local ok, err = nativeHTTPRequest( _url, _post, _headers )
|
local ok, err = nativeHTTPRequest( _url, _post, _headers, _binary )
|
||||||
if not ok then
|
if not ok then
|
||||||
os.queueEvent( "http_failure", _url, err )
|
os.queueEvent( "http_failure", _url, err )
|
||||||
end
|
end
|
||||||
|
Loading…
Reference in New Issue
Block a user