From: ishmal Date: Tue, 11 Mar 2008 21:13:53 +0000 (+0000) Subject: Got initial JS execution working X-Git-Url: https://git.tokkee.org/?a=commitdiff_plain;h=724987df101f1d5d71becaa78a1ad854f45c2a76;p=inkscape.git Got initial JS execution working --- 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; }; diff --git a/src/extension/script/InkscapeScript.cpp b/src/extension/script/InkscapeScript.cpp index 138c8cb7e..1507c6344 100644 --- a/src/extension/script/InkscapeScript.cpp +++ b/src/extension/script/InkscapeScript.cpp @@ -75,15 +75,15 @@ bool InkscapeScript::interpretScript(const Glib::ustring &script, //if() instead of switch() lets us scope vars if (language == InkscapeScript::JAVASCRIPT) { - langname="Javascript"; + langname="javascript"; } else if (language == InkscapeScript::PYTHON) { - langname="Python"; + langname="python"; } else if (language == InkscapeScript::RUBY) { - langname="Ruby"; + langname="ruby"; } else { diff --git a/src/ui/dialog/scriptdialog.cpp b/src/ui/dialog/scriptdialog.cpp index fd0a43851..ff075c186 100644 --- a/src/ui/dialog/scriptdialog.cpp +++ b/src/ui/dialog/scriptdialog.cpp @@ -110,31 +110,18 @@ class ScriptDialogImpl : public ScriptDialog }; -static const char *defaultPythonCodeStr = -#if defined(WITH_PYTHON) - "# This is a sample Python script.\n" - "# To run it, select 'Execute Python' from the File menu above.\n" - "desktop = inkscape.activeDesktop\n" - "dialogmanager = desktop.dialogManager\n" - "document = inkscape.activeDocument\n" - "inkscape.hello()\n" - "dialogmanager.showAbout()\n" -#elif defined(WITH_PERL) - "# This is a sample Perl script.\n" - "# To run it, select 'Execute Perl' from the File menu above.\n" - "my $desktop = $inkscape->getDesktop();\n" - "my $dialogmanager = $inkscape->getDialogManager();\n" - "my $document = $desktop->getDocument();\n" - "$document->hello();\n" - "$dialogmanager->showAbout();\n" -#else - "# This is where you could type a script.\n" - "# However, no scripting languages have been compiled\n" - "# into Inkscape, so this window has no functionality.\n" - "# When compiling Inkscape, run \"configure\" with\n" - "# \"--with-python\" and/or \"--with-perl\".\n" -#endif - ""; +static const char *defaultCodeStr = + "/**\n" + " * This is some example Javascript.\n" + " * Try 'Execute Javascript'\n" + " */\n" + "function sayHello() {\n" + " println('Hello, world!');\n" + "}\n" + "\n" + "sayHello();\n" + "\n"; + @@ -229,7 +216,7 @@ ScriptDialogImpl::ScriptDialogImpl() : //### Set up the script field scriptText.set_editable(true); - scriptText.get_buffer()->set_text(defaultPythonCodeStr); + scriptText.get_buffer()->set_text(defaultCodeStr); scriptTextScroll.add(scriptText); scriptTextScroll.set_policy(Gtk::POLICY_ALWAYS, Gtk::POLICY_ALWAYS); scriptTextFrame.set_label(_("Script"));