added a factory method to LuaState to dynamically create LuaState or DebugLuaState depending on the presence of the platform debug properties
This commit is contained in:
@@ -70,6 +70,9 @@ import org.luaj.lib.TableLib;
|
||||
*/
|
||||
public class LuaState extends Lua {
|
||||
|
||||
public static final String PROPERTY_LUAJ_DEBUG = "Luaj-Debug";
|
||||
protected static final String DEBUG_CLASS_NAME = "org.luaj.debug.DebugLuaState";
|
||||
|
||||
/* thread status; 0 is OK */
|
||||
private static final int LUA_YIELD = 1;
|
||||
private static final int LUA_ERRRUN = 2;
|
||||
@@ -109,6 +112,8 @@ public class LuaState extends Lua {
|
||||
* does all memory allocation for this state through this function. The
|
||||
* second argument, <code>ud</code>, is an opaque pointer that Lua simply
|
||||
* passes to the allocator in every call.
|
||||
*
|
||||
* @deprecated As of version 0.10, replaced by {@link #newState()}
|
||||
*/
|
||||
public LuaState() {
|
||||
_G = new LTable();
|
||||
@@ -119,6 +124,38 @@ public class LuaState extends Lua {
|
||||
_G = globals;
|
||||
}
|
||||
|
||||
/**
|
||||
* Factory method to return an instance of LuaState. If debug property is
|
||||
* present, it will create a DebugLuaState instance.
|
||||
* @return
|
||||
*/
|
||||
public static LuaState newState() {
|
||||
String isDebugStr
|
||||
= Platform.getInstance().getProperty(PROPERTY_LUAJ_DEBUG, "false");
|
||||
boolean isDebug = Boolean.parseBoolean(isDebugStr);
|
||||
|
||||
LuaState vm = null;
|
||||
if ( isDebug ) {
|
||||
try {
|
||||
vm = (LuaState) Class.forName( DEBUG_CLASS_NAME ).newInstance();
|
||||
} catch (Exception e) {
|
||||
System.out.println("Warning: no debug support, " + e );
|
||||
}
|
||||
}
|
||||
|
||||
if ( vm == null )
|
||||
vm = new LuaState();
|
||||
|
||||
vm.init();
|
||||
|
||||
return vm;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs the initialization.
|
||||
*/
|
||||
public void init() {}
|
||||
|
||||
/**
|
||||
* Install the standard set of libraries used by most implementations:
|
||||
* BaseLib, CoroutineLib, MathLib, PackageLib, TableLib, StringLib
|
||||
|
||||
@@ -21,10 +21,15 @@
|
||||
******************************************************************************/
|
||||
package org.luaj.vm;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.Reader;
|
||||
|
||||
import org.luaj.debug.DebugLuaState;
|
||||
import org.luaj.debug.net.DebugSupport;
|
||||
import org.luaj.debug.net.j2se.DebugSupportImpl;
|
||||
|
||||
/**
|
||||
* Singleton to manage platform-specific behaviors.
|
||||
*
|
||||
@@ -41,18 +46,40 @@ abstract public class Platform {
|
||||
* InputStreamReader class.
|
||||
*/
|
||||
public static Platform getInstance() {
|
||||
if ( instance == null ) {
|
||||
instance = new Platform() {
|
||||
public Reader createReader(InputStream inputStream) {
|
||||
return new InputStreamReader(inputStream);
|
||||
}
|
||||
public InputStream openFile(String fileName) {
|
||||
return getClass().getResourceAsStream("/"+fileName);
|
||||
}
|
||||
};
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
if (instance == null) {
|
||||
instance = new 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,
|
||||
String defaultValue) {
|
||||
return System.getProperty(propertyName, defaultValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a J2SE DebugSupport instance.
|
||||
*/
|
||||
public DebugSupport getDebugSupport() throws IOException {
|
||||
String portStr = getProperty(DebugLuaState.PROPERTY_LUAJ_DEBUG_PORT, "-1");
|
||||
try {
|
||||
int port = Integer.parseInt(portStr);
|
||||
return new DebugSupportImpl(port);
|
||||
} catch (NumberFormatException e) {
|
||||
throw new IOException("Bad port number: " + portStr);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the Platform instance.
|
||||
@@ -77,4 +104,18 @@ abstract public class Platform {
|
||||
* @return Reader instance to use for character input
|
||||
*/
|
||||
abstract public Reader createReader( InputStream inputStream );
|
||||
|
||||
/**
|
||||
* Returns the value for the given platform property.
|
||||
* @param propertyName Property name
|
||||
* @param defaultValue Default property value
|
||||
* @return Property value
|
||||
*/
|
||||
abstract public String getProperty(String propertyName, String defaultValue);
|
||||
|
||||
/**
|
||||
* Returns an platform dependent DebugSupport instance.
|
||||
* @return an plaform dependent DebugSupport instance.
|
||||
*/
|
||||
abstract public DebugSupport getDebugSupport() throws IOException;
|
||||
}
|
||||
|
||||
@@ -45,9 +45,14 @@ import org.luaj.vm.LocVars;
|
||||
import org.luaj.vm.Lua;
|
||||
import org.luaj.vm.LuaErrorException;
|
||||
import org.luaj.vm.LuaState;
|
||||
import org.luaj.vm.Platform;
|
||||
|
||||
|
||||
public class DebugLuaState extends LuaState implements DebugRequestListener {
|
||||
public static final String PROPERTY_LUAJ_DEBUG_SUSPEND_AT_START = "Luaj-Debug-SuspendAtStart";
|
||||
public static final String PROPERTY_LUAJ_DEBUG_HOST = "Luaj-Debug-Host";
|
||||
public static final String PROPERTY_LUAJ_DEBUG_PORT = "Luaj-Debug-Port";
|
||||
|
||||
private static final boolean TRACE = (null != System.getProperty("TRACE"));
|
||||
|
||||
// stepping constants and stepping state
|
||||
@@ -68,9 +73,35 @@ public class DebugLuaState extends LuaState implements DebugRequestListener {
|
||||
protected DebugSupport debugSupport;
|
||||
protected LuaErrorException lastError;
|
||||
|
||||
/**
|
||||
* Creates an instance of DebugLuaState.
|
||||
*
|
||||
* @deprecated As of version 0.10, replaced by {@link #LuaState.newState()}
|
||||
*/
|
||||
public DebugLuaState() {}
|
||||
|
||||
public void setDebugSupport(DebugSupport debugSupport)
|
||||
public void init() {
|
||||
Platform platform = Platform.getInstance();
|
||||
|
||||
// set if the vm should be suspended at start
|
||||
String suspendOnStartStr = platform.getProperty(PROPERTY_LUAJ_DEBUG_SUSPEND_AT_START, "false");
|
||||
boolean bSuspendOnStart = Boolean.parseBoolean(suspendOnStartStr);
|
||||
setSuspendAtStart(bSuspendOnStart);
|
||||
|
||||
// set up the debug networking support
|
||||
try {
|
||||
DebugSupport debugSupport = platform.getDebugSupport();
|
||||
if (debugSupport != null)
|
||||
setDebugSupport(debugSupport);
|
||||
else
|
||||
System.out.println("Warning: DebugSupport is not implemented.");
|
||||
} 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());
|
||||
}
|
||||
}
|
||||
|
||||
protected void setDebugSupport(DebugSupport debugSupport)
|
||||
throws IOException {
|
||||
if (debugSupport == null) {
|
||||
throw new IllegalArgumentException("DebugSupport cannot be null");
|
||||
@@ -394,16 +425,17 @@ public class DebugLuaState extends LuaState implements DebugRequestListener {
|
||||
synchronized (this) {
|
||||
if (exiting) return;
|
||||
|
||||
if (this.debugSupport == null) {
|
||||
throw new IllegalStateException(
|
||||
"DebugSupport must be defined.");
|
||||
if (this.debugSupport != null) {
|
||||
DebugMessage event = new DebugMessage(DebugMessageType.terminated);
|
||||
debugSupport.notifyDebugEvent(event);
|
||||
}
|
||||
|
||||
DebugMessage event = new DebugMessage(DebugMessageType.terminated);
|
||||
debugSupport.notifyDebugEvent(event);
|
||||
exit();
|
||||
debugSupport.stop();
|
||||
debugSupport = null;
|
||||
|
||||
if (this.debugSupport != null) {
|
||||
debugSupport.stop();
|
||||
debugSupport = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -28,8 +28,6 @@ import java.io.InputStream;
|
||||
|
||||
import org.luaj.compiler.LuaC;
|
||||
import org.luaj.debug.DebugLuaState;
|
||||
import org.luaj.debug.net.DebugSupport;
|
||||
import org.luaj.debug.net.j2se.DebugSupportImpl;
|
||||
import org.luaj.lib.j2se.LuajavaLib;
|
||||
import org.luaj.vm.LClosure;
|
||||
import org.luaj.vm.LPrototype;
|
||||
@@ -83,6 +81,8 @@ public class StandardLuaJVM {
|
||||
}
|
||||
|
||||
this.isDebugMode = true;
|
||||
System.setProperty(LuaState.PROPERTY_LUAJ_DEBUG, "true");
|
||||
|
||||
String debugOptions = args[0];
|
||||
debugOptions = debugOptions.substring(2); // remove '-D'
|
||||
String[] options = debugOptions.split(",");
|
||||
@@ -91,6 +91,7 @@ public class StandardLuaJVM {
|
||||
String portString = options[i].substring(CMD_LINE_DEBUG_OPTION_PORT.length());
|
||||
try {
|
||||
this.debugPort = Integer.parseInt(portString);
|
||||
System.setProperty(DebugLuaState.PROPERTY_LUAJ_DEBUG_PORT, String.valueOf(debugPort));
|
||||
if (this.debugPort <= 0) {
|
||||
throw new ParseException(
|
||||
"Invalid debug port: it must be greater than zero.");
|
||||
@@ -105,7 +106,8 @@ public class StandardLuaJVM {
|
||||
!suspendOnStartStr.equalsIgnoreCase("false")) {
|
||||
throw new ParseException("invalid debug flag: suspendOnStart");
|
||||
}
|
||||
this.bSuspendOnStart = Boolean.valueOf(suspendOnStartStr).booleanValue();
|
||||
this.bSuspendOnStart = Boolean.parseBoolean(suspendOnStartStr);
|
||||
System.setProperty(DebugLuaState.PROPERTY_LUAJ_DEBUG_SUSPEND_AT_START, suspendOnStartStr);
|
||||
} else {
|
||||
throw new ParseException("Invalid command line argument: " + debugOptions);
|
||||
}
|
||||
@@ -168,10 +170,28 @@ public class StandardLuaJVM {
|
||||
|
||||
public void run() {
|
||||
try {
|
||||
if (isDebug()) {
|
||||
doDebug();
|
||||
} else {
|
||||
doRun();
|
||||
// new lua debug state
|
||||
state = LuaState.newState();
|
||||
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 = new LClosure(p, 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());
|
||||
@@ -194,62 +214,6 @@ public class StandardLuaJVM {
|
||||
LuaC.install();
|
||||
}
|
||||
|
||||
protected void doRun() throws IOException {
|
||||
|
||||
// new lua state
|
||||
state = new LuaState();
|
||||
init(state);
|
||||
|
||||
// convert args to lua
|
||||
String[] scriptArgs = getScriptArgs();
|
||||
int numOfScriptArgs = (scriptArgs == null) ? 0 : scriptArgs.length;
|
||||
LValue[] vargs = new LValue[numOfScriptArgs];
|
||||
for (int i = 0; i < numOfScriptArgs; i++) {
|
||||
vargs[i] = new LString(getScriptArgs()[i]);
|
||||
}
|
||||
|
||||
// load the Lua file
|
||||
InputStream is = new FileInputStream(new File(getScript()));
|
||||
LPrototype p = LoadState.undump(state, is, getScript());
|
||||
|
||||
// create closure and execute
|
||||
LClosure c = new LClosure(state, p);
|
||||
state.doCall(c, vargs);
|
||||
}
|
||||
|
||||
protected void doDebug() throws IOException {
|
||||
// new lua debug state
|
||||
state = new DebugLuaState();
|
||||
init(state);
|
||||
|
||||
// load the Lua file
|
||||
InputStream is = new FileInputStream(new File(getScript()));
|
||||
LPrototype p = LoadState.undump(state, is, getScript());
|
||||
|
||||
// set up debug support if the file is successfully loaded
|
||||
DebugSupport debugSupport = new DebugSupportImpl(getDebugPort());
|
||||
getDebugState().setSuspendAtStart(getSuspendOnStart());
|
||||
getDebugState().setDebugSupport(debugSupport);
|
||||
|
||||
// create closure and execute
|
||||
final LClosure c = new LClosure(p, 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 {
|
||||
getDebugState().doCall(c, vargs);
|
||||
} finally {
|
||||
getDebugState().stop();
|
||||
}
|
||||
}
|
||||
|
||||
private DebugLuaState getDebugState() {
|
||||
return (DebugLuaState) state;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the command line arguments and executes/debugs the lua program.
|
||||
* @param args -- command line arguments:
|
||||
|
||||
@@ -21,14 +21,15 @@
|
||||
******************************************************************************/
|
||||
package org.luaj.debug.j2se;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
|
||||
import org.luaj.debug.j2se.StandardLuaJVM;
|
||||
import org.luaj.debug.j2se.StandardLuaJVM.ParseException;
|
||||
import java.util.Properties;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.luaj.debug.DebugLuaState;
|
||||
import org.luaj.debug.j2se.StandardLuaJVM.ParseException;
|
||||
import org.luaj.vm.LuaState;
|
||||
|
||||
/**
|
||||
* Sanity test for StandardLuaJVM.
|
||||
*/
|
||||
@@ -88,7 +89,7 @@ public class LuaJVMTest extends TestCase {
|
||||
vm = new StandardLuaJVM();
|
||||
try {
|
||||
vm.parse(args);
|
||||
assertFalse(1044 == vm.getDebugPort());
|
||||
assertTrue(1044 == vm.getDebugPort());
|
||||
assertFalse(true == vm.getSuspendOnStart());
|
||||
assertEquals("dummy.lua", vm.getScript());
|
||||
} catch (ParseException e) {
|
||||
@@ -134,6 +135,17 @@ public class LuaJVMTest extends TestCase {
|
||||
fail("Should never reach this line.");
|
||||
}
|
||||
|
||||
args = new String[] { "-Dport=1044,suspendOnStart=True", "dummy.lua" };
|
||||
vm = new StandardLuaJVM();
|
||||
try {
|
||||
vm.parse(args);
|
||||
assertEquals(1044, vm.getDebugPort());
|
||||
assertEquals(true, vm.getSuspendOnStart());
|
||||
assertEquals("dummy.lua", vm.getScript());
|
||||
} catch (ParseException e) {
|
||||
fail("Should never reach this line.");
|
||||
}
|
||||
|
||||
args = new String[] { "-DsuspendOnStart=true,port=1044", "dummy.lua" };
|
||||
vm = new StandardLuaJVM();
|
||||
try {
|
||||
@@ -169,13 +181,37 @@ public class LuaJVMTest extends TestCase {
|
||||
}
|
||||
|
||||
public void testRun() {
|
||||
Properties props = System.getProperties();
|
||||
props.remove(LuaState.PROPERTY_LUAJ_DEBUG);
|
||||
props.remove(DebugLuaState.PROPERTY_LUAJ_DEBUG_HOST);
|
||||
props.remove(DebugLuaState.PROPERTY_LUAJ_DEBUG_PORT);
|
||||
props.remove(DebugLuaState.PROPERTY_LUAJ_DEBUG_SUSPEND_AT_START);
|
||||
System.setProperties(props);
|
||||
|
||||
String[] tests = new String[] { "autoload", "boolean", "calls",
|
||||
"coercions", "compare", "math", "mathlib", "metatables",
|
||||
"select", "setlist", "swingapp", "test1", "test2", "test3",
|
||||
"test4", "test5", "test6", "test7", "type", "upvalues",
|
||||
// "strlib"
|
||||
"strlib"
|
||||
};
|
||||
doRun(tests);
|
||||
}
|
||||
|
||||
public void testDebugRun() {
|
||||
Properties props = System.getProperties();
|
||||
props.setProperty(LuaState.PROPERTY_LUAJ_DEBUG, "true");
|
||||
props.setProperty(DebugLuaState.PROPERTY_LUAJ_DEBUG_PORT, "1999");
|
||||
System.setProperties(props);
|
||||
|
||||
String[] tests = new String[] { "boolean", "calls",
|
||||
"coercions", "compare", "math", "mathlib", "metatables",
|
||||
"select", "setlist", "swingapp", "test1", "test2", "test3",
|
||||
"test4", "test5", "test6", "test7", "type", "upvalues"
|
||||
};
|
||||
doRun(tests);
|
||||
}
|
||||
|
||||
private void doRun(String[] tests) {
|
||||
for (int i = 0; i < tests.length; i++) {
|
||||
String test = tests[i];
|
||||
System.out.println("==> running test: " + test + ".lua");
|
||||
|
||||
Reference in New Issue
Block a user