--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/arch/osx/jcc/sources/jcc.cpp Tue May 25 02:43:45 2010 +0200
@@ -0,0 +1,690 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <jni.h>
+#ifdef linux
+#include <dlfcn.h>
+#endif
+
+#include <Python.h>
+#include "structmember.h"
+
+#include "JObject.h"
+#include "JCCEnv.h"
+#include "macros.h"
+
+_DLL_EXPORT JCCEnv *env;
+
+
+/* JCCEnv */
+
+class t_jccenv {
+public:
+ PyObject_HEAD
+ JCCEnv *env;
+};
+
+static void t_jccenv_dealloc(t_jccenv *self);
+static PyObject *t_jccenv_attachCurrentThread(PyObject *self, PyObject *args);
+static PyObject *t_jccenv_detachCurrentThread(PyObject *self);
+static PyObject *t_jccenv_isCurrentThreadAttached(PyObject *self);
+static PyObject *t_jccenv_strhash(PyObject *self, PyObject *arg);
+static PyObject *t_jccenv__dumpRefs(PyObject *self,
+ PyObject *args, PyObject *kwds);
+static PyObject *t_jccenv__get_jni_version(PyObject *self, void *data);
+static PyObject *t_jccenv__get_java_version(PyObject *self, void *data);
+
+static PyGetSetDef t_jccenv_properties[] = {
+ { "jni_version", (getter) t_jccenv__get_jni_version, NULL, NULL, NULL },
+ { "java_version", (getter) t_jccenv__get_java_version, NULL, NULL, NULL },
+ { NULL, NULL, NULL, NULL, NULL }
+};
+
+static PyMemberDef t_jccenv_members[] = {
+ { NULL, 0, 0, 0, NULL }
+};
+
+static PyMethodDef t_jccenv_methods[] = {
+ { "attachCurrentThread", (PyCFunction) t_jccenv_attachCurrentThread,
+ METH_VARARGS, NULL },
+ { "detachCurrentThread", (PyCFunction) t_jccenv_detachCurrentThread,
+ METH_NOARGS, NULL },
+ { "isCurrentThreadAttached", (PyCFunction) t_jccenv_isCurrentThreadAttached,
+ METH_NOARGS, NULL },
+ { "strhash", (PyCFunction) t_jccenv_strhash,
+ METH_O, NULL },
+ { "_dumpRefs", (PyCFunction) t_jccenv__dumpRefs,
+ METH_VARARGS | METH_KEYWORDS, NULL },
+ { NULL, NULL, 0, NULL }
+};
+
+PyTypeObject JCCEnv$$Type = {
+ PyObject_HEAD_INIT(NULL)
+ 0, /* ob_size */
+ "jcc.JCCEnv", /* tp_name */
+ sizeof(t_jccenv), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)t_jccenv_dealloc, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_compare */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT, /* tp_flags */
+ "JCCEnv", /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ t_jccenv_methods, /* tp_methods */
+ t_jccenv_members, /* tp_members */
+ t_jccenv_properties, /* tp_getset */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+};
+
+static void t_jccenv_dealloc(t_jccenv *self)
+{
+ self->ob_type->tp_free((PyObject *) self);
+}
+
+static void add_option(char *name, char *value, JavaVMOption *option)
+{
+ char *buf = new char[strlen(name) + strlen(value) + 1];
+
+ sprintf(buf, "%s%s", name, value);
+ option->optionString = buf;
+}
+
+#ifdef _jcc_lib
+static void add_paths(char *name, char *p0, char *p1, JavaVMOption *option)
+{
+#if defined(_MSC_VER) || defined(__WIN32)
+ char pathsep = ';';
+#else
+ char pathsep = ':';
+#endif
+ char *buf = new char[strlen(name) + strlen(p0) + strlen(p1) + 4];
+
+ sprintf(buf, "%s%s%c%s", name, p0, pathsep, p1);
+ option->optionString = buf;
+}
+#endif
+
+
+static PyObject *t_jccenv_attachCurrentThread(PyObject *self, PyObject *args)
+{
+ char *name = NULL;
+ int asDaemon = 0, result;
+ JNIEnv *jenv = NULL;
+
+ if (!PyArg_ParseTuple(args, "|si", &name, &asDaemon))
+ return NULL;
+
+ JavaVMAttachArgs attach = {
+ JNI_VERSION_1_4, name, NULL
+ };
+
+ if (asDaemon)
+ result = env->vm->AttachCurrentThreadAsDaemon((void **) &jenv, &attach);
+ else
+ result = env->vm->AttachCurrentThread((void **) &jenv, &attach);
+
+ env->set_vm_env(jenv);
+
+ return PyInt_FromLong(result);
+}
+
+static PyObject *t_jccenv_detachCurrentThread(PyObject *self)
+{
+ int result = env->vm->DetachCurrentThread();
+
+ env->set_vm_env(NULL);
+
+ return PyInt_FromLong(result);
+}
+
+static PyObject *t_jccenv_isCurrentThreadAttached(PyObject *self)
+{
+ if (env->get_vm_env() != NULL)
+ Py_RETURN_TRUE;
+
+ Py_RETURN_FALSE;
+}
+
+static PyObject *t_jccenv_strhash(PyObject *self, PyObject *arg)
+{
+ int hash = PyObject_Hash(arg);
+ char buffer[10];
+
+ sprintf(buffer, "%08x", (unsigned int) hash);
+ return PyString_FromStringAndSize(buffer, 8);
+}
+
+static PyObject *t_jccenv__dumpRefs(PyObject *self,
+ PyObject *args, PyObject *kwds)
+{
+ static char *kwnames[] = {
+ "classes", "values", NULL
+ };
+ int classes = 0, values = 0;
+ PyObject *result;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "|ii", kwnames,
+ &classes, &values))
+ return NULL;
+
+ if (classes)
+ result = PyDict_New();
+ else
+ result = PyList_New(env->refs.size());
+
+ int count = 0;
+
+ for (std::multimap<int, countedRef>::iterator iter = env->refs.begin();
+ iter != env->refs.end();
+ iter++) {
+ if (classes) // return dict of { class name: instance count }
+ {
+ char *name = env->getClassName(iter->second.global);
+ PyObject *key = PyString_FromString(name);
+ PyObject *value = PyDict_GetItem(result, key);
+
+ if (value == NULL)
+ value = PyInt_FromLong(1);
+ else
+ value = PyInt_FromLong(PyInt_AS_LONG(value) + 1);
+
+ PyDict_SetItem(result, key, value);
+ Py_DECREF(key);
+ Py_DECREF(value);
+
+ delete name;
+ }
+ else if (values) // return list of (value string, ref count)
+ {
+ char *str = env->toString(iter->second.global);
+ PyObject *key = PyString_FromString(str);
+ PyObject *value = PyInt_FromLong(iter->second.count);
+
+#if PY_VERSION_HEX < 0x02040000
+ PyList_SET_ITEM(result, count++, Py_BuildValue("(OO)", key, value));
+#else
+ PyList_SET_ITEM(result, count++, PyTuple_Pack(2, key, value));
+#endif
+ Py_DECREF(key);
+ Py_DECREF(value);
+
+ delete str;
+ }
+ else // return list of (id hash code, ref count)
+ {
+ PyObject *key = PyInt_FromLong(iter->first);
+ PyObject *value = PyInt_FromLong(iter->second.count);
+
+#if PY_VERSION_HEX < 0x02040000
+ PyList_SET_ITEM(result, count++, Py_BuildValue("(OO)", key, value));
+#else
+ PyList_SET_ITEM(result, count++, PyTuple_Pack(2, key, value));
+#endif
+ Py_DECREF(key);
+ Py_DECREF(value);
+ }
+ }
+
+ return result;
+}
+
+
+static PyObject *t_jccenv__get_jni_version(PyObject *self, void *data)
+{
+ return PyInt_FromLong(env->getJNIVersion());
+}
+
+static PyObject *t_jccenv__get_java_version(PyObject *self, void *data)
+{
+ return env->fromJString(env->getJavaVersion(), 1);
+}
+
+_DLL_EXPORT PyObject *getVMEnv(PyObject *self)
+{
+ if (env->vm != NULL)
+ {
+ t_jccenv *jccenv = (t_jccenv *) JCCEnv$$Type.tp_alloc(&JCCEnv$$Type, 0);
+ jccenv->env = env;
+
+ return (PyObject *) jccenv;
+ }
+
+ Py_RETURN_NONE;
+}
+
+#ifdef _jcc_lib
+static void registerNatives(JNIEnv *vm_env);
+#endif
+
+_DLL_EXPORT PyObject *initJCC(PyObject *module)
+{
+ static int _once_only = 1;
+
+ if (_once_only)
+ {
+ PyEval_InitThreads();
+ INSTALL_TYPE(JCCEnv, module);
+
+ if (env == NULL)
+ env = new JCCEnv(NULL, NULL);
+
+ _once_only = 0;
+ Py_RETURN_TRUE;
+ }
+
+ Py_RETURN_FALSE;
+}
+
+_DLL_EXPORT PyObject *initVM(PyObject *self, PyObject *args, PyObject *kwds)
+{
+ static char *kwnames[] = {
+ "classpath", "initialheap", "maxheap", "maxstack",
+ "vmargs", NULL
+ };
+ char *classpath = NULL;
+ char *initialheap = NULL, *maxheap = NULL, *maxstack = NULL;
+ char *vmargs = NULL;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "|zzzzz", kwnames,
+ &classpath,
+ &initialheap, &maxheap, &maxstack,
+ &vmargs))
+ return NULL;
+
+ if (env->vm)
+ {
+ PyObject *module_cp = NULL;
+
+ if (initialheap || maxheap || maxstack || vmargs)
+ {
+ PyErr_SetString(PyExc_ValueError,
+ "JVM is already running, options are ineffective");
+ return NULL;
+ }
+
+ if (classpath == NULL && self != NULL)
+ {
+ module_cp = PyObject_GetAttrString(self, "CLASSPATH");
+ if (module_cp != NULL)
+ classpath = PyString_AsString(module_cp);
+ }
+
+ if (classpath && classpath[0])
+ env->setClassPath(classpath);
+
+ Py_XDECREF(module_cp);
+
+ return getVMEnv(self);
+ }
+ else
+ {
+ JavaVMInitArgs vm_args;
+ JavaVMOption vm_options[32];
+ JNIEnv *vm_env;
+ JavaVM *vm;
+ unsigned int nOptions = 0;
+ PyObject *module_cp = NULL;
+
+ vm_args.version = JNI_VERSION_1_4;
+ JNI_GetDefaultJavaVMInitArgs(&vm_args);
+
+ if (classpath == NULL && self != NULL)
+ {
+ module_cp = PyObject_GetAttrString(self, "CLASSPATH");
+ if (module_cp != NULL)
+ classpath = PyString_AsString(module_cp);
+ }
+
+#ifdef _jcc_lib
+ PyObject *jcc = PyImport_ImportModule("jcc");
+ PyObject *cp = PyObject_GetAttrString(jcc, "CLASSPATH");
+
+ if (classpath)
+ add_paths("-Djava.class.path=", PyString_AsString(cp), classpath,
+ &vm_options[nOptions++]);
+ else
+ add_option("-Djava.class.path=", PyString_AsString(cp),
+ &vm_options[nOptions++]);
+
+ Py_DECREF(cp);
+ Py_DECREF(jcc);
+#else
+ if (classpath)
+ add_option("-Djava.class.path=", classpath,
+ &vm_options[nOptions++]);
+#endif
+
+ Py_XDECREF(module_cp);
+
+ if (initialheap)
+ add_option("-Xms", initialheap, &vm_options[nOptions++]);
+ if (maxheap)
+ add_option("-Xmx", maxheap, &vm_options[nOptions++]);
+ if (maxstack)
+ add_option("-Xss", maxstack, &vm_options[nOptions++]);
+
+ if (vmargs)
+ {
+ char *buf = strdup(vmargs);
+ char *sep = ",";
+ char *option;
+
+ for (option = strtok(buf, sep); option; option = strtok(NULL, sep))
+ {
+ if (nOptions < sizeof(vm_options) / sizeof(JavaVMOption))
+ add_option("", option, &vm_options[nOptions++]);
+ else
+ {
+ free(buf);
+ for (unsigned int i = 0; i < nOptions; i++)
+ delete vm_options[i].optionString;
+ PyErr_Format(PyExc_ValueError, "Too many options (> %d)",
+ nOptions);
+ return NULL;
+ }
+ }
+ free(buf);
+ }
+
+ //vm_options[nOptions++].optionString = "-verbose:gc";
+ //vm_options[nOptions++].optionString = "-Xcheck:jni";
+
+ vm_args.nOptions = nOptions;
+ vm_args.ignoreUnrecognized = JNI_FALSE;
+ vm_args.options = vm_options;
+
+ if (JNI_CreateJavaVM(&vm, (void **) &vm_env, &vm_args) < 0)
+ {
+ for (unsigned int i = 0; i < nOptions; i++)
+ delete vm_options[i].optionString;
+
+ PyErr_Format(PyExc_ValueError,
+ "An error occurred while creating Java VM");
+ return NULL;
+ }
+
+ env->set_vm(vm, vm_env);
+
+ for (unsigned int i = 0; i < nOptions; i++)
+ delete vm_options[i].optionString;
+
+ t_jccenv *jccenv = (t_jccenv *) JCCEnv$$Type.tp_alloc(&JCCEnv$$Type, 0);
+ jccenv->env = env;
+
+#ifdef _jcc_lib
+ registerNatives(vm_env);
+#endif
+
+ return (PyObject *) jccenv;
+ }
+}
+
+extern "C" {
+
+#ifdef _jcc_lib
+ static void raise_error(JNIEnv *vm_env, const char *message)
+ {
+ jclass cls = vm_env->FindClass("org/apache/jcc/PythonException");
+ vm_env->ThrowNew(cls, message);
+ }
+
+ JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved)
+ {
+ JNIEnv *vm_env;
+
+ if (!vm->GetEnv((void **) &vm_env, JNI_VERSION_1_4))
+ env = new JCCEnv(vm, vm_env);
+
+ registerNatives(vm_env);
+
+ return JNI_VERSION_1_4;
+ }
+
+ JNIEXPORT void JNICALL Java_org_apache_jcc_PythonVM_init(JNIEnv *vm_env, jobject self, jstring programName, jobjectArray args)
+ {
+ const char *str = vm_env->GetStringUTFChars(programName, JNI_FALSE);
+#ifdef linux
+ char buf[32];
+
+ // load python runtime for other .so modules to link (such as _time.so)
+ sprintf(buf, "libpython%d.%d.so", PY_MAJOR_VERSION, PY_MINOR_VERSION);
+ dlopen(buf, RTLD_NOW | RTLD_GLOBAL);
+#endif
+
+ Py_SetProgramName((char *) str);
+
+ PyEval_InitThreads();
+ Py_Initialize();
+
+ if (args)
+ {
+ int argc = vm_env->GetArrayLength(args);
+ char **argv = (char **) calloc(argc + 1, sizeof(char *));
+
+ argv[0] = (char *) str;
+ for (int i = 0; i < argc; i++) {
+ jstring arg = (jstring) vm_env->GetObjectArrayElement(args, i);
+ argv[i + 1] = (char *) vm_env->GetStringUTFChars(arg, JNI_FALSE);
+ }
+
+ PySys_SetArgv(argc + 1, argv);
+
+ for (int i = 0; i < argc; i++) {
+ jstring arg = (jstring) vm_env->GetObjectArrayElement(args, i);
+ vm_env->ReleaseStringUTFChars(arg, argv[i + 1]);
+ }
+ free(argv);
+ }
+ else
+ PySys_SetArgv(1, (char **) &str);
+
+ vm_env->ReleaseStringUTFChars(programName, str);
+ PyEval_ReleaseLock();
+ }
+
+ JNIEXPORT jobject JNICALL Java_org_apache_jcc_PythonVM_instantiate(JNIEnv *vm_env, jobject self, jstring moduleName, jstring className)
+ {
+ PythonGIL gil(vm_env);
+
+ const char *modStr = vm_env->GetStringUTFChars(moduleName, JNI_FALSE);
+ PyObject *module =
+ PyImport_ImportModule((char *) modStr); // python 2.4 cast
+
+ vm_env->ReleaseStringUTFChars(moduleName, modStr);
+
+ if (!module)
+ {
+ raise_error(vm_env, "import failed");
+ return NULL;
+ }
+
+ const char *clsStr = vm_env->GetStringUTFChars(className, JNI_FALSE);
+ PyObject *cls =
+ PyObject_GetAttrString(module, (char *) clsStr); // python 2.4 cast
+ PyObject *obj;
+ jobject jobj;
+
+ vm_env->ReleaseStringUTFChars(className, clsStr);
+ Py_DECREF(module);
+
+ if (!cls)
+ {
+ raise_error(vm_env, "class not found");
+ return NULL;
+ }
+
+ obj = PyObject_CallFunctionObjArgs(cls, NULL);
+ Py_DECREF(cls);
+
+ if (!obj)
+ {
+ raise_error(vm_env, "instantiation failed");
+ return NULL;
+ }
+
+ PyObject *cObj = PyObject_GetAttrString(obj, "_jobject");
+
+ if (!cObj)
+ {
+ raise_error(vm_env, "instance does not proxy a java object");
+ Py_DECREF(obj);
+
+ return NULL;
+ }
+
+ jobj = (jobject) PyCObject_AsVoidPtr(cObj);
+ Py_DECREF(cObj);
+
+ jobj = vm_env->NewLocalRef(jobj);
+ Py_DECREF(obj);
+
+ return jobj;
+ }
+#endif
+
+ void JNICALL PythonException_getErrorInfo(JNIEnv *vm_env, jobject self)
+ {
+ PythonGIL gil(vm_env);
+
+ if (!PyErr_Occurred())
+ return;
+
+ PyObject *type, *value, *tb, *errorName;
+ jclass jcls = vm_env->GetObjectClass(self);
+
+ PyErr_Fetch(&type, &value, &tb);
+
+ errorName = PyObject_GetAttrString(type, "__name__");
+ if (errorName != NULL)
+ {
+ jfieldID fid =
+ vm_env->GetFieldID(jcls, "errorName", "Ljava/lang/String;");
+ jstring str = env->fromPyString(errorName);
+
+ vm_env->SetObjectField(self, fid, str);
+ vm_env->DeleteLocalRef(str);
+ Py_DECREF(errorName);
+ }
+
+ if (value != NULL)
+ {
+ PyObject *message = PyObject_Str(value);
+
+ if (message != NULL)
+ {
+ jfieldID fid =
+ vm_env->GetFieldID(jcls, "message", "Ljava/lang/String;");
+ jstring str = env->fromPyString(message);
+
+ vm_env->SetObjectField(self, fid, str);
+ vm_env->DeleteLocalRef(str);
+ Py_DECREF(message);
+ }
+ }
+
+ PyObject *module = NULL, *cls = NULL, *stringIO = NULL, *result = NULL;
+ PyObject *_stderr = PySys_GetObject("stderr");
+ if (!_stderr)
+ goto err;
+
+ module = PyImport_ImportModule("cStringIO");
+ if (!module)
+ goto err;
+
+ cls = PyObject_GetAttrString(module, "StringIO");
+ Py_DECREF(module);
+ if (!cls)
+ goto err;
+
+ stringIO = PyObject_CallObject(cls, NULL);
+ Py_DECREF(cls);
+ if (!stringIO)
+ goto err;
+
+ Py_INCREF(_stderr);
+ PySys_SetObject("stderr", stringIO);
+
+ PyErr_Restore(type, value, tb);
+ PyErr_Print();
+
+ result = PyObject_CallMethod(stringIO, "getvalue", NULL);
+ Py_DECREF(stringIO);
+
+ if (result != NULL)
+ {
+ jfieldID fid =
+ vm_env->GetFieldID(jcls, "traceback", "Ljava/lang/String;");
+ jstring str = env->fromPyString(result);
+
+ vm_env->SetObjectField(self, fid, str);
+ vm_env->DeleteLocalRef(str);
+ Py_DECREF(result);
+ }
+
+ PySys_SetObject("stderr", _stderr);
+ Py_DECREF(_stderr);
+
+ return;
+
+ err:
+ PyErr_Restore(type, value, tb);
+ }
+
+ void JNICALL PythonException_clear(JNIEnv *vm_env, jobject self)
+ {
+ PythonGIL gil(vm_env);
+ PyErr_Clear();
+ }
+};
+
+#ifdef _jcc_lib
+static void registerNatives(JNIEnv *vm_env)
+{
+ jclass cls = vm_env->FindClass("org/apache/jcc/PythonException");
+ JNINativeMethod methods[] = {
+ { "getErrorInfo", "()V", (void *) PythonException_getErrorInfo },
+ { "clear", "()V", (void *) PythonException_clear },
+ };
+
+ vm_env->RegisterNatives(cls, methods, 2);
+}
+#endif