diff --git a/src/bind/javabind.cpp b/src/bind/javabind.cpp
index 0262aee54c5cc570756d7d94a1ef663cadfef620..6dc8c9a9bb2b24d1615c0f3abfbd1a03d57f2a5d 100644 (file)
--- a/src/bind/javabind.cpp
+++ b/src/bind/javabind.cpp
/**
- * This is a simple mechanism to bind Inkscape to Java, and thence
+ * @file
+ * @brief This is a simple mechanism to bind Inkscape to Java, and thence
* to all of the nice things that can be layered upon that.
*
* Authors:
#include <prefix.h>
#include <glib/gmessages.h>
+//For repr and document
+#include <document.h>
+#include <inkscape.h>
+#include <xml/repr.h>
/**
* Note: We must limit Java or JVM-specific code to this file
return buf;
}
+
+/**
+ * Convert a java string to a C++ string
+ */
+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;
jclass cls = env->GetObjectClass(exc);
jmethodID mid = env->GetMethodID(cls, "toString", "()Ljava/lang/String;");
jstring jstr = (jstring) env->CallObjectMethod(exc, mid);
- const char *str = env->GetStringUTFChars(jstr, JNI_FALSE);
- buf.append(str);
- env->ReleaseStringUTFChars(jstr, str);
+ buf.append(getString(env, jstr));
env->ExceptionClear();
return buf;
}
-jint getInt(JNIEnv *env, jobject obj, const char *name)
+jint getObjInt(JNIEnv *env, jobject obj, const char *name)
{
jfieldID fid = env->GetFieldID(env->GetObjectClass(obj), name, "I");
return env->GetIntField(obj, fid);
}
-void setInt(JNIEnv *env, jobject obj, const char *name, jint val)
+void setObjInt(JNIEnv *env, jobject obj, const char *name, jint val)
{
jfieldID fid = env->GetFieldID(env->GetObjectClass(obj), name, "I");
env->SetIntField(obj, fid, val);
}
-jlong getLong(JNIEnv *env, jobject obj, const char *name)
+jlong getObjLong(JNIEnv *env, jobject obj, const char *name)
{
jfieldID fid = env->GetFieldID(env->GetObjectClass(obj), name, "J");
return env->GetLongField(obj, fid);
}
-void setLong(JNIEnv *env, jobject obj, const char *name, jlong val)
+void setObjLong(JNIEnv *env, jobject obj, const char *name, jlong val)
{
jfieldID fid = env->GetFieldID(env->GetObjectClass(obj), name, "J");
env->SetLongField(obj, fid, val);
}
-jfloat getFloat(JNIEnv *env, jobject obj, const char *name)
+jfloat getObjFloat(JNIEnv *env, jobject obj, const char *name)
{
jfieldID fid = env->GetFieldID(env->GetObjectClass(obj), name, "F");
return env->GetFloatField(obj, fid);
}
-void setFloat(JNIEnv *env, jobject obj, const char *name, jfloat val)
+void setObjFloat(JNIEnv *env, jobject obj, const char *name, jfloat val)
{
jfieldID fid = env->GetFieldID(env->GetObjectClass(obj), name, "F");
env->SetFloatField(obj, fid, val);
}
-jdouble getDouble(JNIEnv *env, jobject obj, const char *name)
+jdouble getObjDouble(JNIEnv *env, jobject obj, const char *name)
{
jfieldID fid = env->GetFieldID(env->GetObjectClass(obj), name, "D");
return env->GetDoubleField(obj, fid);
}
-void setDouble(JNIEnv *env, jobject obj, const char *name, jdouble val)
+void setObjDouble(JNIEnv *env, jobject obj, const char *name, jdouble val)
{
jfieldID fid = env->GetFieldID(env->GetObjectClass(obj), name, "D");
env->SetDoubleField(obj, fid, val);
}
-String getString(JNIEnv *env, jobject obj, const char *name)
+String getObjString(JNIEnv *env, jobject obj, const char *name)
{
jfieldID fid = env->GetFieldID(env->GetObjectClass(obj), name, "Ljava/lang/String;");
jstring jstr = (jstring)env->GetObjectField(obj, fid);
- const char *chars = env->GetStringUTFChars(jstr, JNI_FALSE);
- String str = chars;
- env->ReleaseStringUTFChars(jstr, chars);
- return str;
+ return getString(env, jstr);
}
-void setString(JNIEnv *env, jobject obj, const char *name, const String &val)
+void setObjString(JNIEnv *env, jobject obj, const char *name, const String &val)
{
jstring jstr = env->NewStringUTF(val.c_str());
jfieldID fid = env->GetFieldID(env->GetObjectClass(obj), name, "Ljava/lang/String;");
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 JAVA_HOME. This will allow the user
+ * 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
- */
- const char *envStr = getenv("JAVA_HOME");
- if (envStr)
+ */
+ if (!found)
{
- String javaHome = cleanPath(envStr);
- msg("JAVA_HOME='%s'", javaHome.c_str());
- for (const char **path = commonJavaPaths ; *path ; path++)
+ const char *envStr = getenv("JAVA_HOME");
+ if (envStr)
{
- String jpath = javaHome;
- jpath.append(*path);
- //msg("trying '%s'", jpath.c_str());
- struct stat finfo;
- if (stat(jpath.c_str(), &finfo)>=0)
+ String javaHome = cleanPath(envStr);
+ msg("JAVA_HOME='%s'", javaHome.c_str());
+ path = checkPathUnderRoot(javaHome);
+ if (path.size() > 0)
{
- //msg("found");
- libname = jpath;
+ libname = path;
found = true;
- break;
}
}
}
return createVM;
}
+/**
+ * Return the directory where the Java classes/libs/resources are
+ * located
+ */
static void getJavaRoot(String &javaroot)
{
- char exeName[80];
- GetModuleFileName(NULL, exeName, 80);
- char *slashPos = strrchr(exeName, '\\');
- if (slashPos)
- *slashPos = '\0';
- javaroot = exeName;
+ /*
+ javaroot = getExePath();
javaroot.append("\\");
javaroot.append(INKSCAPE_BINDDIR);
javaroot.append("\\java");
+ */
+ javaroot = INKSCAPE_BINDDIR;
+ javaroot.append("\\java");
}
}
+/**
+ * Some common places on a Unix filesystem where JVMs are
+ * often found.
+ */
static const char *commonJavaPaths[] =
{
"/usr/lib/jvm/jre",
NULL
};
+
+
/**
* Look for a Java VM (libjvm.so) in several Unix places
*/
+/**
+ * Attempt to find and load a jvm.dll file. Find the createVM()
+ * function's address and return it
+ */
static CreateVMFunc getCreateVMFunc()
{
String libname;
}
+/**
+ * Return the directory where the Java classes/libs/resources are
+ * located
+ */
static void getJavaRoot(String &javaroot)
{
javaroot = INKSCAPE_BINDDIR;
//========================================================================
// 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.
+ */
+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.
+ */
+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.
static JNINativeMethod gatewayMethods[] =
{
-{ (char *)"logWrite", (char *)"(JI)V", (void *)logWrite },
+{ (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 }
};
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;
}
int versionMinor = (vers ) & 0xffff;
msg("Loaded JVM version %d.%d", versionMajor, versionMinor);
- if (!setupGateway())
+ 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;
}
default:
{
err("Unknown value type: %d", v.getType());
+ delete [] jvals;
return false;
}
}
return false;
}
}
- delete jvals;
+ delete [] jvals;
String errStr = getException();
if (errStr.size()>0)
{
default:
{
err("Unknown value type: %d", v.getType());
+ delete [] jvals;
return false;
}
}
return false;
}
}
- delete jvals;
+ delete [] jvals;
String errStr = getException();
if (errStr.size()>0)
{