summaryrefslogtreecommitdiffstats
path: root/src/bind/javabind.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/bind/javabind.cpp')
-rw-r--r--src/bind/javabind.cpp1209
1 files changed, 0 insertions, 1209 deletions
diff --git a/src/bind/javabind.cpp b/src/bind/javabind.cpp
deleted file mode 100644
index 8a66bac59..000000000
--- a/src/bind/javabind.cpp
+++ /dev/null
@@ -1,1209 +0,0 @@
-/**
- * @file
- * This is a simple mechanism to bind Inkscape to Java, and thence
- * to all of the nice things that can be layered upon that.
- *
- * Note: We must limit Java or JVM-specific code to this file
- * and to dobinding.cpp. It should be hidden from javabind.h
- *
- * This file is mostly about getting things up and running, and
- * providing the basic C-to-Java hooks.
- *
- * dobinding.cpp will have the rote and repetitious
- * class-by-class binding
- */
-/*
- * Authors:
- * Bob Jamison
- *
- * Copyright (C) 2007-2008 Bob Jamison
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <string.h>
-#include <jni.h>
-
-#include <sys/types.h>
-#include <dirent.h>
-
-
-#ifdef __WIN32__
-#include <windows.h>
-#else
-#include <dlfcn.h>
-#include <errno.h>
-#endif
-
-#if HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-
-#include "javabind.h"
-#include "javabind-private.h"
-#include <path-prefix.h>
-#include <prefix.h>
-#include <glib.h>
-
-//For repr and document
-#include <document.h>
-#include <inkscape.h>
-#include <xml/repr.h>
-
-
-
-namespace Inkscape
-{
-
-namespace Bind
-{
-
-
-//########################################################################
-//# DEFINITIONS
-//########################################################################
-
-typedef jint (*CreateVMFunc)(JavaVM **, JNIEnv **, void *);
-
-
-
-//########################################################################
-//# UTILITY
-//########################################################################
-
-/**
- * Normalize path. Java wants '/', even on Windows
- */
-String normalizePath(const String &str)
-{
- String buf;
- for (unsigned int i=0 ; i<str.size() ; i++)
- {
- char ch = str[i];
- if (ch == '\\')
- buf.push_back('/');
- else
- buf.push_back(ch);
- }
- return buf;
-}
-
-
-/**
- * Convert a java string to a C++ string
- */
-static String getString(JNIEnv *env, jstring jstr)
-{
- const char *chars = env->GetStringUTFChars(jstr, JNI_FALSE);
- String str = chars;
- env->ReleaseStringUTFChars(jstr, chars);
- return str;
-}
-
-
-/**
- * Check if the VM has encountered an Exception. If so, get the String for it
- * and clear the exception
- */
-String getExceptionString(JNIEnv *env)
-{
- String buf;
- jthrowable exc = env->ExceptionOccurred();
- if (!exc)
- return buf;
- jclass cls = env->GetObjectClass(exc);
- jmethodID mid = env->GetMethodID(cls, "toString", "()Ljava/lang/String;");
- jstring jstr = (jstring) env->CallObjectMethod(exc, mid);
- buf.append(getString(env, jstr));
- env->ExceptionClear();
- return buf;
-}
-
-//########################################################################
-//# CONSTRUCTOR/DESTRUCTOR
-//########################################################################
-
-static JavaBinderyImpl *_instance = NULL;
-
-JavaBindery *JavaBindery::getInstance()
-{
- return JavaBinderyImpl::getInstance();
-}
-
-JavaBinderyImpl *JavaBinderyImpl::getInstance()
-{
- if (!_instance)
- {
- _instance = new JavaBinderyImpl();
- }
- return _instance;
-}
-
-JavaBinderyImpl::JavaBinderyImpl()
-{
- jvm = NULL;
- env = NULL;
- gatewayObj = NULL;
-}
-
-JavaBinderyImpl::~JavaBinderyImpl()
-{
-}
-
-
-//########################################################################
-//# MESSAGES
-//########################################################################
-
-void err(const char *fmt, ...)
-{
- va_list args;
- g_warning("JavaBinderyImpl err:");
- va_start(args, fmt);
- g_logv(G_LOG_DOMAIN, G_LOG_LEVEL_WARNING, fmt, args);
- va_end(args);
- g_warning("\n");
-}
-
-void msg(const char *fmt, ...)
-{
- va_list args;
- g_message("JavaBinderyImpl:");
- va_start(args, fmt);
- g_logv(G_LOG_DOMAIN, G_LOG_LEVEL_MESSAGE, fmt, args);
- va_end(args);
- g_message("\n");
-}
-
-
-
-//########################################################################
-//# W I N 3 2 S T Y L E
-//########################################################################
-#ifdef __WIN32__
-
-
-#define DIR_SEPARATOR "\\"
-#define PATH_SEPARATOR ";"
-
-
-
-static bool getRegistryString(HKEY /*root*/, const char *keyName,
- const char *valName, char *buf, int buflen)
-{
- HKEY key;
- DWORD bufsiz = buflen;
- RegOpenKeyEx(HKEY_LOCAL_MACHINE, keyName, 0, KEY_READ, &key);
- int ret = RegQueryValueEx(key, TEXT(valName),
- NULL, NULL, (BYTE *)buf, &bufsiz);
- if (ret != ERROR_SUCCESS)
- {
- err("Key '%s\\%s not found\n", keyName, valName);
- return false;
- }
- RegCloseKey(key);
- return true;
-}
-
-
-static String cleanPath(const String &s)
-{
- String buf;
- for (unsigned int i=0 ; i<s.size() ; i++)
- {
- char ch = s[i];
- if (ch != '"')
- buf.push_back(ch);
- }
- return buf;
-}
-
-
-/**
- * Common places to find jvm.dll under JAVA_HOME
- */
-static const char *commonJavaPaths[] =
-{
- "\\jre\\bin\\client\\jvm.dll",
- "\\bin\\client\\jvm.dll",
- "\\jvm.dll",
- NULL
-};
-
-
-/**
- * Return the directory of the .exe that is currently running
- */
-static String getExePath()
-{
- char exeName[MAX_PATH+1];
- GetModuleFileName(NULL, exeName, MAX_PATH);
- char *slashPos = strrchr(exeName, '\\');
- if (slashPos)
- *slashPos = '\0';
- String s = exeName;
- return s;
-}
-
-
-/**
- * Check a directory for several possibilities of sub-locations
- * under it, where a jvm might exist.
- */
-static String checkPathUnderRoot(const String &root)
-{
- for (const char **path = commonJavaPaths ; *path ; path++)
- {
- String jpath = root;
- jpath.append(*path);
- //msg("trying '%s'", jpath.c_str());
- struct stat finfo;
- if (stat(jpath.c_str(), &finfo)>=0)
- {
- //msg("found");
- return jpath;
- }
- }
- return "";
-}
-
-
-
-/**
- * Attempt to find and load a jvm.dll file. Find the createVM()
- * function's address and return it
- */
-static CreateVMFunc getCreateVMFunc()
-{
- bool found = false;
- String libname;
-
- /**
- * First, look for an embedded jre in the .exe's dir.
- * This allows us to package our own JRE if we want to.
- */
- String inkscapeHome = getExePath();
- inkscapeHome.append("\\jre");
- msg("INKSCAPE_HOME='%s'", inkscapeHome.c_str());
- String path = checkPathUnderRoot(inkscapeHome);
- if (path.size() > 0)
- {
- libname = path;
- found = true;
- }
-
- /**
- * Next, look for JAVA_HOME. This will allow the user
- * to override what's in the registry
- */
- if (!found)
- {
- const char *envStr = getenv("JAVA_HOME");
- if (envStr)
- {
- String javaHome = cleanPath(envStr);
- msg("JAVA_HOME='%s'", javaHome.c_str());
- path = checkPathUnderRoot(javaHome);
- if (path.size() > 0)
- {
- libname = path;
- found = true;
- }
- }
- }
-
- //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);
- }
- }
- }
-
- if (!found)
- {
- err("JVM not found at JAVA_HOME or in registry");
- return NULL;
- }
-
- /**
- * 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.c_str());
- return NULL;
- }
- CreateVMFunc createVM = (CreateVMFunc)GetProcAddress(lib, "JNI_CreateJavaVM");
- if (!createVM)
- {
- err("Could not find 'JNI_CreateJavaVM' in shared library '%s'",
- libname.c_str());
- return NULL;
- }
- return createVM;
-}
-
-/**
- * Return the directory where the Java classes/libs/resources are
- * located
- */
-static void getJavaRoot(String &javaroot)
-{
- /*
- javaroot = getExePath();
- javaroot.append("\\");
- javaroot.append(INKSCAPE_BINDDIR);
- javaroot.append("\\java");
- */
- javaroot = INKSCAPE_BINDDIR;
- javaroot.append("\\java");
-}
-
-
-
-
-//########################################################################
-//# U N I X S T Y L E
-//########################################################################
-#else /* !__WIN32__ */
-
-
-#define DIR_SEPARATOR "/"
-#define PATH_SEPARATOR ":"
-
-
-/**
- * Recursively descend into a directory looking for libjvm.so
- */
-static bool findJVMRecursive(const String &dirpath,
- std::vector<String> &results)
-{
- DIR *dir = opendir(dirpath.c_str());
- if (!dir)
- return false;
- bool ret = false;
- while (true)
- {
- struct dirent *de = readdir(dir);
- if (!de)
- break;
- String fname = de->d_name;
- if (fname == "." || fname == "..")
- continue;
- String path = dirpath;
- path.push_back('/');
- path.append(fname);
- if (fname == "libjvm.so")
- {
- ret = true;
- results.push_back(path);
- continue;
- }
- struct stat finfo;
- if (lstat(path.c_str(), &finfo)<0)
- {
- break;
- }
- if (finfo.st_mode & S_IFDIR)
- {
- ret |= findJVMRecursive(path, results);
- }
- }
- closedir(dir);
- return ret;
-}
-
-
-/**
- * Some common places on a Unix filesystem where JVMs are
- * often found.
- */
-static const char *commonJavaPaths[] =
-{
- "/usr/lib/jvm/jre",
- "/usr/lib/jvm",
- "/usr/local/lib/jvm/jre",
- "/usr/local/lib/jvm",
- "/usr/java",
- "/usr/local/java",
- NULL
-};
-
-
-
-/**
- * Look for a Java VM (libjvm.so) in several Unix places
- */
-static bool findJVM(String &result)
-{
- std::vector<String> results;
- bool found = false;
-
- /* Is there one specified by the user? */
- const char *javaHome = getenv("JAVA_HOME");
- if (javaHome && findJVMRecursive(javaHome, results))
- found = true;
- else for (const char **path = commonJavaPaths ; *path ; path++)
- {
- if (findJVMRecursive(*path, results))
- {
- found = true;
- break;
- }
- }
- if (!found)
- {
- return false;
- }
- if (results.empty())
- return false;
- //Look first for a Client VM
- for (unsigned int i=0 ; i<results.size() ; i++)
- {
- String s = results[i];
- if (s.find("client") != s.npos)
- {
- result = s;
- return true;
- }
- }
- //else default to the first
- result = results[0];
- return true;
-}
-
-
-
-/**
- * Attempt to find and load a jvm.dll file. Find the createVM()
- * function's address and return it
- */
-static CreateVMFunc getCreateVMFunc()
-{
- String libname;
- if (!findJVM(libname))
- {
- 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)
- {
- err("Java VM not found at '%s' : %s", libname.c_str(), strerror(errno));
- return NULL;
- }
- CreateVMFunc createVM = (CreateVMFunc)dlsym(lib, "JNI_CreateJavaVM");
- if (!createVM)
- {
- err("Could not find 'JNI_CreateJavaVM' in shared library");
- return NULL;
- }
- return createVM;
-}
-
-
-/**
- * Return the directory where the Java classes/libs/resources are
- * located
- */
-static void getJavaRoot(String &javaroot)
-{
- javaroot = INKSCAPE_BINDDIR;
- javaroot.append("/java");
-}
-
-#endif /* !__WIN32__ */
-
-
-//########################################################################
-//# COMMON
-//########################################################################
-
-
-bool JavaBinderyImpl::isLoaded()
-{
- return (jvm != (void *)0);
-}
-
-
-
-/**
- * This will set up the classpath for the launched VM.
- * We will add two things:
- * 1. INKSCAPE_JAVADIR/classes -- path to loose classes
- * 2. A concatenation of all jar files in INKSCAPE_JAVADIR/lib
- *
- * This will allow people to add classes and jars to the JVM without
- * needing to state them explicitly.
- *
- * @param javaroot. Should be INKSCAPE_JAVADIR
- * @param result a string buffer to hold the result of this method
- */
-static void populateClassPath(const String &javaroot,
- String &result)
-{
- String classdir = javaroot;
- classdir.append(DIR_SEPARATOR);
- classdir.append("classes");
-
- String cp = classdir;
-
- String libdir = javaroot;
- libdir.append(DIR_SEPARATOR);
- libdir.append("lib");
-
- DIR *dir = opendir(libdir.c_str());
- if (!dir)
- {
- result = cp;
- return;
- }
-
- while (true)
- {
- struct dirent *de = readdir(dir);
- if (!de)
- break;
- String fname = de->d_name;
- if (fname == "." || fname == "..")
- continue;
- if (fname.size()<5) //x.jar
- continue;
- if (fname.compare(fname.size()-4, 4, ".jar") != 0)
- continue;
-
- String path = libdir;
- path.append(DIR_SEPARATOR);
- path.append(fname);
-
- cp.append(PATH_SEPARATOR);
- cp.append(path);
- }
- closedir(dir);
-
- result = cp;
-}
-
-
-
-//========================================================================
-// Gateway
-//========================================================================
-/**
- * This is provided to scripts can grab the current copy or the
- * repr tree. If anyone has a smarter way of doing this, please implement.
- */
-static jstring JNICALL documentGet(JNIEnv *env, jobject /*obj*/, jlong /*ptr*/)
-{
- //JavaBinderyImpl *bind = (JavaBinderyImpl *)ptr;
- String buf = sp_repr_save_buf((SP_ACTIVE_DOCUMENT)->rdoc);
- jstring jstr = env->NewStringUTF(buf.c_str());
- return jstr;
-}
-
-/**
- * This is provided to scripts can load an XML tree into Inkscape.
- * If anyone has a smarter way of doing this, please implement.
- */
-static jboolean JNICALL documentSet(JNIEnv */*env*/, jobject /*obj*/, jlong /*ptr*/, jstring /*jstr*/)
-{
- /*
- JavaBinderyImpl *bind = (JavaBinderyImpl *)ptr;
- String s = getString(env, jstr);
- SPDocument *doc = sp_document_new_from_mem(s.c_str(), s.size(), true);
- */
- return JNI_TRUE;
-}
-
-/**
- * This method is used to allow the gateway class to
- * redirect its logging stream here.
- * For the main C++/Java bindings, see dobinding.cpp
- */
-static void JNICALL logWrite(JNIEnv */*env*/, jobject /*obj*/, jlong ptr, jint ch)
-{
- JavaBinderyImpl *bind = reinterpret_cast<JavaBinderyImpl *>(ptr);
- bind->log(ch);
-}
-
-
-static JNINativeMethod gatewayMethods[] =
-{
-{ (char *)"documentGet", (char *)"(J)Ljava/lang/String;", (void *)documentGet },
-{ (char *)"documentSet", (char *)"(JLjava/lang/String;)Z", (void *)documentSet },
-{ (char *)"logWrite", (char *)"(JI)V", (void *)logWrite },
-{ NULL, NULL, NULL }
-};
-
-
-/**
- * This sets up the 'Gateway' java class for execution of
- * scripts. The class's constructor takes a jlong. This java long
- * is used to store the pointer to 'this'. When ScriptRunner makes
- * native calls, it passes that jlong back, so that it can call the
- * methods of this C++ class.
- */
-bool JavaBinderyImpl::setupGateway()
-{
- String className = "org/inkscape/cmn/Gateway";
- if (!registerNatives(className, gatewayMethods))
- {
- return false;
- }
- jclass cls = env->FindClass(className.c_str());
- if (!cls)
- {
- err("setupGateway: cannot find class '%s' : %s",
- className.c_str(), getException().c_str());
- return false;
- }
- jmethodID mid = env->GetMethodID(cls, "<init>", "(J)V");
- if (!mid)
- {
- err("setupGateway: cannot find constructor for '%s' : %s",
- className.c_str(), getException().c_str());
- return false;
- }
- gatewayObj = env->NewObject(cls, mid, ((jlong)this));
- if (!gatewayObj)
- {
- err("setupGateway: cannot construct '%s' : %s",
- className.c_str(), getException().c_str());
- return false;
- }
-
- msg("Gateway ready");
- return true;
-}
-
-bool JavaBinderyImpl::scriptRun(const String &lang, const String &script)
-{
- if (!loadJVM())
- return false;
-
- std::vector<Value> params;
- Value langParm(lang);
- params.push_back(langParm);
- Value scriptParm(script);
- params.push_back(scriptParm);
- Value retval;
- callInstance(Value::BIND_VOID, gatewayObj, "scriptRun",
- "(Ljava/lang/String;Ljava/lang/String;)Z", params, retval);
- return retval.getBoolean();
-}
-
-bool JavaBinderyImpl::scriptRunFile(const String &lang, const String &fname)
-{
- if (!loadJVM())
- return false;
-
- std::vector<Value> params;
- Value langParm(lang);
- params.push_back(langParm);
- Value fnameParm(fname);
- params.push_back(fnameParm);
- Value retval;
- callInstance(Value::BIND_VOID, gatewayObj, "scriptRunFile",
- "(Ljava/lang/String;Ljava/lang/String;)Z", params, retval);
- return retval.getBoolean();
-}
-
-bool JavaBinderyImpl::showConsole()
-{
- if (!loadJVM())
- return false;
-
- std::vector<Value> params;
- Value retval;
- callInstance(Value::BIND_VOID, gatewayObj, "showConsole",
- "()Z", params, retval);
- return retval.getBoolean();
-}
-
-
-//========================================================================
-// End Gateway
-//========================================================================
-
-
-/**
- * This is used to grab output from the VM itself. See 'options' below.
- */
-static int JNICALL vfprintfHook(FILE* /*f*/, const char *fmt, va_list args)
-{
- g_logv(G_LOG_DOMAIN, G_LOG_LEVEL_MESSAGE, fmt, args);
- return JNI_TRUE;
-}
-
-
-/**
- * This is the most important part of this class. Here we
- * attempt to find, load, and initialize a java (or mlvm?) virtual
- * machine.
- *
- * @return true if successful, else false
- */
-bool JavaBinderyImpl::loadJVM()
-{
- if (jvm)
- return true;
-
- CreateVMFunc createVM = getCreateVMFunc();
- if (!createVM)
- {
- err("Could not find 'JNI_CreateJavaVM' in shared library");
- return false;
- }
-
- String javaroot;
- getJavaRoot(javaroot);
- String cp;
- populateClassPath(javaroot, cp);
- String classpath = "-Djava.class.path=";
- classpath.append(normalizePath(cp));
- msg("Class path is: '%s'", classpath.c_str());
-
- String libpath = "-Djava.library.path=";
- libpath.append(javaroot);
- libpath.append(DIR_SEPARATOR);
- libpath.append("libm");
- libpath = normalizePath(libpath);
- msg("Lib path is: '%s'", libpath.c_str());
-
- JavaVMInitArgs vm_args;
- JavaVMOption options[10];//should be enough
- int nOptions = 0;
- options[nOptions++].optionString = (char *)classpath.c_str();
- options[nOptions++].optionString = (char *)libpath.c_str();
- //options[nOptions++].optionString = (char *)"-verbose:jni";
- options[nOptions ].optionString = (char *)"vfprintf";
- options[nOptions++].extraInfo = (void *)vfprintfHook;
- vm_args.version = JNI_VERSION_1_4;
- vm_args.options = options;
- vm_args.nOptions = nOptions;
- vm_args.ignoreUnrecognized = true;
-
- if (createVM(&jvm, &env, &vm_args) < 0)
- {
- err("JNI_CreateJavaVM() failed");
- return false;
- }
-
- //get jvm version
- jint vers = env->GetVersion();
- int versionMajor = (vers>>16) & 0xffff;
- int versionMinor = (vers ) & 0xffff;
- msg("Loaded JVM version %d.%d", versionMajor, versionMinor);
-
- if (!setupGateway()) {
- // set jvm = NULL, otherwise, this method will return true when called for the second time while the gateway might not have been created!
- jvm->DestroyJavaVM();
- jvm = NULL;
- env = NULL;
- err("Java bindings: setupGateway() failed");
- 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
- * a varargs call, we need to marshal the Values into their
- * Java equivalents and make the proper call.
- *
- * @param type the return type of the method
- * @param className the full (package / name) name of the java class
- * @param methodName the name of the method being invoked
- * @param signature the method signature (ex: "(Ljava/lang/String;I)V" )
- * that describes the param and return types of the method.
- * @param retval the return value of the java method
- * @return true if the call was successful, else false. This is not
- * the return value of the method.
- */
-bool JavaBinderyImpl::callStatic(int type,
- const String &className,
- const String &methodName,
- const String &signature,
- const std::vector<Value> &params,
- Value &retval)
-{
- jclass cls = env->FindClass(className.c_str());
- if (!cls)
- {
- err("Could not find class '%s' : %s",
- className.c_str(), getException().c_str());
- return false;
- }
- jmethodID mid = env->GetStaticMethodID(cls,
- methodName.c_str(), signature.c_str());
- if (!mid)
- {
- err("Could not find method '%s:%s/%s' : %s",
- className.c_str(), methodName.c_str(),
- signature.c_str(), getException().c_str());
- return false;
- }
- /**
- * Assemble your parameters into a form usable by JNI
- */
- jvalue *jvals = new jvalue[params.size()];
- for (unsigned int i=0 ; i<params.size() ; i++)
- {
- Value v = params[i];
- switch (v.getType())
- {
- case Value::BIND_BOOLEAN:
- {
- jvals[i].z = (jboolean)v.getBoolean();
- break;
- }
- case Value::BIND_INT:
- {
- jvals[i].i = (jint)v.getInt();
- break;
- }
- case Value::BIND_DOUBLE:
- {
- jvals[i].d = (jdouble)v.getDouble();
- break;
- }
- case Value::BIND_STRING:
- {
- jvals[i].l = (jobject) env->NewStringUTF(v.getString().c_str());
- break;
- }
- default:
- {
- err("Unknown value type: %d", v.getType());
- delete [] jvals;
- return false;
- }
- }
- }
- switch (type)
- {
- case Value::BIND_VOID:
- {
- env->CallStaticVoidMethodA(cls, mid, jvals);
- break;
- }
- case Value::BIND_BOOLEAN:
- {
- jboolean ret = env->CallStaticBooleanMethodA(cls, mid, jvals);
- if (ret == JNI_TRUE) //remember, don't truncate
- retval.setBoolean(true);
- else
- retval.setBoolean(false);
- break;
- }
- case Value::BIND_INT:
- {
- jint ret = env->CallStaticIntMethodA(cls, mid, jvals);
- retval.setInt(ret);
- break;
- }
- case Value::BIND_DOUBLE:
- {
- jdouble ret = env->CallStaticDoubleMethodA(cls, mid, jvals);
- retval.setDouble(ret);
- break;
- }
- case Value::BIND_STRING:
- {
- jobject ret = env->CallStaticObjectMethodA(cls, mid, jvals);
- jstring jstr = (jstring) ret;
- const char *str = env->GetStringUTFChars(jstr, JNI_FALSE);
- retval.setString(str);
- env->ReleaseStringUTFChars(jstr, str);
- break;
- }
- default:
- {
- err("Unknown return type: %d", type);
- return false;
- }
- }
- delete [] jvals;
- String errStr = getException();
- if (errStr.size()>0)
- {
- err("callStatic: %s", errStr.c_str());
- return false;
- }
- return true;
-}
-
-
-
-/**
- * Another difficult method. However, this time we are operating
- * on an existing instance jobject.
- *
- * @param type the return type of the method
- * @param obj the instance upon which to make the call
- * @param methodName the name of the method being invoked
- * @param signature the method signature (ex: "(Ljava/lang/String;I)V" )
- * that describes the param and return types of the method.
- * @param retval the return value of the java method
- * @return true if the call was successful, else false. This is not
- * the return value of the method.
- */
-bool JavaBinderyImpl::callInstance(
- int type,
- const jobject obj,
- const String &methodName,
- const String &signature,
- const std::vector<Value> &params,
- Value &retval)
-{
- jmethodID mid = env->GetMethodID(env->GetObjectClass(obj),
- methodName.c_str(), signature.c_str());
- if (!mid)
- {
- err("Could not find method '%s/%s' : %s",
- methodName.c_str(),
- signature.c_str(), getException().c_str());
- return false;
- }
- /**
- * Assemble your parameters into a form usable by JNI
- */
- jvalue *jvals = new jvalue[params.size()];
- for (unsigned int i=0 ; i<params.size() ; i++)
- {
- Value v = params[i];
- switch (v.getType())
- {
- case Value::BIND_BOOLEAN:
- {
- jvals[i].z = (jboolean)v.getBoolean();
- break;
- }
- case Value::BIND_INT:
- {
- jvals[i].i = (jint)v.getInt();
- break;
- }
- case Value::BIND_DOUBLE:
- {
- jvals[i].d = (jdouble)v.getDouble();
- break;
- }
- case Value::BIND_STRING:
- {
- jvals[i].l = (jobject) env->NewStringUTF(v.getString().c_str());
- break;
- }
- default:
- {
- err("Unknown value type: %d", v.getType());
- delete [] jvals;
- return false;
- }
- }
- }
- switch (type)
- {
- case Value::BIND_VOID:
- {
- env->CallVoidMethodA(obj, mid, jvals);
- break;
- }
- case Value::BIND_BOOLEAN:
- {
- jboolean ret = env->CallBooleanMethodA(obj, mid, jvals);
- if (ret == JNI_TRUE) //remember, don't truncate
- retval.setBoolean(true);
- else
- retval.setBoolean(false);
- break;
- }
- case Value::BIND_INT:
- {
- jint ret = env->CallIntMethodA(obj, mid, jvals);
- retval.setInt(ret);
- break;
- }
- case Value::BIND_DOUBLE:
- {
- jdouble ret = env->CallDoubleMethodA(obj, mid, jvals);
- retval.setDouble(ret);
- break;
- }
- case Value::BIND_STRING:
- {
- jobject ret = env->CallObjectMethodA(obj, mid, jvals);
- jstring jstr = (jstring) ret;
- const char *str = env->GetStringUTFChars(jstr, JNI_FALSE);
- retval.setString(str);
- env->ReleaseStringUTFChars(jstr, str);
- break;
- }
- default:
- {
- err("Unknown return type: %d", type);
- return false;
- }
- }
- delete [] jvals;
- String errStr = getException();
- if (errStr.size()>0)
- {
- err("callStatic: %s", errStr.c_str());
- return false;
- }
- return true;
-}
-
-
-
-
-/**
- * Fetch the last exception from the JVM, if any. Clear it to
- * continue processing
- *
- * @return the exception's descriptio,if any. Else ""
- */
-String JavaBinderyImpl::getException()
-{
- return getExceptionString(env);
-}
-
-
-
-/**
- * Convenience method to call the static void main(String argv[])
- * method of a given class
- *
- * @param className full name of the java class
- * @args the argument strings to the method
- * @return true if successful, else false
- */
-bool JavaBinderyImpl::callMain(const String &className,
- const std::vector<String> &args)
-{
- std::vector<Value> parms;
- for (unsigned int i=0 ; i<args.size() ; i++)
- {
- Value v;
- v.setString(args[i]);
- parms.push_back(v);
- }
- Value retval;
- return callStatic(Value::BIND_VOID, className, "main",
- "([Ljava/lang/String;)V", parms, retval);
-}
-
-
-/**
- * Used to register an array of native methods for a named class
- *
- * @param className the full name of the java class
- * @param the method array
- * @return true if successful, else false
- */
-bool JavaBinderyImpl::registerNatives(const String &className,
- const JNINativeMethod *methods)
-{
- jclass cls = env->FindClass(className.c_str());
- if (!cls)
- {
- err("Could not find class '%s'", className.c_str());
- return false;
- }
- //msg("registerNatives: class '%s' found", className.c_str());
-
- /**
- * hack for JDK bug http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6493522
- */
- jmethodID mid = env->GetMethodID(env->GetObjectClass(cls), "getConstructors",
- "()[Ljava/lang/reflect/Constructor;");
- if (!mid)
- {
- err("Could not get reflect mid for 'getConstructors' : %s",
- getException().c_str());
- return false;
- }
- jobject res = env->CallObjectMethod(cls, mid);
- if (!res)
- {
- err("Could not get constructors : %s", getException().c_str());
- return false;
- }
- /**
- * end hack
- */
- jint nrMethods = 0;
- for (const JNINativeMethod *m = methods ; m->name ; m++)
- nrMethods++;
- jint ret = env->RegisterNatives(cls, methods, nrMethods);
- if (ret < 0)
- {
- err("Could not register %d native methods for '%s' : %s",
- nrMethods, className.c_str(), getException().c_str());
- return false;
- }
- return true;
-}
-
-
-
-
-} // namespace Bind
-} // namespace Inkscape
-
-//########################################################################
-//# E N D O F F I L E
-//########################################################################