1. updated the code to use LuaErrorException and removed VMException
2. refactored debugging network communication layer
This commit is contained in:
@@ -1,66 +0,0 @@
|
|||||||
package org.luaj.debug.j2me;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
import javax.microedition.io.Connector;
|
|
||||||
import javax.microedition.io.ServerSocketConnection;
|
|
||||||
import javax.microedition.io.SocketConnection;
|
|
||||||
|
|
||||||
import org.luaj.debug.DebugSupport;
|
|
||||||
|
|
||||||
public class DebugSupportImpl extends DebugSupport {
|
|
||||||
protected ServerSocketConnection serverConnection;
|
|
||||||
protected SocketConnection clientDebugConnection;
|
|
||||||
protected SocketConnection eventSocketConnection;
|
|
||||||
|
|
||||||
public DebugSupportImpl(int debugPort) throws IOException {
|
|
||||||
super(debugPort);
|
|
||||||
this.serverConnection
|
|
||||||
= (ServerSocketConnection) Connector.open(
|
|
||||||
"socket://:" + this.debugPort, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* (non-Javadoc)
|
|
||||||
*
|
|
||||||
* @see lua.debug.j2se.DebugSupport#start()
|
|
||||||
*/
|
|
||||||
public void acceptClientConnection() throws IOException {
|
|
||||||
// Set up the request socket and request input + event output streams
|
|
||||||
this.clientDebugConnection
|
|
||||||
= (SocketConnection) serverConnection.acceptAndOpen();
|
|
||||||
clientDebugConnection.setSocketOption(SocketConnection.DELAY, 0);
|
|
||||||
clientDebugConnection.setSocketOption(SocketConnection.LINGER, 0);
|
|
||||||
clientDebugConnection.setSocketOption(SocketConnection.KEEPALIVE, 1);
|
|
||||||
clientDebugConnection.setSocketOption(SocketConnection.RCVBUF, 1024);
|
|
||||||
clientDebugConnection.setSocketOption(SocketConnection.SNDBUF, 1024);
|
|
||||||
this.requestReader = clientDebugConnection.openDataInputStream();
|
|
||||||
this.eventWriter = clientDebugConnection.openDataOutputStream();
|
|
||||||
|
|
||||||
System.out.println("Lua debug server is started on ports: " + debugPort);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void releaseClientConnection() {
|
|
||||||
super.dispose();
|
|
||||||
|
|
||||||
if (this.clientDebugConnection != null) {
|
|
||||||
try {
|
|
||||||
clientDebugConnection.close();
|
|
||||||
clientDebugConnection = null;
|
|
||||||
} catch (IOException e) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void dispose() {
|
|
||||||
releaseClientConnection();
|
|
||||||
|
|
||||||
if (this.serverConnection != null) {
|
|
||||||
try {
|
|
||||||
serverConnection.close();
|
|
||||||
serverConnection = null;
|
|
||||||
} catch (IOException e) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,71 +0,0 @@
|
|||||||
/*******************************************************************************
|
|
||||||
* Copyright (c) 2007 LuaJ. All rights reserved.
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in
|
|
||||||
* all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
* THE SOFTWARE.
|
|
||||||
******************************************************************************/
|
|
||||||
package org.luaj.debug.j2se;
|
|
||||||
|
|
||||||
import java.io.DataInputStream;
|
|
||||||
import java.io.DataOutputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.net.ServerSocket;
|
|
||||||
import java.net.Socket;
|
|
||||||
|
|
||||||
import org.luaj.debug.DebugSupport;
|
|
||||||
|
|
||||||
|
|
||||||
public class DebugSupportImpl extends DebugSupport {
|
|
||||||
protected ServerSocket serverSocket;
|
|
||||||
protected Socket clientSocket;
|
|
||||||
|
|
||||||
public DebugSupportImpl(int debugPort) throws IOException {
|
|
||||||
super(debugPort);
|
|
||||||
this.serverSocket = new ServerSocket(debugPort, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void acceptClientConnection() throws IOException {
|
|
||||||
this.clientSocket = serverSocket.accept();
|
|
||||||
this.requestReader
|
|
||||||
= new DataInputStream(clientSocket.getInputStream());
|
|
||||||
this.eventWriter
|
|
||||||
= new DataOutputStream(clientSocket.getOutputStream());
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void releaseClientConnection() {
|
|
||||||
super.dispose();
|
|
||||||
|
|
||||||
if (this.clientSocket != null) {
|
|
||||||
try {
|
|
||||||
clientSocket.close();
|
|
||||||
clientSocket = null;
|
|
||||||
} catch (IOException e) {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void dispose() {
|
|
||||||
releaseClientConnection();
|
|
||||||
|
|
||||||
if (this.serverSocket != null) {
|
|
||||||
try {
|
|
||||||
serverSocket.close();
|
|
||||||
serverSocket = null;
|
|
||||||
} catch (IOException e) {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -28,15 +28,15 @@ import java.io.InputStream;
|
|||||||
|
|
||||||
import org.luaj.compiler.LuaC;
|
import org.luaj.compiler.LuaC;
|
||||||
import org.luaj.debug.DebugLuaState;
|
import org.luaj.debug.DebugLuaState;
|
||||||
import org.luaj.debug.DebugSupport;
|
import org.luaj.debug.net.DebugSupport;
|
||||||
import org.luaj.debug.DebugUtils;
|
import org.luaj.debug.net.j2se.DebugSupportImpl;
|
||||||
import org.luaj.debug.VMException;
|
|
||||||
import org.luaj.lib.j2se.LuajavaLib;
|
import org.luaj.lib.j2se.LuajavaLib;
|
||||||
import org.luaj.vm.LClosure;
|
import org.luaj.vm.LClosure;
|
||||||
import org.luaj.vm.LPrototype;
|
import org.luaj.vm.LPrototype;
|
||||||
import org.luaj.vm.LString;
|
import org.luaj.vm.LString;
|
||||||
import org.luaj.vm.LValue;
|
import org.luaj.vm.LValue;
|
||||||
import org.luaj.vm.LoadState;
|
import org.luaj.vm.LoadState;
|
||||||
|
import org.luaj.vm.LuaErrorException;
|
||||||
import org.luaj.vm.LuaState;
|
import org.luaj.vm.LuaState;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -131,7 +131,6 @@ public class StandardLuaJVM {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.script = args[0];
|
this.script = args[0];
|
||||||
DebugUtils.println("Lua script to run: " + this.script);
|
|
||||||
int scriptArgsLength = args.length - 1;
|
int scriptArgsLength = args.length - 1;
|
||||||
if (scriptArgsLength > 0) {
|
if (scriptArgsLength > 0) {
|
||||||
this.scriptArgs = new String[scriptArgsLength];
|
this.scriptArgs = new String[scriptArgsLength];
|
||||||
@@ -167,11 +166,19 @@ public class StandardLuaJVM {
|
|||||||
return this.scriptArgs;
|
return this.scriptArgs;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void run() throws IOException {
|
public void run() {
|
||||||
if (isDebug()) {
|
try {
|
||||||
doDebug();
|
if (isDebug()) {
|
||||||
} else {
|
doDebug();
|
||||||
doRun();
|
} else {
|
||||||
|
doRun();
|
||||||
|
}
|
||||||
|
} catch (LuaErrorException e) {
|
||||||
|
System.err.println("Error: " + e.getMessage());
|
||||||
|
System.err.print(state.getStackTrace());
|
||||||
|
System.err.flush();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -202,29 +209,24 @@ public class StandardLuaJVM {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// load the Lua file
|
// load the Lua file
|
||||||
DebugUtils.println("loading Lua script '" + getScript() + "'");
|
|
||||||
InputStream is = new FileInputStream(new File(getScript()));
|
InputStream is = new FileInputStream(new File(getScript()));
|
||||||
LPrototype p = LoadState.undump(state, is, getScript());
|
LPrototype p = LoadState.undump(state, is, getScript());
|
||||||
|
|
||||||
// create closure and execute
|
// create closure and execute
|
||||||
LClosure c = new LClosure(state, p);
|
LClosure c = new LClosure(state, p);
|
||||||
state.doCall(c, vargs);
|
state.doCall(c, vargs);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void doDebug() throws IOException {
|
protected void doDebug() throws IOException {
|
||||||
DebugUtils.println("setting up LuaJava and debug stack state...");
|
|
||||||
|
|
||||||
// new lua debug state
|
// new lua debug state
|
||||||
state = new DebugLuaState();
|
state = new DebugLuaState();
|
||||||
init(state);
|
init(state);
|
||||||
|
|
||||||
// load the Lua file
|
// load the Lua file
|
||||||
DebugUtils.println("loading Lua script '" + getScript() + "'");
|
|
||||||
InputStream is = new FileInputStream(new File(getScript()));
|
InputStream is = new FileInputStream(new File(getScript()));
|
||||||
LPrototype p = LoadState.undump(state, is, getScript());
|
LPrototype p = LoadState.undump(state, is, getScript());
|
||||||
|
|
||||||
// set up debug support if the file is successfully loaded
|
// set up debug support if the file is successfully loaded
|
||||||
DebugUtils.println("start debugging...");
|
|
||||||
DebugSupport debugSupport = new DebugSupportImpl(getDebugPort());
|
DebugSupport debugSupport = new DebugSupportImpl(getDebugPort());
|
||||||
getDebugState().setSuspendAtStart(getSuspendOnStart());
|
getDebugState().setSuspendAtStart(getSuspendOnStart());
|
||||||
getDebugState().setDebugSupport(debugSupport);
|
getDebugState().setDebugSupport(debugSupport);
|
||||||
@@ -239,10 +241,9 @@ public class StandardLuaJVM {
|
|||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
getDebugState().doCall(c, vargs);
|
getDebugState().doCall(c, vargs);
|
||||||
} catch (VMException e) {
|
} finally {
|
||||||
System.err.println("VMException: " + e.getMessage());
|
getDebugState().stop();
|
||||||
}
|
}
|
||||||
getDebugState().stop();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private DebugLuaState getDebugState() {
|
private DebugLuaState getDebugState() {
|
||||||
@@ -264,9 +265,6 @@ public class StandardLuaJVM {
|
|||||||
System.out.println("Error: " + e.getMessage());
|
System.out.println("Error: " + e.getMessage());
|
||||||
vm.printUsage();
|
vm.printUsage();
|
||||||
return;
|
return;
|
||||||
} catch (IOException e) {
|
|
||||||
System.out.println("Error: " + e.getMessage());
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
18
src/debug/org/luaj/debug/net/DebugSupport.java
Normal file
18
src/debug/org/luaj/debug/net/DebugSupport.java
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
package org.luaj.debug.net;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import org.luaj.debug.DebugLuaState;
|
||||||
|
import org.luaj.debug.event.DebugEventListener;
|
||||||
|
import org.luaj.debug.request.DebugRequestListener;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DebugSupport provides the network communication support for the debugger and
|
||||||
|
* debug clients.
|
||||||
|
*/
|
||||||
|
public interface DebugSupport extends DebugRequestListener, DebugEventListener {
|
||||||
|
public void start() throws IOException;
|
||||||
|
public void stop();
|
||||||
|
public void setDebugStackState(DebugLuaState vm);
|
||||||
|
public void disconnect(int id);
|
||||||
|
}
|
||||||
147
src/debug/org/luaj/debug/net/j2se/ClientConnectionTask.java
Normal file
147
src/debug/org/luaj/debug/net/j2se/ClientConnectionTask.java
Normal file
@@ -0,0 +1,147 @@
|
|||||||
|
package org.luaj.debug.net.j2se;
|
||||||
|
|
||||||
|
import java.io.DataInputStream;
|
||||||
|
import java.io.DataOutputStream;
|
||||||
|
import java.io.EOFException;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.Socket;
|
||||||
|
|
||||||
|
import org.luaj.debug.SerializationHelper;
|
||||||
|
import org.luaj.debug.event.DebugEvent;
|
||||||
|
import org.luaj.debug.event.DebugEventListener;
|
||||||
|
import org.luaj.debug.request.DebugRequest;
|
||||||
|
import org.luaj.debug.request.DebugRequestType;
|
||||||
|
import org.luaj.debug.response.DebugResponseSession;
|
||||||
|
|
||||||
|
public class ClientConnectionTask implements Runnable, DebugEventListener {
|
||||||
|
private static final boolean TRACE = (null != System.getProperty("TRACE"));
|
||||||
|
protected static int counter = 1;
|
||||||
|
|
||||||
|
protected int sessionId;
|
||||||
|
protected Socket clientSocket;
|
||||||
|
protected boolean bDisconnected = false;
|
||||||
|
protected DataInputStream requestReader;
|
||||||
|
protected DataOutputStream eventWriter;
|
||||||
|
protected DebugSupportImpl debugSupport;
|
||||||
|
|
||||||
|
public ClientConnectionTask(DebugSupportImpl debugSupport, Socket socket)
|
||||||
|
throws IOException {
|
||||||
|
this.debugSupport = debugSupport;
|
||||||
|
this.sessionId = getNextId();
|
||||||
|
this.clientSocket = socket;
|
||||||
|
this.requestReader
|
||||||
|
= new DataInputStream(clientSocket.getInputStream());
|
||||||
|
this.eventWriter
|
||||||
|
= new DataOutputStream(clientSocket.getOutputStream());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected synchronized int getNextId() {
|
||||||
|
// when the number of ClientConnectionTask created approaches
|
||||||
|
// Integer.MAX_VALUE, reset to 1. We don't expect we have
|
||||||
|
// Integer.MAX_VALUE concurrent debug clients ever.
|
||||||
|
if (counter == Integer.MAX_VALUE) {
|
||||||
|
counter = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return counter++;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void disconnect () {
|
||||||
|
this.bDisconnected = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isDisconnected() {
|
||||||
|
return this.bDisconnected;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getSessionId() {
|
||||||
|
return this.sessionId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
// loop for incoming requests
|
||||||
|
while (!isDisconnected()) {
|
||||||
|
byte[] data = null;
|
||||||
|
int size = requestReader.readInt();
|
||||||
|
data = new byte[size];
|
||||||
|
requestReader.readFully(data);
|
||||||
|
|
||||||
|
DebugRequest request = (DebugRequest) SerializationHelper
|
||||||
|
.deserialize(data);
|
||||||
|
if (TRACE) {
|
||||||
|
System.out.println("SERVER receives request: " + request.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
handleRequest(request);
|
||||||
|
}
|
||||||
|
} catch (EOFException e) {
|
||||||
|
// client has terminated the connection
|
||||||
|
// it's time to exit.
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
|
||||||
|
// if the connected debugging client aborted abnormally,
|
||||||
|
// discard the current connection.
|
||||||
|
handleRequest(new DebugRequest(DebugRequestType.reset));
|
||||||
|
} finally {
|
||||||
|
dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void handleRequest(DebugRequest request) {
|
||||||
|
if (TRACE) {
|
||||||
|
System.out.println("SERVER handling request: " + request.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (request.getType() == DebugRequestType.session) {
|
||||||
|
notifyDebugEvent(new DebugResponseSession(getSessionId()));
|
||||||
|
} else {
|
||||||
|
debugSupport.handleRequest(request);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void notifyDebugEvent(DebugEvent event) {
|
||||||
|
if (TRACE)
|
||||||
|
System.out.println("SERVER sending event: " + event.toString());
|
||||||
|
|
||||||
|
if (event == null)
|
||||||
|
System.out.println("notifyDebugEvent: event is null");
|
||||||
|
if (eventWriter == null)
|
||||||
|
System.out.println("notifyDebugEvent: eventWriter is null");
|
||||||
|
|
||||||
|
try {
|
||||||
|
byte[] data = SerializationHelper.serialize(event);
|
||||||
|
eventWriter.writeInt(data.length);
|
||||||
|
eventWriter.write(data);
|
||||||
|
eventWriter.flush();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void dispose() {
|
||||||
|
debugSupport.decrementClientCount();
|
||||||
|
|
||||||
|
if (this.requestReader != null) {
|
||||||
|
try {
|
||||||
|
requestReader.close();
|
||||||
|
requestReader = null;
|
||||||
|
} catch (IOException e) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.eventWriter != null) {
|
||||||
|
try {
|
||||||
|
eventWriter.close();
|
||||||
|
eventWriter = null;
|
||||||
|
} catch (IOException e) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.clientSocket != null) {
|
||||||
|
try {
|
||||||
|
clientSocket.close();
|
||||||
|
clientSocket = null;
|
||||||
|
} catch (IOException e) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
182
src/debug/org/luaj/debug/net/j2se/DebugSupportImpl.java
Normal file
182
src/debug/org/luaj/debug/net/j2se/DebugSupportImpl.java
Normal file
@@ -0,0 +1,182 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2007 LuaJ. All rights reserved.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
******************************************************************************/
|
||||||
|
package org.luaj.debug.net.j2se;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.ServerSocket;
|
||||||
|
import java.net.Socket;
|
||||||
|
|
||||||
|
import org.luaj.debug.DebugLuaState;
|
||||||
|
import org.luaj.debug.event.DebugEvent;
|
||||||
|
import org.luaj.debug.net.DebugSupport;
|
||||||
|
import org.luaj.debug.request.DebugRequest;
|
||||||
|
|
||||||
|
|
||||||
|
public class DebugSupportImpl implements DebugSupport {
|
||||||
|
protected static final int UNKNOWN = 0;
|
||||||
|
protected static final int RUNNING = 1;
|
||||||
|
protected static final int STOPPED = 2;
|
||||||
|
|
||||||
|
protected int state = UNKNOWN;
|
||||||
|
protected int numClientConnectionsAllowed;
|
||||||
|
protected int numClientConnections = 0;
|
||||||
|
protected DebugLuaState vm;
|
||||||
|
protected ServerSocket serverSocket;
|
||||||
|
protected int debugPort;
|
||||||
|
protected ClientConnectionTask clientConnectionTask;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an instance of DebugSupportImpl at the given port
|
||||||
|
* @param debugPort
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
public DebugSupportImpl(int debugPort) throws IOException {
|
||||||
|
this(debugPort, 1);
|
||||||
|
this.serverSocket
|
||||||
|
= new ServerSocket(debugPort, this.numClientConnectionsAllowed);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a debugging service on the given port. The service will support
|
||||||
|
* <code>numClientConnections</code> debug client connections.
|
||||||
|
* @param port Debug port
|
||||||
|
* @param connections
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
protected DebugSupportImpl(int port, int connections) throws IOException {
|
||||||
|
if (port < 0 || port > 0xFFFF) {
|
||||||
|
throw new IllegalArgumentException("port value out of range: " + port);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (connections <= 0) {
|
||||||
|
throw new IllegalArgumentException("numClientConnections value must be greater than zero");
|
||||||
|
}
|
||||||
|
|
||||||
|
this.debugPort = port;
|
||||||
|
this.numClientConnectionsAllowed = connections;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDebugStackState(DebugLuaState vm) {
|
||||||
|
this.vm = vm;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void start() throws IOException {
|
||||||
|
if (this.vm == null) {
|
||||||
|
throw new IllegalStateException(
|
||||||
|
"DebugLuaState is not set. Please call setDebugStackState first.");
|
||||||
|
}
|
||||||
|
|
||||||
|
setState(RUNNING);
|
||||||
|
System.out.println("LuaJ debug server is listening on port: " + debugPort);
|
||||||
|
|
||||||
|
new Thread(new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
while (isRunning()) {
|
||||||
|
try {
|
||||||
|
acceptClientConnection();
|
||||||
|
} catch (IOException e) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}).start();
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void incrementClientCount() {
|
||||||
|
this.numClientConnections++;
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void decrementClientCount() {
|
||||||
|
this.numClientConnections--;
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized int getClientCount() {
|
||||||
|
return this.numClientConnections;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected synchronized void setState(int state) {
|
||||||
|
this.state = state;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected synchronized boolean isRunning() {
|
||||||
|
return this.state == RUNNING;
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void stop() {
|
||||||
|
setState(STOPPED);
|
||||||
|
if (clientConnectionTask != null) {
|
||||||
|
disconnect(clientConnectionTask.getSessionId());
|
||||||
|
}
|
||||||
|
dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
*
|
||||||
|
* @see org.luaj.debug.event.DebugEventListener#notifyDebugEvent(org.luaj.debug.event.DebugEvent)
|
||||||
|
*/
|
||||||
|
public void notifyDebugEvent(DebugEvent event) {
|
||||||
|
if (clientConnectionTask != null) {
|
||||||
|
clientConnectionTask.notifyDebugEvent(event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
*
|
||||||
|
* @see org.luaj.debug.request.DebugRequestListener#handleRequest(org.luaj.debug.request.DebugRequest)
|
||||||
|
*/
|
||||||
|
public void handleRequest(DebugRequest request) {
|
||||||
|
vm.handleRequest(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void disconnect(int id) {
|
||||||
|
if (clientConnectionTask.getSessionId() == id) {
|
||||||
|
clientConnectionTask.disconnect();
|
||||||
|
clientConnectionTask = null;
|
||||||
|
} else {
|
||||||
|
throw new RuntimeException("Internal Error: mismatching sesion Id: " + id + " current task: " + clientConnectionTask.getSessionId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void acceptClientConnection() throws IOException {
|
||||||
|
Socket clientSocket = serverSocket.accept();
|
||||||
|
int count = getClientCount();
|
||||||
|
if (count == numClientConnectionsAllowed) {
|
||||||
|
clientSocket.close();
|
||||||
|
} else {
|
||||||
|
synchronized(this) {
|
||||||
|
incrementClientCount();
|
||||||
|
this.clientConnectionTask = new ClientConnectionTask(this, clientSocket);
|
||||||
|
new Thread(clientConnectionTask).start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected synchronized void dispose() {
|
||||||
|
this.clientConnectionTask = null;
|
||||||
|
if (this.serverSocket != null) {
|
||||||
|
try {
|
||||||
|
serverSocket.close();
|
||||||
|
serverSocket = null;
|
||||||
|
} catch (IOException e) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
34
src/debug/org/luaj/debug/request/DebugRequestDisconnect.java
Normal file
34
src/debug/org/luaj/debug/request/DebugRequestDisconnect.java
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
package org.luaj.debug.request;
|
||||||
|
|
||||||
|
import java.io.DataInputStream;
|
||||||
|
import java.io.DataOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
public class DebugRequestDisconnect extends DebugRequest {
|
||||||
|
protected int sessionId;
|
||||||
|
|
||||||
|
public DebugRequestDisconnect(int connectionId) {
|
||||||
|
super(DebugRequestType.disconnect);
|
||||||
|
this.sessionId = connectionId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getSessionId() {
|
||||||
|
return this.sessionId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return super.toString() + " sessionId:" + getSessionId();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void serialize(DataOutputStream out, DebugRequestDisconnect request)
|
||||||
|
throws IOException {
|
||||||
|
out.writeInt(request.getSessionId());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static DebugRequest deserialize(DataInputStream in)
|
||||||
|
throws IOException {
|
||||||
|
int id = in.readInt();
|
||||||
|
|
||||||
|
return new DebugRequestDisconnect(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,24 +1,24 @@
|
|||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* Copyright (c) 2007 LuaJ. All rights reserved.
|
* Copyright (c) 2007 LuaJ. All rights reserved.
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
* in the Software without restriction, including without limitation the rights
|
* in the Software without restriction, including without limitation the rights
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
* furnished to do so, subject to the following conditions:
|
* furnished to do so, subject to the following conditions:
|
||||||
*
|
*
|
||||||
* The above copyright notice and this permission notice shall be included in
|
* The above copyright notice and this permission notice shall be included in
|
||||||
* all copies or substantial portions of the Software.
|
* all copies or substantial portions of the Software.
|
||||||
*
|
*
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
* THE SOFTWARE.
|
* THE SOFTWARE.
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
package org.luaj.debug.request;
|
package org.luaj.debug.request;
|
||||||
|
|
||||||
import java.io.DataInputStream;
|
import java.io.DataInputStream;
|
||||||
@@ -27,34 +27,36 @@ import java.io.IOException;
|
|||||||
|
|
||||||
import org.luaj.debug.Serializable;
|
import org.luaj.debug.Serializable;
|
||||||
|
|
||||||
|
|
||||||
public class DebugRequestStack extends DebugRequest implements Serializable {
|
public class DebugRequestStack extends DebugRequest implements Serializable {
|
||||||
protected int index;
|
protected int index;
|
||||||
|
|
||||||
public DebugRequestStack(int index) {
|
public DebugRequestStack(int index) {
|
||||||
super(DebugRequestType.stack);
|
super(DebugRequestType.stack);
|
||||||
this.index = index;
|
this.index = index;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getIndex() {
|
public int getIndex() {
|
||||||
return this.index;
|
return this.index;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* (non-Javadoc)
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
*
|
||||||
* @see lua.debug.DebugRequest#toString()
|
* @see lua.debug.DebugRequest#toString()
|
||||||
*/
|
*/
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return super.toString() + " stack frame:" + getIndex();
|
return super.toString() + " stack frame:" + getIndex();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void serialize(DataOutputStream out, DebugRequestStack request)
|
public static void serialize(DataOutputStream out, DebugRequestStack request)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
out.writeInt(request.getIndex());
|
out.writeInt(request.getIndex());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static DebugRequest deserialize(DataInputStream in) throws IOException {
|
public static DebugRequest deserialize(DataInputStream in)
|
||||||
int index = in.readInt();
|
throws IOException {
|
||||||
|
int index = in.readInt();
|
||||||
return new DebugRequestStack(index);
|
|
||||||
}
|
return new DebugRequestStack(index);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,6 +44,8 @@ public class DebugRequestType extends EnumType {
|
|||||||
public static final DebugRequestType stepReturn = new DebugRequestType("stepReturn", 12);
|
public static final DebugRequestType stepReturn = new DebugRequestType("stepReturn", 12);
|
||||||
public static final DebugRequestType global = new DebugRequestType("global", 13);
|
public static final DebugRequestType global = new DebugRequestType("global", 13);
|
||||||
public static final DebugRequestType disconnect = new DebugRequestType("disconnect", 14);
|
public static final DebugRequestType disconnect = new DebugRequestType("disconnect", 14);
|
||||||
|
public static final DebugRequestType reset = new DebugRequestType("reset", 15);
|
||||||
|
public static final DebugRequestType session = new DebugRequestType("session", 16);
|
||||||
|
|
||||||
protected static final DebugRequestType[] ENUMS = new DebugRequestType[] {
|
protected static final DebugRequestType[] ENUMS = new DebugRequestType[] {
|
||||||
start,
|
start,
|
||||||
@@ -60,7 +62,9 @@ public class DebugRequestType extends EnumType {
|
|||||||
stepOver,
|
stepOver,
|
||||||
stepReturn,
|
stepReturn,
|
||||||
global,
|
global,
|
||||||
disconnect
|
disconnect,
|
||||||
|
reset,
|
||||||
|
session
|
||||||
};
|
};
|
||||||
|
|
||||||
public DebugRequestType(String name, int ordinal) {
|
public DebugRequestType(String name, int ordinal) {
|
||||||
|
|||||||
36
src/debug/org/luaj/debug/response/DebugResponseSession.java
Normal file
36
src/debug/org/luaj/debug/response/DebugResponseSession.java
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
package org.luaj.debug.response;
|
||||||
|
|
||||||
|
import java.io.DataInputStream;
|
||||||
|
import java.io.DataOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import org.luaj.debug.event.DebugEvent;
|
||||||
|
import org.luaj.debug.event.DebugEventType;
|
||||||
|
|
||||||
|
public class DebugResponseSession extends DebugEvent {
|
||||||
|
protected int sessionId;
|
||||||
|
|
||||||
|
public DebugResponseSession(int id) {
|
||||||
|
super(DebugEventType.session);
|
||||||
|
this.sessionId = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getSessionId() {
|
||||||
|
return this.sessionId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return "SessionId: " + getSessionId();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void serialize(DataOutputStream out,
|
||||||
|
DebugResponseSession response)
|
||||||
|
throws IOException {
|
||||||
|
out.writeInt(response.getSessionId());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static DebugEvent deserialize(DataInputStream in) throws IOException {
|
||||||
|
int id = in.readInt();
|
||||||
|
return new DebugResponseSession(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,10 +4,9 @@ import java.io.IOException;
|
|||||||
|
|
||||||
import junit.framework.TestCase;
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
import org.luaj.debug.event.DebugEventType;
|
|
||||||
import org.luaj.debug.response.DebugResponseCallgraph;
|
import org.luaj.debug.response.DebugResponseCallgraph;
|
||||||
|
import org.luaj.debug.response.DebugResponseSession;
|
||||||
import org.luaj.debug.response.DebugResponseStack;
|
import org.luaj.debug.response.DebugResponseStack;
|
||||||
import org.luaj.debug.response.DebugResponseVariables;
|
|
||||||
import org.luaj.vm.Lua;
|
import org.luaj.vm.Lua;
|
||||||
|
|
||||||
public class DebugResponseTest extends TestCase {
|
public class DebugResponseTest extends TestCase {
|
||||||
@@ -62,7 +61,7 @@ public class DebugResponseTest extends TestCase {
|
|||||||
doTestDebugResponseCallgraphSerialization(new StackFrame[0]);
|
doTestDebugResponseCallgraphSerialization(new StackFrame[0]);
|
||||||
|
|
||||||
StackFrame[] frames = new StackFrame[1];
|
StackFrame[] frames = new StackFrame[1];
|
||||||
frames[0] = new StackFrame(100, "test.lua");
|
frames[0] = new StackFrame("test.lua", 100);
|
||||||
doTestDebugResponseCallgraphSerialization(frames);
|
doTestDebugResponseCallgraphSerialization(frames);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
fail(e.getMessage());
|
fail(e.getMessage());
|
||||||
@@ -84,4 +83,17 @@ public class DebugResponseTest extends TestCase {
|
|||||||
assertEquals(inFrames[i], outFrames[i]);
|
assertEquals(inFrames[i], outFrames[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testDebugResponseSession() {
|
||||||
|
try {
|
||||||
|
DebugResponseSession sessionResponse = new DebugResponseSession(100);
|
||||||
|
byte[] data = SerializationHelper.serialize(sessionResponse);
|
||||||
|
DebugResponseSession sessionOut
|
||||||
|
= (DebugResponseSession) SerializationHelper.deserialize(data);
|
||||||
|
assertNotNull(sessionOut);
|
||||||
|
assertEquals(sessionResponse.getSessionId(), sessionOut.getSessionId());
|
||||||
|
} catch (IOException e) {
|
||||||
|
fail(e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import junit.framework.TestCase;
|
|||||||
public class StackFrameTest extends TestCase {
|
public class StackFrameTest extends TestCase {
|
||||||
public void testSerialization() {
|
public void testSerialization() {
|
||||||
try {
|
try {
|
||||||
StackFrame stackIn = new StackFrame(10, "test.lua");
|
StackFrame stackIn = new StackFrame("test.lua", 10);
|
||||||
byte[] data = SerializationHelper.serialize(stackIn);
|
byte[] data = SerializationHelper.serialize(stackIn);
|
||||||
StackFrame stackOut = (StackFrame) SerializationHelper.deserialize(data);
|
StackFrame stackOut = (StackFrame) SerializationHelper.deserialize(data);
|
||||||
assertNotNull(stackOut);
|
assertNotNull(stackOut);
|
||||||
|
|||||||
@@ -111,7 +111,6 @@ public class LuaJVMTest extends TestCase {
|
|||||||
vm.run();
|
vm.run();
|
||||||
fail("Should never reach this line.");
|
fail("Should never reach this line.");
|
||||||
} catch (ParseException e) {}
|
} catch (ParseException e) {}
|
||||||
catch (IOException e) {}
|
|
||||||
|
|
||||||
// lua script cannot be found
|
// lua script cannot be found
|
||||||
args = new String[] { "dummy.lua" };
|
args = new String[] { "dummy.lua" };
|
||||||
@@ -122,7 +121,7 @@ public class LuaJVMTest extends TestCase {
|
|||||||
fail("Bad parsing program. Should never reach this line.");
|
fail("Bad parsing program. Should never reach this line.");
|
||||||
} catch (ParseException e) {
|
} catch (ParseException e) {
|
||||||
fail("Should never reach this line.");
|
fail("Should never reach this line.");
|
||||||
} catch (IOException e) {}
|
}
|
||||||
|
|
||||||
// valid command line
|
// valid command line
|
||||||
args = new String[] { "-Dport=1044,suspendOnStart=true", "dummy.lua" };
|
args = new String[] { "-Dport=1044,suspendOnStart=true", "dummy.lua" };
|
||||||
|
|||||||
Reference in New Issue
Block a user