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:
Shu Lei
2007-11-30 23:47:44 +00:00
parent 0db9925ee9
commit 96864694de
5 changed files with 203 additions and 93 deletions

View File

@@ -70,6 +70,9 @@ import org.luaj.lib.TableLib;
*/ */
public class LuaState extends Lua { 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 */ /* thread status; 0 is OK */
private static final int LUA_YIELD = 1; private static final int LUA_YIELD = 1;
private static final int LUA_ERRRUN = 2; 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 * does all memory allocation for this state through this function. The
* second argument, <code>ud</code>, is an opaque pointer that Lua simply * second argument, <code>ud</code>, is an opaque pointer that Lua simply
* passes to the allocator in every call. * passes to the allocator in every call.
*
* @deprecated As of version 0.10, replaced by {@link #newState()}
*/ */
public LuaState() { public LuaState() {
_G = new LTable(); _G = new LTable();
@@ -119,6 +124,38 @@ public class LuaState extends Lua {
_G = globals; _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: * Install the standard set of libraries used by most implementations:
* BaseLib, CoroutineLib, MathLib, PackageLib, TableLib, StringLib * BaseLib, CoroutineLib, MathLib, PackageLib, TableLib, StringLib

View File

@@ -21,10 +21,15 @@
******************************************************************************/ ******************************************************************************/
package org.luaj.vm; package org.luaj.vm;
import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.io.Reader; 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. * Singleton to manage platform-specific behaviors.
* *
@@ -46,9 +51,31 @@ abstract public class Platform {
public Reader createReader(InputStream inputStream) { public Reader createReader(InputStream inputStream) {
return new InputStreamReader(inputStream); return new InputStreamReader(inputStream);
} }
public InputStream openFile(String fileName) { public InputStream openFile(String fileName) {
return getClass().getResourceAsStream("/" + 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; return instance;
@@ -77,4 +104,18 @@ abstract public class Platform {
* @return Reader instance to use for character input * @return Reader instance to use for character input
*/ */
abstract public Reader createReader( InputStream inputStream ); 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;
} }

View File

@@ -45,9 +45,14 @@ import org.luaj.vm.LocVars;
import org.luaj.vm.Lua; import org.luaj.vm.Lua;
import org.luaj.vm.LuaErrorException; import org.luaj.vm.LuaErrorException;
import org.luaj.vm.LuaState; import org.luaj.vm.LuaState;
import org.luaj.vm.Platform;
public class DebugLuaState extends LuaState implements DebugRequestListener { 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")); private static final boolean TRACE = (null != System.getProperty("TRACE"));
// stepping constants and stepping state // stepping constants and stepping state
@@ -68,9 +73,35 @@ public class DebugLuaState extends LuaState implements DebugRequestListener {
protected DebugSupport debugSupport; protected DebugSupport debugSupport;
protected LuaErrorException lastError; protected LuaErrorException lastError;
/**
* Creates an instance of DebugLuaState.
*
* @deprecated As of version 0.10, replaced by {@link #LuaState.newState()}
*/
public DebugLuaState() {} 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 { throws IOException {
if (debugSupport == null) { if (debugSupport == null) {
throw new IllegalArgumentException("DebugSupport cannot be null"); throw new IllegalArgumentException("DebugSupport cannot be null");
@@ -394,18 +425,19 @@ public class DebugLuaState extends LuaState implements DebugRequestListener {
synchronized (this) { synchronized (this) {
if (exiting) return; if (exiting) return;
if (this.debugSupport == null) { if (this.debugSupport != null) {
throw new IllegalStateException(
"DebugSupport must be defined.");
}
DebugMessage event = new DebugMessage(DebugMessageType.terminated); DebugMessage event = new DebugMessage(DebugMessageType.terminated);
debugSupport.notifyDebugEvent(event); debugSupport.notifyDebugEvent(event);
}
exit(); exit();
if (this.debugSupport != null) {
debugSupport.stop(); debugSupport.stop();
debugSupport = null; debugSupport = null;
} }
} }
}
public void disconnect(int connectionId) { public void disconnect(int connectionId) {
if (this.debugSupport == null) { if (this.debugSupport == null) {

View File

@@ -28,8 +28,6 @@ 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.net.DebugSupport;
import org.luaj.debug.net.j2se.DebugSupportImpl;
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;
@@ -83,6 +81,8 @@ public class StandardLuaJVM {
} }
this.isDebugMode = true; this.isDebugMode = true;
System.setProperty(LuaState.PROPERTY_LUAJ_DEBUG, "true");
String debugOptions = args[0]; String debugOptions = args[0];
debugOptions = debugOptions.substring(2); // remove '-D' debugOptions = debugOptions.substring(2); // remove '-D'
String[] options = debugOptions.split(","); String[] options = debugOptions.split(",");
@@ -91,6 +91,7 @@ public class StandardLuaJVM {
String portString = options[i].substring(CMD_LINE_DEBUG_OPTION_PORT.length()); String portString = options[i].substring(CMD_LINE_DEBUG_OPTION_PORT.length());
try { try {
this.debugPort = Integer.parseInt(portString); this.debugPort = Integer.parseInt(portString);
System.setProperty(DebugLuaState.PROPERTY_LUAJ_DEBUG_PORT, String.valueOf(debugPort));
if (this.debugPort <= 0) { if (this.debugPort <= 0) {
throw new ParseException( throw new ParseException(
"Invalid debug port: it must be greater than zero."); "Invalid debug port: it must be greater than zero.");
@@ -105,7 +106,8 @@ public class StandardLuaJVM {
!suspendOnStartStr.equalsIgnoreCase("false")) { !suspendOnStartStr.equalsIgnoreCase("false")) {
throw new ParseException("invalid debug flag: suspendOnStart"); 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 { } else {
throw new ParseException("Invalid command line argument: " + debugOptions); throw new ParseException("Invalid command line argument: " + debugOptions);
} }
@@ -168,10 +170,28 @@ public class StandardLuaJVM {
public void run() { public void run() {
try { try {
if (isDebug()) { // new lua debug state
doDebug(); state = LuaState.newState();
} else { init(state);
doRun();
// 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) { } catch (LuaErrorException e) {
System.err.println("Error: " + e.getMessage()); System.err.println("Error: " + e.getMessage());
@@ -194,62 +214,6 @@ public class StandardLuaJVM {
LuaC.install(); 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. * Parses the command line arguments and executes/debugs the lua program.
* @param args -- command line arguments: * @param args -- command line arguments:

View File

@@ -21,14 +21,15 @@
******************************************************************************/ ******************************************************************************/
package org.luaj.debug.j2se; package org.luaj.debug.j2se;
import java.io.IOException;
import java.net.URL; import java.net.URL;
import java.util.Properties;
import org.luaj.debug.j2se.StandardLuaJVM;
import org.luaj.debug.j2se.StandardLuaJVM.ParseException;
import junit.framework.TestCase; 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. * Sanity test for StandardLuaJVM.
*/ */
@@ -88,7 +89,7 @@ public class LuaJVMTest extends TestCase {
vm = new StandardLuaJVM(); vm = new StandardLuaJVM();
try { try {
vm.parse(args); vm.parse(args);
assertFalse(1044 == vm.getDebugPort()); assertTrue(1044 == vm.getDebugPort());
assertFalse(true == vm.getSuspendOnStart()); assertFalse(true == vm.getSuspendOnStart());
assertEquals("dummy.lua", vm.getScript()); assertEquals("dummy.lua", vm.getScript());
} catch (ParseException e) { } catch (ParseException e) {
@@ -134,6 +135,17 @@ public class LuaJVMTest extends TestCase {
fail("Should never reach this line."); 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" }; args = new String[] { "-DsuspendOnStart=true,port=1044", "dummy.lua" };
vm = new StandardLuaJVM(); vm = new StandardLuaJVM();
try { try {
@@ -169,13 +181,37 @@ public class LuaJVMTest extends TestCase {
} }
public void testRun() { 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", String[] tests = new String[] { "autoload", "boolean", "calls",
"coercions", "compare", "math", "mathlib", "metatables", "coercions", "compare", "math", "mathlib", "metatables",
"select", "setlist", "swingapp", "test1", "test2", "test3", "select", "setlist", "swingapp", "test1", "test2", "test3",
"test4", "test5", "test6", "test7", "type", "upvalues", "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++) { for (int i = 0; i < tests.length; i++) {
String test = tests[i]; String test = tests[i];
System.out.println("==> running test: " + test + ".lua"); System.out.println("==> running test: " + test + ".lua");