javabind.cpp revision ceb04aab53a753e8128b203dd32507d82fefcea2
/**
* 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:
* Bob Jamison
*
* Copyright (C) 2007-2008 Bob Jamison
*
* 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 <dirent.h>
#ifdef __WIN32__
#include <windows.h>
#else
#include <dlfcn.h>
#include <errno.h>
#endif
#if HAVE_SYS_STAT_H
#endif
#include "javabind.h"
#include "javabind-private.h"
#include <path-prefix.h>
#include <prefix.h>
#include <glib/gmessages.h>
/**
* 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
*/
namespace Inkscape
{
namespace Bind
{
//########################################################################
//# DEFINITIONS
//########################################################################
//########################################################################
//# UTILITY
//########################################################################
/**
* Normalize path. Java wants '/', even on Windows
*/
{
{
if (ch == '\\')
else
}
return buf;
}
{
if (!exc)
return buf;
env->ExceptionClear();
return buf;
}
{
}
{
}
{
}
{
}
{
}
{
}
{
}
{
}
{
return str;
}
{
}
//########################################################################
//########################################################################
{
return JavaBinderyImpl::getInstance();
}
{
if (!_instance)
{
_instance = new JavaBinderyImpl();
}
return _instance;
}
{
}
{
}
//########################################################################
//# MESSAGES
//########################################################################
{
#if 0
#else
g_warning("JavaBinderyImpl err:");
g_warning("\n");
#endif
}
{
#if 0
#else
g_message("JavaBinderyImpl:");
g_message("\n");
#endif
}
//########################################################################
//# W I N 3 2 S T Y L E
//########################################################################
#ifdef __WIN32__
#define DIR_SEPARATOR "\\"
#define PATH_SEPARATOR ";"
{
if (ret != ERROR_SUCCESS)
{
return false;
}
return true;
}
{
for (unsigned int i=0 ; i<s.size() ; i++)
{
char ch = s[i];
if (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",
};
static CreateVMFunc getCreateVMFunc()
{
bool found = false;
/**
* First, look for JAVA_HOME. This will allow the user
* to override what's in the registry
*/
if (envStr)
{
{
//msg("trying '%s'", jpath.c_str());
{
//msg("found");
found = true;
break;
}
}
}
//not at JAVA_HOME. check the registry
if (!found)
{
char verbuf[16];
char regpath[80];
if (!ret)
{
}
else
{
//msg("reg path: %s\n", regpath);
char valbuf[80];
if (ret)
{
found = true;
}
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
*/
if (!lib)
{
return NULL;
}
if (!createVM)
{
err("Could not find 'JNI_CreateJavaVM' in shared library '%s'",
return NULL;
}
return createVM;
}
{
char exeName[80];
if (slashPos)
*slashPos = '\0';
}
//########################################################################
//# 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
*/
{
if (!dir)
return false;
bool ret = false;
while (true)
{
if (!de)
break;
continue;
{
ret = true;
continue;
}
{
break;
}
{
}
}
return ret;
}
static const char *commonJavaPaths[] =
{
};
/**
* Look for a Java VM (libjvm.so) in several Unix places
*/
{
int found = false;
/* Is there one specified by the user? */
found = true;
{
{
found = true;
break;
}
}
if (!found)
{
return false;
}
return false;
//Look first for a Client VM
{
{
result = s;
return true;
}
}
//else default to the first
return true;
}
static CreateVMFunc getCreateVMFunc()
{
{
return NULL;
}
if (!lib)
{
return NULL;
}
if (!createVM)
{
err("Could not find 'JNI_CreateJavaVM' in shared library");
return NULL;
}
return createVM;
}
{
}
#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
*/
{
if (!dir)
{
return;
}
while (true)
{
if (!de)
break;
continue;
continue;
continue;
}
}
//========================================================================
// SCRIPT RUNNER
//========================================================================
/**
* These methods are used to allow the ScriptRunner class to
* redirect its stderr and stdout streams to here, to be caught
* by two string buffers. We can then use those buffers how we
* want. These native methods are only those needed for running
* a script. For the main C++/Java bindings, see dobinding.cpp
*/
{
}
{
}
{
}
static JNINativeMethod scriptRunnerMethods[] =
{
};
/**
* This sets up the 'ScriptRunner' 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::setupScriptRunner()
{
{
return false;
}
if (!cls)
{
err("setupScriptRunner: cannot find class '%s' : %s",
return false;
}
if (!mid)
{
err("setupScriptRunner: cannot find constructor for '%s' : %s",
return false;
}
if (!obj)
{
err("setupScriptRunner: cannot construct '%s' : %s",
return false;
}
msg("ScriptRunner ready");
return true;
}
//========================================================================
// End SCRIPT RUNNER
//========================================================================
/**
* This is used to grab output from the VM itself. See 'options' below.
*/
{
}
/**
* 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;
if (!createVM)
{
err("Could not find 'JNI_CreateJavaVM' in shared library");
return false;
}
int nOptions = 0;
//options[nOptions++].optionString = (char *)"-verbose:jni";
vm_args.ignoreUnrecognized = true;
{
err("JNI_CreateJavaVM() failed");
return false;
}
//get jvm version
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
* 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
* 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.
*/
const String &methodName,
{
if (!cls)
{
err("Could not find class '%s' : %s",
return false;
}
if (!mid)
{
err("Could not find method '%s:%s/%s' : %s",
return false;
}
/**
* Assemble your parameters into a form usable by JNI
*/
{
switch (v.getType())
{
case Value::BIND_BOOLEAN:
{
break;
}
{
break;
}
case Value::BIND_DOUBLE:
{
break;
}
case Value::BIND_STRING:
{
break;
}
default:
{
return false;
}
}
}
switch (type)
{
{
break;
}
case Value::BIND_BOOLEAN:
{
retval.setBoolean(true);
else
retval.setBoolean(false);
break;
}
{
break;
}
case Value::BIND_DOUBLE:
{
break;
}
case Value::BIND_STRING:
{
break;
}
default:
{
return false;
}
}
delete jvals;
{
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 ""
*/
{
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
*/
{
{
Value v;
}
}
/**
* 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
*/
const JNINativeMethod *methods)
{
if (!cls)
{
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
*/
"()[Ljava/lang/reflect/Constructor;");
if (!mid)
{
err("Could not get reflect mid for 'getConstructors' : %s",
getException().c_str());
return false;
}
if (!res)
{
return false;
}
/**
* end hack
*/
nrMethods++;
if (ret < 0)
{
err("Could not register %d native methods for '%s' : %s",
return false;
}
return true;
}
} // namespace Bind
} // namespace Inkscape
//########################################################################
//# E N D O F F I L E
//########################################################################