v 0.44, drop debug support
This commit is contained in:
@@ -1,247 +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.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import org.luaj.compiler.LuaC;
|
||||
import org.luaj.debug.DebugLuaState;
|
||||
import org.luaj.lib.PackageLib;
|
||||
import org.luaj.platform.J2sePlatform;
|
||||
import org.luaj.vm.LClosure;
|
||||
import org.luaj.vm.LPrototype;
|
||||
import org.luaj.vm.LString;
|
||||
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.
|
||||
*
|
||||
* @author: Shu Lei
|
||||
* @version: 1.0
|
||||
*/
|
||||
public class StandardLuaJVM {
|
||||
private static final String CMD_LINE_DEBUG_OPTION_SUSPEND_ON_START = "suspendOnStart=";
|
||||
private static final String CMD_LINE_DEBUG_OPTION_PORT = "port=";
|
||||
protected boolean isDebugMode = false;
|
||||
protected int debugPort = -1;;
|
||||
protected boolean bSuspendOnStart = false;
|
||||
protected String script;
|
||||
protected String[] scriptArgs;
|
||||
protected LuaState state;
|
||||
protected boolean isReady = false;
|
||||
protected boolean isTerminated = false;
|
||||
|
||||
// command line parsing utilities
|
||||
class ParseException extends Exception {
|
||||
private static final long serialVersionUID = -3134938136698856577L;
|
||||
|
||||
public ParseException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
|
||||
protected void printUsage() {
|
||||
System.out.println("Usage:");
|
||||
System.out.println("\t java StandardLuaJVM [-Dport=<port>[,suspendedOnStart=<true|false>]] [-L<lua path>] <script> [<script arguments>]");
|
||||
System.out.println("where [] denotes an optional argument and <> denotes a placeholder.");
|
||||
}
|
||||
|
||||
void parse(String[] args) throws ParseException {
|
||||
if (args == null || args.length < 1) {
|
||||
throw new ParseException("Invalid command line arguments.");
|
||||
}
|
||||
|
||||
int index = 0;
|
||||
if (args[index] != null && args[index].startsWith("-D")) {
|
||||
if (args.length < 2) {
|
||||
throw new ParseException("Invalid command line arguments.");
|
||||
}
|
||||
|
||||
this.isDebugMode = true;
|
||||
System.setProperty(Platform.PROPERTY_LUAJ_DEBUG, "true");
|
||||
|
||||
String debugOptions = args[index];
|
||||
debugOptions = debugOptions.substring(2); // remove '-D'
|
||||
String[] options = debugOptions.split(",");
|
||||
for (int i = 0; options != null && i < options.length; i++) {
|
||||
if (options[i].startsWith(CMD_LINE_DEBUG_OPTION_PORT)) {
|
||||
String portString = options[i].substring(CMD_LINE_DEBUG_OPTION_PORT.length());
|
||||
try {
|
||||
this.debugPort = Integer.parseInt(portString);
|
||||
System.setProperty(Platform.PROPERTY_LUAJ_DEBUG_PORT, String.valueOf(debugPort));
|
||||
if (this.debugPort <= 0) {
|
||||
throw new ParseException(
|
||||
"Invalid debug port: it must be greater than zero.");
|
||||
}
|
||||
} catch (NumberFormatException e) {
|
||||
throw new ParseException("Invalid debug port: " + e.getMessage());
|
||||
}
|
||||
} else if (options[i].startsWith(CMD_LINE_DEBUG_OPTION_SUSPEND_ON_START)) {
|
||||
String suspendOnStartStr
|
||||
= options[i].substring(CMD_LINE_DEBUG_OPTION_SUSPEND_ON_START.length());
|
||||
if (!suspendOnStartStr.equalsIgnoreCase("true") &&
|
||||
!suspendOnStartStr.equalsIgnoreCase("false")) {
|
||||
throw new ParseException("invalid debug flag: suspendOnStart");
|
||||
}
|
||||
this.bSuspendOnStart = "true".equalsIgnoreCase(suspendOnStartStr);
|
||||
System.setProperty(Platform.PROPERTY_LUAJ_DEBUG_SUSPEND_AT_START, suspendOnStartStr);
|
||||
} else {
|
||||
throw new ParseException("Invalid command line argument: " + debugOptions);
|
||||
}
|
||||
}
|
||||
|
||||
if (this.debugPort == -1) {
|
||||
throw new ParseException("Invalid command line: debug port is missing");
|
||||
}
|
||||
|
||||
index++;
|
||||
}
|
||||
|
||||
String[] scriptArgStrs;
|
||||
if (index != 0) {
|
||||
int scriptArgsCount = args.length - index;
|
||||
scriptArgStrs = new String[scriptArgsCount];
|
||||
System.arraycopy(args, index, scriptArgStrs, 0, scriptArgsCount);
|
||||
} else {
|
||||
scriptArgStrs = args;
|
||||
}
|
||||
|
||||
parseScriptArgs(scriptArgStrs);
|
||||
}
|
||||
|
||||
private void parseScriptArgs(String[] args)
|
||||
throws org.luaj.debug.j2se.StandardLuaJVM.ParseException {
|
||||
if (args == null || args.length < 1) {
|
||||
throw new ParseException("script is missing.");
|
||||
}
|
||||
|
||||
this.script = args[0];
|
||||
int scriptArgsLength = args.length - 1;
|
||||
if (scriptArgsLength > 0) {
|
||||
this.scriptArgs = new String[scriptArgsLength];
|
||||
for (int i = 1; i < args.length; i++) {
|
||||
this.scriptArgs[i - 1] = args[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// end of command line parsing utilities
|
||||
|
||||
boolean isDebug() {
|
||||
return this.isDebugMode;
|
||||
}
|
||||
|
||||
int getDebugPort() {
|
||||
return this.debugPort;
|
||||
}
|
||||
|
||||
boolean getSuspendOnStart() {
|
||||
return this.bSuspendOnStart;
|
||||
}
|
||||
|
||||
String getScript() {
|
||||
return this.script;
|
||||
}
|
||||
|
||||
boolean hasScriptArgs() {
|
||||
return (this.scriptArgs != null && this.scriptArgs.length > 0);
|
||||
}
|
||||
|
||||
String[] getScriptArgs() {
|
||||
return this.scriptArgs;
|
||||
}
|
||||
|
||||
String getLuaPath() {
|
||||
return System.getProperty("LUA_PATH");
|
||||
}
|
||||
|
||||
public void run() {
|
||||
try {
|
||||
// new lua debug state
|
||||
Platform.setInstance(new J2sePlatform());
|
||||
state = Platform.newLuaState();
|
||||
init(state);
|
||||
|
||||
// load the Lua file
|
||||
InputStream is = new FileInputStream(new File(getScript()));
|
||||
LPrototype p = LoadState.undump(state, is, getScript());
|
||||
|
||||
// create closure and execute
|
||||
final LClosure c = p.newClosure(state._G);
|
||||
String[] args = getScriptArgs();
|
||||
int numOfScriptArgs = (args != null ? args.length : 0);
|
||||
LValue[] vargs = new LValue[numOfScriptArgs];
|
||||
for (int i = 0; i < numOfScriptArgs; i++) {
|
||||
vargs[i] = new LString(args[i]);
|
||||
}
|
||||
try {
|
||||
state.doCall(c, vargs);
|
||||
} finally {
|
||||
if (state instanceof DebugLuaState) {
|
||||
((DebugLuaState)state).stop();
|
||||
}
|
||||
}
|
||||
} catch (LuaErrorException e) {
|
||||
System.err.println("Error: " + e.getMessage());
|
||||
System.err.print(state.getStackTrace());
|
||||
System.err.flush();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
protected void init(LuaState state) {
|
||||
// add the compiler
|
||||
LuaC.install();
|
||||
|
||||
// set the lua path if present
|
||||
String luaPath = getLuaPath();
|
||||
if (luaPath != null && luaPath.trim().length() > 0) {
|
||||
PackageLib.setLuaPath(luaPath);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the command line arguments and executes/debugs the lua program.
|
||||
* @param args -- command line arguments:
|
||||
* [-debug <requestPort> <eventPort>] <script> <script arguments separated by a whitespace>
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
StandardLuaJVM vm = new StandardLuaJVM();
|
||||
|
||||
try {
|
||||
vm.parse(args);
|
||||
vm.run();
|
||||
} catch (ParseException e) {
|
||||
System.out.println("Error: " + e.getMessage());
|
||||
vm.printUsage();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,156 +0,0 @@
|
||||
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.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.lib.BaseLib;
|
||||
|
||||
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;
|
||||
protected boolean isDisposed = false;
|
||||
protected RedirectOutputStream redirectOutputStream;
|
||||
|
||||
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 {
|
||||
// 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;
|
||||
int size = requestReader.readInt();
|
||||
data = new byte[size];
|
||||
requestReader.readFully(data);
|
||||
|
||||
DebugMessage request = (DebugMessage) 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 DebugMessage(DebugMessageType.reset));
|
||||
|
||||
debugSupport.disconnect();
|
||||
} finally {
|
||||
try {
|
||||
redirectOutputStream.close();
|
||||
} catch (IOException ignore) {}
|
||||
|
||||
// restore the print output
|
||||
BaseLib.restoreStandardOutput();
|
||||
|
||||
dispose();
|
||||
}
|
||||
}
|
||||
|
||||
public void handleRequest(DebugMessage request) {
|
||||
if (TRACE) {
|
||||
System.out.println("SERVER handling request: " + request.toString());
|
||||
}
|
||||
|
||||
debugSupport.handleRequest(request);
|
||||
}
|
||||
|
||||
public void notifyDebugEvent(DebugMessage event) {
|
||||
if (TRACE)
|
||||
System.out.println("SERVER sending event: " + event.toString());
|
||||
|
||||
try {
|
||||
byte[] data = SerializationHelper.serialize(event);
|
||||
eventWriter.writeInt(data.length);
|
||||
eventWriter.write(data);
|
||||
eventWriter.flush();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void dispose() {
|
||||
if ( this.isDisposed ) return;
|
||||
|
||||
this.isDisposed = true;
|
||||
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) {}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,161 +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.net.j2se;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
|
||||
import org.luaj.debug.DebugMessage;
|
||||
import org.luaj.debug.net.DebugNetSupportBase;
|
||||
|
||||
/**
|
||||
* J2SE version of DebugNetSupportBase. The luaj-vm opens a port accepting the debug
|
||||
* client connections. The current implementation allows the vm to accept one
|
||||
* and only one debug client connection at any time.
|
||||
*/
|
||||
public class DebugSupportImpl extends DebugNetSupportBase {
|
||||
|
||||
protected int numClientConnectionsAllowed;
|
||||
protected int numClientConnections = 0;
|
||||
protected ServerSocket serverSocket;
|
||||
protected int debugPort;
|
||||
protected ClientConnectionTask clientConnectionTask;
|
||||
|
||||
/**
|
||||
* Creates an instance of DebugNetSupportBase 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 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;
|
||||
}
|
||||
|
||||
public synchronized void stop() {
|
||||
setState(STOPPED);
|
||||
if (clientConnectionTask != null) {
|
||||
disconnect();
|
||||
}
|
||||
dispose();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.luaj.debug.event.DebugEventListener#notifyDebugEvent(org.luaj.debug.DebugMessage)
|
||||
*/
|
||||
public void notifyDebugEvent(DebugMessage event) {
|
||||
if (clientConnectionTask != null) {
|
||||
clientConnectionTask.notifyDebugEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void disconnect() {
|
||||
clientConnectionTask.disconnect();
|
||||
clientConnectionTask = null;
|
||||
}
|
||||
|
||||
public void acceptClientConnection() throws IOException {
|
||||
try {
|
||||
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();
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
dispose();
|
||||
}
|
||||
}
|
||||
|
||||
protected synchronized void dispose() {
|
||||
if (this.clientConnectionTask != null) {
|
||||
clientConnectionTask.dispose();
|
||||
clientConnectionTask = null;
|
||||
}
|
||||
|
||||
if (this.serverSocket != null) {
|
||||
try {
|
||||
serverSocket.close();
|
||||
serverSocket = null;
|
||||
} catch (IOException e) {}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,19 +3,14 @@ package org.luaj.platform;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
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.lib.MathLib;
|
||||
import org.luaj.lib.j2se.LuajavaLib;
|
||||
import org.luaj.vm.DebugNetSupport;
|
||||
import org.luaj.vm.LDouble;
|
||||
import org.luaj.vm.LNumber;
|
||||
import org.luaj.vm.LValue;
|
||||
import org.luaj.vm.LuaErrorException;
|
||||
import org.luaj.vm.LuaState;
|
||||
import org.luaj.vm.Platform;
|
||||
|
||||
@@ -29,11 +24,6 @@ public class J2sePlatform extends Platform {
|
||||
return new InputStreamReader(inputStream);
|
||||
}
|
||||
|
||||
public DebugNetSupport getDebugSupport() throws IOException {
|
||||
DebugNetSupport debugNetSupport = new DebugSupportImpl(getDebugPort());
|
||||
return debugNetSupport;
|
||||
}
|
||||
|
||||
public String getProperty(String propertyName) {
|
||||
return System.getProperty(propertyName);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user