From c12eeb6315500334d0a244d87f8a88936ee04959 Mon Sep 17 00:00:00 2001 From: Bob Jamison Date: Tue, 11 Mar 2008 21:13:53 +0000 Subject: Got initial JS execution working (bzr r5057) --- src/bind/java/org/inkscape/cmn/ScriptRunner.java | 211 ++++++++++++++++++----- src/bind/javabind-private.h | 2 + src/bind/javabind.cpp | 179 ++++++++++++++++--- src/bind/javabind.h | 29 +++- 4 files changed, 348 insertions(+), 73 deletions(-) (limited to 'src/bind') diff --git a/src/bind/java/org/inkscape/cmn/ScriptRunner.java b/src/bind/java/org/inkscape/cmn/ScriptRunner.java index a128af734..d05afd2e3 100644 --- a/src/bind/java/org/inkscape/cmn/ScriptRunner.java +++ b/src/bind/java/org/inkscape/cmn/ScriptRunner.java @@ -25,6 +25,7 @@ package org.inkscape.cmn; import javax.script.*; +import java.util.List; import java.io.FileReader; import java.io.PrintStream; import java.io.OutputStream; @@ -37,9 +38,40 @@ import javax.swing.JOptionPane; */ public class ScriptRunner { +/** + * Pointer back to the BinderyImpl C++ object that launched me + */ long backPtr; +/** + * The script engine manager that we want to use + */ +ScriptEngineManager scriptEngineManager; + + +//######################################################################## +//# MESSSAGES +//######################################################################## +static void err(String message) +{ + System.err.println("ScriptRunner err:" + message); +} + +static void msg(String message) +{ + System.out.println("ScriptRunner:" + message); +} +static void trace(String message) +{ + log.println("ScriptRunner:" + message); +} + + + +//######################################################################## +//# REDIRECT STDERR / STDOUT +//######################################################################## /** * Redirect stdout */ @@ -55,7 +87,6 @@ public void write(int b) } - /** * Redirect stderr */ @@ -71,14 +102,27 @@ public void write(int b) } +/** + * A logging stream + */ +static PrintStream log; +public native void logWrite(long ptr, int b); +class LogStream extends OutputStream +{ -static void err(String message) +public void write(int b) { - JOptionPane.showMessageDialog(null, message, - "Script Error", JOptionPane.ERROR_MESSAGE); + logWrite(backPtr, b); } +} + + +//######################################################################## +//# RUN +//######################################################################## + /** * Run a script buffer @@ -87,12 +131,16 @@ static void err(String message) * @param str the script buffer to execute * @return true if successful, else false */ -public boolean run(String lang, String str) +public boolean doRun(String lang, String str) { - ScriptEngineManager factory = new ScriptEngineManager(); // create JavaScript engine - ScriptEngine engine = factory.getEngineByName(lang); - // evaluate JavaScript code from given file - specified by first argument + ScriptEngine engine = scriptEngineManager.getEngineByName(lang); + if (engine == null) + { + err("doRun: cannot find script engine '" + lang + "'"); + return false; + } + //execute script from buffer try { engine.eval(str); @@ -100,10 +148,41 @@ public boolean run(String lang, String str) catch (javax.script.ScriptException e) { err("Executing script: " + e); + e.printStackTrace(); } return true; } +/** + * Run a script buffer + * + * @param backPtr pointer back to the C context that called this + * @param lang the scripting language to run + * @param str the script buffer to execute + * @return true if successful, else false + */ +public static boolean run(String lang, String str) +{ + //wrap whole thing in try/catch, since this will + //likely be called from C + try + { + ScriptRunner runner = getInstance(); + if (runner == null) + { + err("ScriptRunner not initialized"); + return false; + } + return runner.doRun(lang, str); + } + catch (Exception e) + { + err("run :" + e); + e.printStackTrace(); + return false; + } +} + /** * Run a script file @@ -112,12 +191,16 @@ public boolean run(String lang, String str) * @param fname the script file to execute * @return true if successful, else false */ -public boolean runFile(String lang, String fname) +public boolean doRunFile(String lang, String fname) { - ScriptEngineManager factory = new ScriptEngineManager(); // create JavaScript engine - ScriptEngine engine = factory.getEngineByName(lang); - // evaluate JavaScript code from given file - specified by first argument + ScriptEngine engine = scriptEngineManager.getEngineByName(lang); + if (engine == null) + { + err("doRunFile: cannot find script engine '" + lang + "'"); + return false; + } + //try opening file and feeding into engine FileReader in = null; boolean ret = true; try @@ -152,58 +235,104 @@ public boolean runFile(String lang, String fname) /** - * Constructor + * Run a script file + * * @param backPtr pointer back to the C context that called this + * @param lang the scripting language to run + * @param fname the script file to execute + * @return true if successful, else false */ -public ScriptRunner(long backPtr) +public static boolean runFile(String lang, String fname) { - this.backPtr = backPtr; - System.setOut(new PrintStream(new StdOutStream())); - System.setErr(new PrintStream(new StdErrStream())); + //wrap whole thing in try/catch, since this will + //likely be called from C + try + { + ScriptRunner runner = getInstance(); + if (runner == null) + { + err("ScriptRunner not initialized"); + return false; + } + return runner.doRunFile(lang, fname); + } + catch (Exception e) + { + err("run :" + e); + return false; + } } -private static ScriptRunner _instance = null; +//######################################################################## +//# CONSTRUCTOR +//######################################################################## + -public static ScriptRunner getInstance(long backPtr) +private static ScriptRunner _instance = null; +public static ScriptRunner getInstance() { - if (_instance == null) - _instance = new ScriptRunner(backPtr); return _instance; } - -/** - * Run a script buffer - * - * @param backPtr pointer back to the C context that called this - * @param lang the scripting language to run - * @param str the script buffer to execute - * @return true if successful, else false - */ -public static boolean run(long ptr, String lang, String str) +private void listFactories() { - ScriptRunner runner = getInstance(ptr); - return runner.run(lang, str); + List factories = + scriptEngineManager.getEngineFactories(); + for (ScriptEngineFactory factory: factories) + { + log.println("ScriptEngineFactory Info"); + String engName = factory.getEngineName(); + String engVersion = factory.getEngineVersion(); + String langName = factory.getLanguageName(); + String langVersion = factory.getLanguageVersion(); + log.printf("\tScript Engine: %s (%s)\n", + engName, engVersion); + List engNames = factory.getNames(); + for(String name: engNames) + { + log.printf("\tEngine Alias: %s\n", name); + } + log.printf("\tLanguage: %s (%s)\n", + langName, langVersion); + } } + /** - * Run a script file - * + * Constructor * @param backPtr pointer back to the C context that called this - * @param lang the scripting language to run - * @param fname the script file to execute - * @return true if successful, else false */ -public static boolean runFile(long ptr, String lang, String fname) +public ScriptRunner(long backPtr) { - ScriptRunner runner = getInstance(ptr); - return runner.runFile(lang, fname); + /** + * Set up the output, error, and logging stream + */ + System.setOut(new PrintStream(new StdOutStream())); + System.setErr(new PrintStream(new StdErrStream())); + log = new PrintStream(new LogStream()); + + //Point back to C++ object + this.backPtr = backPtr; + + //Start up the factory + scriptEngineManager = new ScriptEngineManager(); + listFactories(); + _instance = this; } +static +{ + +} } +//######################################################################## +//# E N D O F F I L E +//######################################################################## + + diff --git a/src/bind/javabind-private.h b/src/bind/javabind-private.h index ce595fa85..f76118c28 100644 --- a/src/bind/javabind-private.h +++ b/src/bind/javabind-private.h @@ -63,6 +63,8 @@ public: virtual bool doBinding(); + virtual bool setupScriptRunner(); + static JavaBinderyImpl *getInstance(); diff --git a/src/bind/javabind.cpp b/src/bind/javabind.cpp index 3d68bdc15..5a8700633 100644 --- a/src/bind/javabind.cpp +++ b/src/bind/javabind.cpp @@ -285,40 +285,115 @@ static bool getRegistryString(HKEY root, const char *keyName, } +static String cleanPath(const String &s) +{ + String buf; + for (unsigned int i=0 ; i=0) + { + //msg("found"); + libname = jpath; + found = true; + break; + } + } + } + + //not at JAVA_HOME. check the registry + if (!found) + { + char verbuf[16]; + char regpath[80]; + strcpy(regpath, "SOFTWARE\\JavaSoft\\Java Runtime Environment"); + bool ret = getRegistryString(HKEY_LOCAL_MACHINE, + regpath, "CurrentVersion", verbuf, 15); + if (!ret) + { + msg("JVM CurrentVersion not found in registry at '%s'", regpath); + } + else + { + strcat(regpath, "\\"); + strcat(regpath, verbuf); + //msg("reg path: %s\n", regpath); + char valbuf[80]; + ret = getRegistryString(HKEY_LOCAL_MACHINE, + regpath, "RuntimeLib", valbuf, 79); + if (ret) + { + found = true; + libname = valbuf; + } + else + { + msg("JVM RuntimeLib not found in registry at '%s'", + regpath); + } + } } - strcat(regpath, "\\"); - strcat(regpath, verbuf); - //msg("reg path: %s\n", regpath); - char libname[80]; - ret = getRegistryString(HKEY_LOCAL_MACHINE, - regpath, "RuntimeLib", libname, 79); - if (!ret) + + if (!found) { - err("Current JVM RuntimeLib not found in registry\n"); + err("JVM not found at JAVA_HOME or in registry"); return NULL; } - //msg("jvm path: %s\n", libname); - HMODULE lib = LoadLibrary(libname); + + /** + * If we are here, then we seem to have a valid path for jvm.dll + * Give it a try + */ + msg("getCreateVMFunc: Loading JVM: %s", libname.c_str()); + HMODULE lib = LoadLibrary(libname.c_str()); if (!lib) { - err("Java VM not found at '%s'", libname); + err("Java VM not found at '%s'", libname.c_str()); return NULL; } CreateVMFunc createVM = (CreateVMFunc)GetProcAddress(lib, "JNI_CreateJavaVM"); if (!createVM) { - err("Could not find 'JNI_CreateJavaVM' in shared library"); + err("Could not find 'JNI_CreateJavaVM' in shared library '%s'", + libname.c_str()); return NULL; } return createVM; @@ -451,6 +526,7 @@ static CreateVMFunc getCreateVMFunc() err("No Java VM found. Is JAVA_HOME defined? Need to find 'libjvm.so'"); return NULL; } + msg("getCreateVMFunc: Loading JVM: %s", libname.c_str()); void *lib = dlopen(libname.c_str(), RTLD_NOW); if (!lib) { @@ -547,7 +623,7 @@ static void populateClassPath(const String &javaroot, //======================================================================== -// Native methods +// SCRIPT RUNNER //======================================================================== /** * These methods are used to allow the ScriptRunner class to @@ -569,14 +645,57 @@ void JNICALL stdErrWrite(JNIEnv */*env*/, jobject /*obj*/, jlong ptr, jint ch) } +void JNICALL logWrite(JNIEnv */*env*/, jobject /*obj*/, jlong ptr, jint ch) +{ + JavaBinderyImpl *bind = (JavaBinderyImpl *)ptr; + bind->log(ch); +} + + static JNINativeMethod scriptRunnerMethods[] = { { (char *)"stdOutWrite", (char *)"(JI)V", (void *)stdOutWrite }, { (char *)"stdErrWrite", (char *)"(JI)V", (void *)stdErrWrite }, +{ (char *)"logWrite", (char *)"(JI)V", (void *)logWrite }, { NULL, NULL, NULL } }; + +/** + * This sets up the 'ScriptRunner' java class for execution of + * scripts + */ +bool JavaBinderyImpl::setupScriptRunner() +{ + String className = "org/inkscape/cmn/ScriptRunner"; + if (!registerNatives(className, scriptRunnerMethods)) + { + return false; + } + jclass cls = env->FindClass(className.c_str()); + if (!cls) + { + err("setupScriptRunner: cannot find class '%s'", className.c_str()); + return false; + } + jmethodID mid = env->GetMethodID(cls, "", "(J)V"); + if (!mid) + { + err("setupScriptRunner: cannot find constructor for '%s'", className.c_str()); + return false; + } + jobject obj = env->NewObject(cls, mid, ((jlong)this)); + if (!obj) + { + err("setupScriptRunner: cannot construct '%s'", className.c_str()); + return false; + } + msg("ScriptRunner ready"); + return true; +} + + //======================================================================== -// End native methods +// End SCRIPT RUNNER //======================================================================== @@ -647,16 +766,14 @@ bool JavaBinderyImpl::loadJVM() int versionMinor = (vers ) & 0xffff; msg("Loaded JVM version %d.%d", versionMajor, versionMinor); - if (!registerNatives("org/inkscape/cmn/ScriptRunner", - scriptRunnerMethods)) - { + if (!setupScriptRunner()) return false; - } + + return true; } - /** * This is a difficult method. What we are doing is trying to * call a static method with a list of arguments. Similar to @@ -763,6 +880,12 @@ bool JavaBinderyImpl::callStatic(int type, } } delete jvals; + String errStr = getException(env); + if (errStr.size()>0) + { + err("callStatic: %s", errStr.c_str()); + return false; + } return true; } @@ -800,7 +923,7 @@ bool JavaBinderyImpl::registerNatives(const String &className, err("Could not find class '%s'", className.c_str()); return false; } - msg("registerNatives: class '%s' found", className.c_str()); + //msg("registerNatives: class '%s' found", className.c_str()); /** * hack for JDK bug http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6493522 diff --git a/src/bind/javabind.h b/src/bind/javabind.h index 164110ea6..b20132d03 100644 --- a/src/bind/javabind.h +++ b/src/bind/javabind.h @@ -272,6 +272,11 @@ public: stdOutBuf.clear(); } + virtual void stdOut(int ch) + { + stdOutBuf.push_back((char)ch); + } + virtual String stdErrGet() { return stdErrBuf; @@ -282,14 +287,29 @@ public: stdErrBuf.clear(); } - virtual void stdOut(int ch) + virtual void stdErr(int ch) { - stdOutBuf.push_back((char)ch); + stdErrBuf.push_back((char)ch); } - virtual void stdErr(int ch) + virtual String logGet() { - stdErrBuf.push_back((char)ch); + return logBuf; + } + + virtual void logClear() + { + logBuf.clear(); + } + + virtual void log(int ch) + { + logBuf.push_back((char)ch); + if (ch == '\n' || ch == '\r') + { + g_message(logBuf.c_str()); + logBuf.clear(); + } } @@ -303,6 +323,7 @@ protected: String stdOutBuf; String stdErrBuf; + String logBuf; }; -- cgit v1.2.3