1. added J2sePlatform for StandardLuaJVM to use J2SE DebugNetSupportImpl
This commit is contained in:
@@ -91,10 +91,10 @@ public class DebugLuaState extends LuaState implements DebugRequestListener {
|
||||
if (debugSupport != null)
|
||||
setDebugSupport(debugSupport);
|
||||
else
|
||||
System.out.println("Warning: DebugNetSupportBase is not implemented.");
|
||||
System.out.println("Warning: DebugNetSupport is missing. Cannot communicate with a debugging client.");
|
||||
} catch (IOException e) {
|
||||
// no debug client can talk to VM, but VM can continue functioning
|
||||
System.out.println("Warning: no debug client support due to error: " + e.getMessage());
|
||||
System.out.println("Warning: cannot communicate with a debugging client due to error: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -66,6 +66,7 @@ public class DebugMessageType extends EnumType {
|
||||
public static final DebugMessageType disconnected = new DebugMessageType("disconnected", 34);
|
||||
public static final DebugMessageType sessionId = new DebugMessageType("sessionId", 35);
|
||||
public static final DebugMessageType debugServiceDown = new DebugMessageType("debugServiceDown", 36);
|
||||
public static final DebugMessageType outputRedirect = new DebugMessageType("outputRedirect", 37);
|
||||
|
||||
protected static DebugMessageType[] ENUMS = new DebugMessageType[] {
|
||||
start,
|
||||
@@ -104,7 +105,8 @@ public class DebugMessageType extends EnumType {
|
||||
clientRequestGlobalReply,
|
||||
disconnected,
|
||||
sessionId,
|
||||
debugServiceDown
|
||||
debugServiceDown,
|
||||
outputRedirect
|
||||
};
|
||||
|
||||
protected DebugMessageType(String name, int ordinal) {
|
||||
|
||||
57
src/debug/org/luaj/debug/RedirectOutputStream.java
Normal file
57
src/debug/org/luaj/debug/RedirectOutputStream.java
Normal file
@@ -0,0 +1,57 @@
|
||||
package org.luaj.debug;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
|
||||
import org.luaj.debug.event.DebugEventListener;
|
||||
import org.luaj.debug.event.DebugEventOutputRedirect;
|
||||
|
||||
public class RedirectOutputStream extends OutputStream {
|
||||
|
||||
protected DebugEventListener listener;
|
||||
protected int count;
|
||||
protected byte[] buffer;
|
||||
|
||||
public RedirectOutputStream(DebugEventListener listener) {
|
||||
this(listener, 1024);
|
||||
}
|
||||
|
||||
public RedirectOutputStream(DebugEventListener listener, int count) {
|
||||
this.listener = listener;
|
||||
this.count = 0;
|
||||
this.buffer = new byte[count];
|
||||
}
|
||||
|
||||
public void close() throws IOException {
|
||||
flushBuffer();
|
||||
}
|
||||
|
||||
public synchronized void flush() throws IOException {
|
||||
flushBuffer();
|
||||
}
|
||||
|
||||
public void write(byte[] b, int off, int len) throws IOException {
|
||||
super.write(b, off, len);
|
||||
flushBuffer();
|
||||
}
|
||||
|
||||
public void write(byte[] b) throws IOException {
|
||||
super.write(b);
|
||||
flushBuffer();
|
||||
}
|
||||
|
||||
public synchronized void write(int b) throws IOException {
|
||||
if (count >= buffer.length) {
|
||||
flushBuffer();
|
||||
}
|
||||
buffer[count++] = (byte)b;
|
||||
}
|
||||
|
||||
protected synchronized void flushBuffer(){
|
||||
if (count > 0) {
|
||||
String msg = new String(buffer, 0, this.count);
|
||||
listener.notifyDebugEvent(new DebugEventOutputRedirect(msg));
|
||||
count = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,7 @@ import java.io.IOException;
|
||||
|
||||
import org.luaj.debug.event.DebugEventBreakpoint;
|
||||
import org.luaj.debug.event.DebugEventError;
|
||||
import org.luaj.debug.event.DebugEventOutputRedirect;
|
||||
import org.luaj.debug.request.DebugRequestDisconnect;
|
||||
import org.luaj.debug.request.DebugRequestLineBreakpointToggle;
|
||||
import org.luaj.debug.request.DebugRequestStack;
|
||||
@@ -59,6 +60,7 @@ public class SerializationHelper {
|
||||
static final int SERIAL_TYPE_DebugResponseVariables = 12;
|
||||
static final int SERIAL_TYPE_DebugResponseStack = 13;
|
||||
static final int SERIAL_TYPE_DebugResponseSession = 14;
|
||||
static final int SERIAL_TYPE_DebugEventOutputRedirect = 15;
|
||||
|
||||
public static void serialize(Serializable object, DataOutputStream dout)
|
||||
throws IOException {
|
||||
@@ -93,6 +95,9 @@ public class SerializationHelper {
|
||||
} else if (object instanceof DebugEventError) {
|
||||
dout.writeInt(SERIAL_TYPE_DebugEventError);
|
||||
DebugEventError.serialize(dout, (DebugEventError) object);
|
||||
} else if (object instanceof DebugEventOutputRedirect) {
|
||||
dout.writeInt(SERIAL_TYPE_DebugEventOutputRedirect);
|
||||
DebugEventOutputRedirect.serialize(dout, (DebugEventOutputRedirect) object);
|
||||
} else if (object instanceof DebugResponseStack) {
|
||||
dout.writeInt(SERIAL_TYPE_DebugResponseStack);
|
||||
DebugResponseStack.serialize(dout, (DebugResponseStack) object);
|
||||
@@ -152,6 +157,9 @@ public class SerializationHelper {
|
||||
case SERIAL_TYPE_DebugEventError:
|
||||
object = DebugEventError.deserialize(din);
|
||||
break;
|
||||
case SERIAL_TYPE_DebugEventOutputRedirect:
|
||||
object = DebugEventOutputRedirect.deserialize(din);
|
||||
break;
|
||||
case SERIAL_TYPE_DebugResponseCallgraph:
|
||||
object = DebugResponseCallgraph.deserialize(din);
|
||||
break;
|
||||
|
||||
40
src/debug/org/luaj/debug/event/DebugEventOutputRedirect.java
Normal file
40
src/debug/org/luaj/debug/event/DebugEventOutputRedirect.java
Normal file
@@ -0,0 +1,40 @@
|
||||
package org.luaj.debug.event;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import org.luaj.debug.DebugMessage;
|
||||
import org.luaj.debug.DebugMessageType;
|
||||
|
||||
public class DebugEventOutputRedirect extends DebugMessage {
|
||||
protected String data;
|
||||
|
||||
public DebugEventOutputRedirect(String data) {
|
||||
super(DebugMessageType.outputRedirect);
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public String getOutput() {
|
||||
return this.data;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
public String toString() {
|
||||
return type.toString() + ": " + this.data;
|
||||
}
|
||||
|
||||
public static void serialize(DataOutputStream out, DebugEventOutputRedirect event)
|
||||
throws IOException {
|
||||
out.writeUTF(event.getOutput());
|
||||
}
|
||||
|
||||
public static DebugMessage deserialize(DataInputStream in) throws IOException {
|
||||
String data = in.readUTF();
|
||||
return new DebugEventOutputRedirect(data);
|
||||
}
|
||||
}
|
||||
37
src/debug/org/luaj/debug/j2se/J2sePlatform.java
Normal file
37
src/debug/org/luaj/debug/j2se/J2sePlatform.java
Normal file
@@ -0,0 +1,37 @@
|
||||
package org.luaj.debug.j2se;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.Reader;
|
||||
|
||||
import org.luaj.debug.net.j2se.DebugSupportImpl;
|
||||
import org.luaj.vm.DebugNetSupport;
|
||||
import org.luaj.vm.Platform;
|
||||
|
||||
public class J2sePlatform extends Platform {
|
||||
public Reader createReader(InputStream inputStream) {
|
||||
return new InputStreamReader(inputStream);
|
||||
}
|
||||
|
||||
public InputStream openFile(String fileName) {
|
||||
return getClass().getResourceAsStream("/" + fileName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assumes J2SE platform, return the corresponding system
|
||||
* property
|
||||
*/
|
||||
public String getProperty(String propertyName) {
|
||||
return System.getProperty(propertyName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a J2SE DebugSupport instance.
|
||||
*/
|
||||
public DebugNetSupport getDebugSupport() throws IOException {
|
||||
int port = getDebugPort();
|
||||
DebugSupportImpl debugSupport = new DebugSupportImpl(port);
|
||||
return debugSupport;
|
||||
}
|
||||
}
|
||||
@@ -36,6 +36,7 @@ import org.luaj.vm.LValue;
|
||||
import org.luaj.vm.LoadState;
|
||||
import org.luaj.vm.LuaErrorException;
|
||||
import org.luaj.vm.LuaState;
|
||||
import org.luaj.vm.Platform;
|
||||
|
||||
/**
|
||||
* StandardLuaJVM executes a lua program in normal run mode or debug mode.
|
||||
@@ -171,6 +172,8 @@ public class StandardLuaJVM {
|
||||
public void run() {
|
||||
try {
|
||||
// new lua debug state
|
||||
Platform.setInstance(new J2sePlatform());
|
||||
|
||||
state = LuaState.newState();
|
||||
init(state);
|
||||
|
||||
|
||||
@@ -10,9 +10,11 @@ import javax.microedition.io.SocketConnection;
|
||||
|
||||
import org.luaj.debug.DebugMessage;
|
||||
import org.luaj.debug.DebugMessageType;
|
||||
import org.luaj.debug.RedirectOutputStream;
|
||||
import org.luaj.debug.SerializationHelper;
|
||||
import org.luaj.debug.event.DebugEventListener;
|
||||
import org.luaj.debug.response.DebugResponseSession;
|
||||
import org.luaj.lib.BaseLib;
|
||||
|
||||
public class ClientConnectionTask implements Runnable, DebugEventListener {
|
||||
private static final boolean TRACE = true; //(null != System.getProperty("TRACE"));
|
||||
@@ -26,6 +28,8 @@ public class ClientConnectionTask implements Runnable, DebugEventListener {
|
||||
protected DataInputStream inStream;
|
||||
protected DataOutputStream outStream;
|
||||
|
||||
protected RedirectOutputStream redirectOutputStream;
|
||||
|
||||
public ClientConnectionTask(String host, int port, DebugSupportImpl debugSupport) {
|
||||
this.host = host;
|
||||
this.port = port;
|
||||
@@ -59,6 +63,10 @@ public class ClientConnectionTask implements Runnable, DebugEventListener {
|
||||
if ( TRACE )
|
||||
System.out.println("LuaJ debug server connected to " + host + ":" + port);
|
||||
|
||||
// to redirect the print to the debug client console
|
||||
this.redirectOutputStream = new RedirectOutputStream(this);
|
||||
BaseLib.redirectOutput( redirectOutputStream );
|
||||
|
||||
// loop for incoming requests
|
||||
while ( !isDisconnected() ) {
|
||||
byte[] data = null;
|
||||
@@ -85,6 +93,13 @@ public class ClientConnectionTask implements Runnable, DebugEventListener {
|
||||
|
||||
debugSupport.disconnect(1);
|
||||
} finally {
|
||||
try {
|
||||
redirectOutputStream.close();
|
||||
} catch (IOException ignore) {}
|
||||
|
||||
// restore the print output
|
||||
BaseLib.restoreStandardOutput();
|
||||
|
||||
dispose();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,9 +8,11 @@ import java.net.Socket;
|
||||
|
||||
import org.luaj.debug.DebugMessage;
|
||||
import org.luaj.debug.DebugMessageType;
|
||||
import org.luaj.debug.RedirectOutputStream;
|
||||
import org.luaj.debug.SerializationHelper;
|
||||
import org.luaj.debug.event.DebugEventListener;
|
||||
import org.luaj.debug.response.DebugResponseSession;
|
||||
import org.luaj.lib.BaseLib;
|
||||
|
||||
public class ClientConnectionTask implements Runnable, DebugEventListener {
|
||||
private static final boolean TRACE = (null != System.getProperty("TRACE"));
|
||||
@@ -23,6 +25,7 @@ public class ClientConnectionTask implements Runnable, DebugEventListener {
|
||||
protected DataOutputStream eventWriter;
|
||||
protected DebugSupportImpl debugSupport;
|
||||
protected boolean isDisposed = false;
|
||||
protected RedirectOutputStream redirectOutputStream;
|
||||
|
||||
public ClientConnectionTask(DebugSupportImpl debugSupport, Socket socket)
|
||||
throws IOException {
|
||||
@@ -60,6 +63,10 @@ public class ClientConnectionTask implements Runnable, DebugEventListener {
|
||||
|
||||
public void run() {
|
||||
try {
|
||||
// to redirect the print to the debug client console
|
||||
this.redirectOutputStream = new RedirectOutputStream(this);
|
||||
BaseLib.redirectOutput( redirectOutputStream );
|
||||
|
||||
// loop for incoming requests
|
||||
while (!isDisconnected()) {
|
||||
byte[] data = null;
|
||||
@@ -87,6 +94,13 @@ public class ClientConnectionTask implements Runnable, DebugEventListener {
|
||||
|
||||
debugSupport.disconnect(getSessionId());
|
||||
} finally {
|
||||
try {
|
||||
redirectOutputStream.close();
|
||||
} catch (IOException ignore) {}
|
||||
|
||||
// restore the print output
|
||||
BaseLib.restoreStandardOutput();
|
||||
|
||||
dispose();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import java.io.IOException;
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.luaj.debug.event.DebugEventBreakpoint;
|
||||
import org.luaj.debug.event.DebugEventOutputRedirect;
|
||||
|
||||
public class DebugEventTest extends TestCase {
|
||||
public void testDebugEventSerialization() {
|
||||
@@ -34,4 +35,17 @@ public class DebugEventTest extends TestCase {
|
||||
fail(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public void testDebugEventOutputRedirectSerialization() {
|
||||
try {
|
||||
String msg = "This is a testing message";
|
||||
DebugEventOutputRedirect redirectEvent = new DebugEventOutputRedirect(msg);
|
||||
byte[] data = SerializationHelper.serialize(redirectEvent);
|
||||
DebugEventOutputRedirect redirectEventOut = (DebugEventOutputRedirect)
|
||||
SerializationHelper.deserialize(data);
|
||||
assertEquals(msg, redirectEventOut.getOutput());
|
||||
} catch (IOException e) {
|
||||
fail(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
24
src/test/java/org/luaj/debug/RedirectOutputStreamTest.java
Normal file
24
src/test/java/org/luaj/debug/RedirectOutputStreamTest.java
Normal file
@@ -0,0 +1,24 @@
|
||||
package org.luaj.debug;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.luaj.debug.event.DebugEventListener;
|
||||
|
||||
public class RedirectOutputStreamTest extends TestCase {
|
||||
public void testRedirectOutputStream() {
|
||||
RedirectOutputStream redirectOut = new RedirectOutputStream(
|
||||
new DebugEventListener(){
|
||||
public void notifyDebugEvent(DebugMessage event) {
|
||||
assertEquals(event.toString(), "outputRedirect: true\r\na");
|
||||
}
|
||||
|
||||
});
|
||||
PrintWriter writer = new PrintWriter(redirectOut);
|
||||
writer.print(true);
|
||||
writer.println();
|
||||
writer.print('a');
|
||||
writer.close();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user