web/lib/arch/osx/jcc/sources/jcc.cpp
changeset 29 cc9b7e14412b
equal deleted inserted replaced
28:b758351d191f 29:cc9b7e14412b
       
     1 /*
       
     2  *   Licensed under the Apache License, Version 2.0 (the "License");
       
     3  *   you may not use this file except in compliance with the License.
       
     4  *   You may obtain a copy of the License at
       
     5  *
       
     6  *       http://www.apache.org/licenses/LICENSE-2.0
       
     7  *
       
     8  *   Unless required by applicable law or agreed to in writing, software
       
     9  *   distributed under the License is distributed on an "AS IS" BASIS,
       
    10  *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
       
    11  *   See the License for the specific language governing permissions and
       
    12  *   limitations under the License.
       
    13  */
       
    14 
       
    15 #include <stdio.h>
       
    16 #include <stdlib.h>
       
    17 #include <string.h>
       
    18 #include <jni.h>
       
    19 #ifdef linux
       
    20 #include <dlfcn.h>
       
    21 #endif
       
    22 
       
    23 #include <Python.h>
       
    24 #include "structmember.h"
       
    25 
       
    26 #include "JObject.h"
       
    27 #include "JCCEnv.h"
       
    28 #include "macros.h"
       
    29 
       
    30 _DLL_EXPORT JCCEnv *env;
       
    31 
       
    32 
       
    33 /* JCCEnv */
       
    34 
       
    35 class t_jccenv {
       
    36 public:
       
    37     PyObject_HEAD
       
    38     JCCEnv *env;
       
    39 };
       
    40     
       
    41 static void t_jccenv_dealloc(t_jccenv *self);
       
    42 static PyObject *t_jccenv_attachCurrentThread(PyObject *self, PyObject *args);
       
    43 static PyObject *t_jccenv_detachCurrentThread(PyObject *self);
       
    44 static PyObject *t_jccenv_isCurrentThreadAttached(PyObject *self);
       
    45 static PyObject *t_jccenv_strhash(PyObject *self, PyObject *arg);
       
    46 static PyObject *t_jccenv__dumpRefs(PyObject *self,
       
    47                                     PyObject *args, PyObject *kwds);
       
    48 static PyObject *t_jccenv__get_jni_version(PyObject *self, void *data);
       
    49 static PyObject *t_jccenv__get_java_version(PyObject *self, void *data);
       
    50 
       
    51 static PyGetSetDef t_jccenv_properties[] = {
       
    52     { "jni_version", (getter) t_jccenv__get_jni_version, NULL, NULL, NULL },
       
    53     { "java_version", (getter) t_jccenv__get_java_version, NULL, NULL, NULL },
       
    54     { NULL, NULL, NULL, NULL, NULL }
       
    55 };
       
    56 
       
    57 static PyMemberDef t_jccenv_members[] = {
       
    58     { NULL, 0, 0, 0, NULL }
       
    59 };
       
    60 
       
    61 static PyMethodDef t_jccenv_methods[] = {
       
    62     { "attachCurrentThread", (PyCFunction) t_jccenv_attachCurrentThread,
       
    63       METH_VARARGS, NULL },
       
    64     { "detachCurrentThread", (PyCFunction) t_jccenv_detachCurrentThread,
       
    65       METH_NOARGS, NULL },
       
    66     { "isCurrentThreadAttached", (PyCFunction) t_jccenv_isCurrentThreadAttached,
       
    67       METH_NOARGS, NULL },
       
    68     { "strhash", (PyCFunction) t_jccenv_strhash,
       
    69       METH_O, NULL },
       
    70     { "_dumpRefs", (PyCFunction) t_jccenv__dumpRefs,
       
    71       METH_VARARGS | METH_KEYWORDS, NULL },
       
    72     { NULL, NULL, 0, NULL }
       
    73 };
       
    74 
       
    75 PyTypeObject JCCEnv$$Type = {
       
    76     PyObject_HEAD_INIT(NULL)
       
    77     0,                                   /* ob_size */
       
    78     "jcc.JCCEnv",                        /* tp_name */
       
    79     sizeof(t_jccenv),                    /* tp_basicsize */
       
    80     0,                                   /* tp_itemsize */
       
    81     (destructor)t_jccenv_dealloc,        /* tp_dealloc */
       
    82     0,                                   /* tp_print */
       
    83     0,                                   /* tp_getattr */
       
    84     0,                                   /* tp_setattr */
       
    85     0,                                   /* tp_compare */
       
    86     0,                                   /* tp_repr */
       
    87     0,                                   /* tp_as_number */
       
    88     0,                                   /* tp_as_sequence */
       
    89     0,                                   /* tp_as_mapping */
       
    90     0,                                   /* tp_hash  */
       
    91     0,                                   /* tp_call */
       
    92     0,                                   /* tp_str */
       
    93     0,                                   /* tp_getattro */
       
    94     0,                                   /* tp_setattro */
       
    95     0,                                   /* tp_as_buffer */
       
    96     Py_TPFLAGS_DEFAULT,                  /* tp_flags */
       
    97     "JCCEnv",                            /* tp_doc */
       
    98     0,                                   /* tp_traverse */
       
    99     0,                                   /* tp_clear */
       
   100     0,                                   /* tp_richcompare */
       
   101     0,                                   /* tp_weaklistoffset */
       
   102     0,                                   /* tp_iter */
       
   103     0,                                   /* tp_iternext */
       
   104     t_jccenv_methods,                    /* tp_methods */
       
   105     t_jccenv_members,                    /* tp_members */
       
   106     t_jccenv_properties,                 /* tp_getset */
       
   107     0,                                   /* tp_getset */
       
   108     0,                                   /* tp_base */
       
   109     0,                                   /* tp_dict */
       
   110     0,                                   /* tp_descr_get */
       
   111     0,                                   /* tp_descr_set */
       
   112     0,                                   /* tp_dictoffset */
       
   113     0,                                   /* tp_init */
       
   114     0,                                   /* tp_alloc */
       
   115     0,                                   /* tp_new */
       
   116 };
       
   117 
       
   118 static void t_jccenv_dealloc(t_jccenv *self)
       
   119 {
       
   120     self->ob_type->tp_free((PyObject *) self);
       
   121 }
       
   122 
       
   123 static void add_option(char *name, char *value, JavaVMOption *option)
       
   124 {
       
   125     char *buf = new char[strlen(name) + strlen(value) + 1];
       
   126 
       
   127     sprintf(buf, "%s%s", name, value);
       
   128     option->optionString = buf;
       
   129 }
       
   130 
       
   131 #ifdef _jcc_lib
       
   132 static void add_paths(char *name, char *p0, char *p1, JavaVMOption *option)
       
   133 {
       
   134 #if defined(_MSC_VER) || defined(__WIN32)
       
   135     char pathsep = ';';
       
   136 #else
       
   137     char pathsep = ':';
       
   138 #endif
       
   139     char *buf = new char[strlen(name) + strlen(p0) + strlen(p1) + 4];
       
   140 
       
   141     sprintf(buf, "%s%s%c%s", name, p0, pathsep, p1);
       
   142     option->optionString = buf;
       
   143 }
       
   144 #endif
       
   145 
       
   146 
       
   147 static PyObject *t_jccenv_attachCurrentThread(PyObject *self, PyObject *args)
       
   148 {
       
   149     char *name = NULL;
       
   150     int asDaemon = 0, result;
       
   151     JNIEnv *jenv = NULL;
       
   152 
       
   153     if (!PyArg_ParseTuple(args, "|si", &name, &asDaemon))
       
   154         return NULL;
       
   155 
       
   156     JavaVMAttachArgs attach = {
       
   157         JNI_VERSION_1_4, name, NULL
       
   158     };
       
   159 
       
   160     if (asDaemon)
       
   161         result = env->vm->AttachCurrentThreadAsDaemon((void **) &jenv, &attach);
       
   162     else
       
   163         result = env->vm->AttachCurrentThread((void **) &jenv, &attach);
       
   164 
       
   165     env->set_vm_env(jenv);
       
   166         
       
   167     return PyInt_FromLong(result);
       
   168 }
       
   169 
       
   170 static PyObject *t_jccenv_detachCurrentThread(PyObject *self)
       
   171 {
       
   172     int result = env->vm->DetachCurrentThread();
       
   173 
       
   174     env->set_vm_env(NULL);
       
   175 
       
   176     return PyInt_FromLong(result);
       
   177 }
       
   178 
       
   179 static PyObject *t_jccenv_isCurrentThreadAttached(PyObject *self)
       
   180 {
       
   181     if (env->get_vm_env() != NULL)
       
   182         Py_RETURN_TRUE;
       
   183 
       
   184     Py_RETURN_FALSE;
       
   185 }
       
   186 
       
   187 static PyObject *t_jccenv_strhash(PyObject *self, PyObject *arg)
       
   188 {
       
   189     int hash = PyObject_Hash(arg);
       
   190     char buffer[10];
       
   191 
       
   192     sprintf(buffer, "%08x", (unsigned int) hash);
       
   193     return PyString_FromStringAndSize(buffer, 8);
       
   194 }
       
   195 
       
   196 static PyObject *t_jccenv__dumpRefs(PyObject *self,
       
   197                                     PyObject *args, PyObject *kwds)
       
   198 {
       
   199     static char *kwnames[] = {
       
   200         "classes", "values", NULL
       
   201     };
       
   202     int classes = 0, values = 0;
       
   203     PyObject *result;
       
   204 
       
   205     if (!PyArg_ParseTupleAndKeywords(args, kwds, "|ii", kwnames,
       
   206                                      &classes, &values))
       
   207         return NULL;
       
   208 
       
   209     if (classes)
       
   210         result = PyDict_New();
       
   211     else
       
   212         result = PyList_New(env->refs.size());
       
   213 
       
   214     int count = 0;
       
   215 
       
   216     for (std::multimap<int, countedRef>::iterator iter = env->refs.begin();
       
   217          iter != env->refs.end();
       
   218          iter++) {
       
   219         if (classes)  // return dict of { class name: instance count }
       
   220         {
       
   221             char *name = env->getClassName(iter->second.global);
       
   222             PyObject *key = PyString_FromString(name);
       
   223             PyObject *value = PyDict_GetItem(result, key);
       
   224 
       
   225             if (value == NULL)
       
   226                 value = PyInt_FromLong(1);
       
   227             else
       
   228                 value = PyInt_FromLong(PyInt_AS_LONG(value) + 1);
       
   229 
       
   230             PyDict_SetItem(result, key, value);
       
   231             Py_DECREF(key);
       
   232             Py_DECREF(value);
       
   233 
       
   234             delete name;
       
   235         }
       
   236         else if (values)  // return list of (value string, ref count)
       
   237         {
       
   238             char *str = env->toString(iter->second.global);
       
   239             PyObject *key = PyString_FromString(str);
       
   240             PyObject *value = PyInt_FromLong(iter->second.count);
       
   241 
       
   242 #if PY_VERSION_HEX < 0x02040000
       
   243             PyList_SET_ITEM(result, count++, Py_BuildValue("(OO)", key, value));
       
   244 #else
       
   245             PyList_SET_ITEM(result, count++, PyTuple_Pack(2, key, value));
       
   246 #endif
       
   247             Py_DECREF(key);
       
   248             Py_DECREF(value);
       
   249 
       
   250             delete str;
       
   251         }
       
   252         else  // return list of (id hash code, ref count)
       
   253         {
       
   254             PyObject *key = PyInt_FromLong(iter->first);
       
   255             PyObject *value = PyInt_FromLong(iter->second.count);
       
   256 
       
   257 #if PY_VERSION_HEX < 0x02040000
       
   258             PyList_SET_ITEM(result, count++, Py_BuildValue("(OO)", key, value));
       
   259 #else
       
   260             PyList_SET_ITEM(result, count++, PyTuple_Pack(2, key, value));
       
   261 #endif
       
   262             Py_DECREF(key);
       
   263             Py_DECREF(value);
       
   264         }
       
   265     }
       
   266 
       
   267     return result;
       
   268 }
       
   269 
       
   270 
       
   271 static PyObject *t_jccenv__get_jni_version(PyObject *self, void *data)
       
   272 {
       
   273     return PyInt_FromLong(env->getJNIVersion());
       
   274 }
       
   275 
       
   276 static PyObject *t_jccenv__get_java_version(PyObject *self, void *data)
       
   277 {
       
   278     return env->fromJString(env->getJavaVersion(), 1);
       
   279 }
       
   280 
       
   281 _DLL_EXPORT PyObject *getVMEnv(PyObject *self)
       
   282 {
       
   283     if (env->vm != NULL)
       
   284     {
       
   285         t_jccenv *jccenv = (t_jccenv *) JCCEnv$$Type.tp_alloc(&JCCEnv$$Type, 0);
       
   286         jccenv->env = env;
       
   287 
       
   288         return (PyObject *) jccenv;
       
   289     }
       
   290 
       
   291     Py_RETURN_NONE;
       
   292 }
       
   293 
       
   294 #ifdef _jcc_lib
       
   295 static void registerNatives(JNIEnv *vm_env);
       
   296 #endif
       
   297 
       
   298 _DLL_EXPORT PyObject *initJCC(PyObject *module)
       
   299 {
       
   300     static int _once_only = 1;
       
   301 
       
   302     if (_once_only)
       
   303     {
       
   304         PyEval_InitThreads();
       
   305         INSTALL_TYPE(JCCEnv, module);
       
   306 
       
   307         if (env == NULL)
       
   308             env = new JCCEnv(NULL, NULL);
       
   309 
       
   310         _once_only = 0;
       
   311         Py_RETURN_TRUE;
       
   312     }
       
   313 
       
   314     Py_RETURN_FALSE;
       
   315 }
       
   316 
       
   317 _DLL_EXPORT PyObject *initVM(PyObject *self, PyObject *args, PyObject *kwds)
       
   318 {
       
   319     static char *kwnames[] = {
       
   320         "classpath", "initialheap", "maxheap", "maxstack",
       
   321         "vmargs", NULL
       
   322     };
       
   323     char *classpath = NULL;
       
   324     char *initialheap = NULL, *maxheap = NULL, *maxstack = NULL;
       
   325     char *vmargs = NULL;
       
   326 
       
   327     if (!PyArg_ParseTupleAndKeywords(args, kwds, "|zzzzz", kwnames,
       
   328                                      &classpath,
       
   329                                      &initialheap, &maxheap, &maxstack,
       
   330                                      &vmargs))
       
   331         return NULL;
       
   332 
       
   333     if (env->vm)
       
   334     {
       
   335         PyObject *module_cp = NULL;
       
   336 
       
   337         if (initialheap || maxheap || maxstack || vmargs)
       
   338         {
       
   339             PyErr_SetString(PyExc_ValueError,
       
   340                             "JVM is already running, options are ineffective");
       
   341             return NULL;
       
   342         }
       
   343 
       
   344         if (classpath == NULL && self != NULL)
       
   345         {
       
   346             module_cp = PyObject_GetAttrString(self, "CLASSPATH");
       
   347             if (module_cp != NULL)
       
   348                 classpath = PyString_AsString(module_cp);
       
   349         }
       
   350 
       
   351         if (classpath && classpath[0])
       
   352             env->setClassPath(classpath);
       
   353 
       
   354         Py_XDECREF(module_cp);
       
   355 
       
   356         return getVMEnv(self);
       
   357     }
       
   358     else
       
   359     {
       
   360         JavaVMInitArgs vm_args;
       
   361         JavaVMOption vm_options[32];
       
   362         JNIEnv *vm_env;
       
   363         JavaVM *vm;
       
   364         unsigned int nOptions = 0;
       
   365         PyObject *module_cp = NULL;
       
   366 
       
   367         vm_args.version = JNI_VERSION_1_4;
       
   368         JNI_GetDefaultJavaVMInitArgs(&vm_args);
       
   369 
       
   370         if (classpath == NULL && self != NULL)
       
   371         {
       
   372             module_cp = PyObject_GetAttrString(self, "CLASSPATH");
       
   373             if (module_cp != NULL)
       
   374                 classpath = PyString_AsString(module_cp);
       
   375         }
       
   376 
       
   377 #ifdef _jcc_lib
       
   378         PyObject *jcc = PyImport_ImportModule("jcc");
       
   379         PyObject *cp = PyObject_GetAttrString(jcc, "CLASSPATH");
       
   380 
       
   381         if (classpath)
       
   382             add_paths("-Djava.class.path=", PyString_AsString(cp), classpath,
       
   383                       &vm_options[nOptions++]);
       
   384         else
       
   385             add_option("-Djava.class.path=", PyString_AsString(cp),
       
   386                        &vm_options[nOptions++]);
       
   387             
       
   388         Py_DECREF(cp);
       
   389         Py_DECREF(jcc);
       
   390 #else
       
   391         if (classpath)
       
   392             add_option("-Djava.class.path=", classpath,
       
   393                        &vm_options[nOptions++]);
       
   394 #endif
       
   395 
       
   396         Py_XDECREF(module_cp);
       
   397 
       
   398         if (initialheap)
       
   399             add_option("-Xms", initialheap, &vm_options[nOptions++]);
       
   400         if (maxheap)
       
   401             add_option("-Xmx", maxheap, &vm_options[nOptions++]);
       
   402         if (maxstack)
       
   403             add_option("-Xss", maxstack, &vm_options[nOptions++]);
       
   404 
       
   405         if (vmargs)
       
   406         {
       
   407             char *buf = strdup(vmargs);
       
   408             char *sep = ",";
       
   409             char *option;
       
   410 
       
   411             for (option = strtok(buf, sep); option; option = strtok(NULL, sep))
       
   412             {
       
   413                 if (nOptions < sizeof(vm_options) / sizeof(JavaVMOption))
       
   414                     add_option("", option, &vm_options[nOptions++]);
       
   415                 else
       
   416                 {
       
   417                     free(buf);
       
   418                     for (unsigned int i = 0; i < nOptions; i++)
       
   419                         delete vm_options[i].optionString;
       
   420                     PyErr_Format(PyExc_ValueError, "Too many options (> %d)",
       
   421                                  nOptions);
       
   422                     return NULL;
       
   423                 }
       
   424             }
       
   425             free(buf);
       
   426         }
       
   427 
       
   428         //vm_options[nOptions++].optionString = "-verbose:gc";
       
   429         //vm_options[nOptions++].optionString = "-Xcheck:jni";
       
   430 
       
   431         vm_args.nOptions = nOptions;
       
   432         vm_args.ignoreUnrecognized = JNI_FALSE;
       
   433         vm_args.options = vm_options;
       
   434 
       
   435         if (JNI_CreateJavaVM(&vm, (void **) &vm_env, &vm_args) < 0)
       
   436         {
       
   437             for (unsigned int i = 0; i < nOptions; i++)
       
   438                 delete vm_options[i].optionString;
       
   439 
       
   440             PyErr_Format(PyExc_ValueError,
       
   441                          "An error occurred while creating Java VM");
       
   442             return NULL;
       
   443         }
       
   444 
       
   445         env->set_vm(vm, vm_env);
       
   446 
       
   447         for (unsigned int i = 0; i < nOptions; i++)
       
   448             delete vm_options[i].optionString;
       
   449 
       
   450         t_jccenv *jccenv = (t_jccenv *) JCCEnv$$Type.tp_alloc(&JCCEnv$$Type, 0);
       
   451         jccenv->env = env;
       
   452 
       
   453 #ifdef _jcc_lib
       
   454         registerNatives(vm_env);
       
   455 #endif
       
   456 
       
   457         return (PyObject *) jccenv;
       
   458     }
       
   459 }
       
   460 
       
   461 extern "C" {
       
   462 
       
   463 #ifdef _jcc_lib
       
   464     static void raise_error(JNIEnv *vm_env, const char *message)
       
   465     {
       
   466         jclass cls = vm_env->FindClass("org/apache/jcc/PythonException");
       
   467         vm_env->ThrowNew(cls, message);
       
   468     }
       
   469 
       
   470     JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved)
       
   471     {
       
   472         JNIEnv *vm_env;
       
   473 
       
   474         if (!vm->GetEnv((void **) &vm_env, JNI_VERSION_1_4))
       
   475             env = new JCCEnv(vm, vm_env);
       
   476 
       
   477         registerNatives(vm_env);
       
   478 
       
   479         return JNI_VERSION_1_4;
       
   480     }
       
   481 
       
   482     JNIEXPORT void JNICALL Java_org_apache_jcc_PythonVM_init(JNIEnv *vm_env, jobject self, jstring programName, jobjectArray args)
       
   483     {
       
   484         const char *str = vm_env->GetStringUTFChars(programName, JNI_FALSE);
       
   485 #ifdef linux
       
   486         char buf[32];
       
   487 
       
   488         // load python runtime for other .so modules to link (such as _time.so)
       
   489         sprintf(buf, "libpython%d.%d.so", PY_MAJOR_VERSION, PY_MINOR_VERSION);
       
   490         dlopen(buf, RTLD_NOW | RTLD_GLOBAL);
       
   491 #endif
       
   492 
       
   493 	Py_SetProgramName((char *) str);
       
   494 
       
   495         PyEval_InitThreads();
       
   496 	Py_Initialize();
       
   497 
       
   498         if (args)
       
   499         {
       
   500             int argc = vm_env->GetArrayLength(args);
       
   501             char **argv = (char **) calloc(argc + 1, sizeof(char *));
       
   502 
       
   503             argv[0] = (char *) str;
       
   504             for (int i = 0; i < argc; i++) {
       
   505                 jstring arg = (jstring) vm_env->GetObjectArrayElement(args, i);
       
   506                 argv[i + 1] = (char *) vm_env->GetStringUTFChars(arg, JNI_FALSE);
       
   507             }
       
   508 
       
   509             PySys_SetArgv(argc + 1, argv);
       
   510 
       
   511             for (int i = 0; i < argc; i++) {
       
   512                 jstring arg = (jstring) vm_env->GetObjectArrayElement(args, i);
       
   513                 vm_env->ReleaseStringUTFChars(arg, argv[i + 1]);
       
   514             }
       
   515             free(argv);
       
   516         }
       
   517         else
       
   518             PySys_SetArgv(1, (char **) &str);
       
   519 
       
   520         vm_env->ReleaseStringUTFChars(programName, str);
       
   521         PyEval_ReleaseLock();
       
   522     }
       
   523 
       
   524     JNIEXPORT jobject JNICALL Java_org_apache_jcc_PythonVM_instantiate(JNIEnv *vm_env, jobject self, jstring moduleName, jstring className)
       
   525     {
       
   526         PythonGIL gil(vm_env);
       
   527 
       
   528         const char *modStr = vm_env->GetStringUTFChars(moduleName, JNI_FALSE);
       
   529         PyObject *module =
       
   530             PyImport_ImportModule((char *) modStr);  // python 2.4 cast
       
   531 
       
   532         vm_env->ReleaseStringUTFChars(moduleName, modStr);
       
   533 
       
   534         if (!module)
       
   535         {
       
   536             raise_error(vm_env, "import failed");
       
   537             return NULL;
       
   538         }
       
   539 
       
   540         const char *clsStr = vm_env->GetStringUTFChars(className, JNI_FALSE);
       
   541         PyObject *cls =
       
   542             PyObject_GetAttrString(module, (char *) clsStr); // python 2.4 cast
       
   543         PyObject *obj;
       
   544         jobject jobj;
       
   545 
       
   546         vm_env->ReleaseStringUTFChars(className, clsStr);
       
   547         Py_DECREF(module);
       
   548 
       
   549         if (!cls)
       
   550         {
       
   551             raise_error(vm_env, "class not found");
       
   552             return NULL;
       
   553         }
       
   554 
       
   555         obj = PyObject_CallFunctionObjArgs(cls, NULL);
       
   556         Py_DECREF(cls);
       
   557 
       
   558         if (!obj)
       
   559         {
       
   560             raise_error(vm_env, "instantiation failed");
       
   561             return NULL;
       
   562         }
       
   563 
       
   564         PyObject *cObj = PyObject_GetAttrString(obj, "_jobject");
       
   565 
       
   566         if (!cObj)
       
   567         {
       
   568             raise_error(vm_env, "instance does not proxy a java object");
       
   569             Py_DECREF(obj);
       
   570 
       
   571             return NULL;
       
   572         }
       
   573 
       
   574         jobj = (jobject) PyCObject_AsVoidPtr(cObj);
       
   575         Py_DECREF(cObj);
       
   576 
       
   577         jobj = vm_env->NewLocalRef(jobj);
       
   578         Py_DECREF(obj);
       
   579 
       
   580         return jobj;
       
   581     }
       
   582 #endif
       
   583 
       
   584     void JNICALL PythonException_getErrorInfo(JNIEnv *vm_env, jobject self)
       
   585     {
       
   586         PythonGIL gil(vm_env);
       
   587 
       
   588         if (!PyErr_Occurred())
       
   589             return;
       
   590 
       
   591         PyObject *type, *value, *tb, *errorName;
       
   592         jclass jcls = vm_env->GetObjectClass(self);
       
   593 
       
   594         PyErr_Fetch(&type, &value, &tb);
       
   595 
       
   596         errorName = PyObject_GetAttrString(type, "__name__");
       
   597         if (errorName != NULL)
       
   598         {
       
   599             jfieldID fid =
       
   600                 vm_env->GetFieldID(jcls, "errorName", "Ljava/lang/String;");
       
   601             jstring str = env->fromPyString(errorName);
       
   602 
       
   603             vm_env->SetObjectField(self, fid, str);
       
   604             vm_env->DeleteLocalRef(str);
       
   605             Py_DECREF(errorName);
       
   606         }
       
   607 
       
   608         if (value != NULL)
       
   609         {
       
   610             PyObject *message = PyObject_Str(value);
       
   611 
       
   612             if (message != NULL)
       
   613             {
       
   614                 jfieldID fid =
       
   615                     vm_env->GetFieldID(jcls, "message", "Ljava/lang/String;");
       
   616                 jstring str = env->fromPyString(message);
       
   617 
       
   618                 vm_env->SetObjectField(self, fid, str);
       
   619                 vm_env->DeleteLocalRef(str);
       
   620                 Py_DECREF(message);
       
   621             }
       
   622         }
       
   623 
       
   624         PyObject *module = NULL, *cls = NULL, *stringIO = NULL, *result = NULL;
       
   625         PyObject *_stderr = PySys_GetObject("stderr");
       
   626         if (!_stderr)
       
   627             goto err;
       
   628 
       
   629         module = PyImport_ImportModule("cStringIO");
       
   630         if (!module)
       
   631             goto err;
       
   632 
       
   633         cls = PyObject_GetAttrString(module, "StringIO");
       
   634         Py_DECREF(module);
       
   635         if (!cls)
       
   636             goto err;
       
   637 
       
   638         stringIO = PyObject_CallObject(cls, NULL);
       
   639         Py_DECREF(cls);
       
   640         if (!stringIO)
       
   641             goto err;
       
   642 
       
   643         Py_INCREF(_stderr);
       
   644         PySys_SetObject("stderr", stringIO);
       
   645 
       
   646         PyErr_Restore(type, value, tb);
       
   647         PyErr_Print();
       
   648 
       
   649         result = PyObject_CallMethod(stringIO, "getvalue", NULL);
       
   650         Py_DECREF(stringIO);
       
   651 
       
   652         if (result != NULL)
       
   653         {
       
   654             jfieldID fid =
       
   655                 vm_env->GetFieldID(jcls, "traceback", "Ljava/lang/String;");
       
   656             jstring str = env->fromPyString(result);
       
   657 
       
   658             vm_env->SetObjectField(self, fid, str);
       
   659             vm_env->DeleteLocalRef(str);
       
   660             Py_DECREF(result);
       
   661         }
       
   662 
       
   663         PySys_SetObject("stderr", _stderr);
       
   664         Py_DECREF(_stderr);
       
   665 
       
   666         return;
       
   667 
       
   668       err:
       
   669         PyErr_Restore(type, value, tb);
       
   670     }
       
   671 
       
   672     void JNICALL PythonException_clear(JNIEnv *vm_env, jobject self)
       
   673     {
       
   674         PythonGIL gil(vm_env);
       
   675         PyErr_Clear();
       
   676     }
       
   677 };
       
   678 
       
   679 #ifdef _jcc_lib
       
   680 static void registerNatives(JNIEnv *vm_env)
       
   681 {
       
   682     jclass cls = vm_env->FindClass("org/apache/jcc/PythonException");
       
   683     JNINativeMethod methods[] = {
       
   684         { "getErrorInfo", "()V", (void *) PythonException_getErrorInfo },
       
   685         { "clear", "()V", (void *) PythonException_clear },
       
   686     };
       
   687 
       
   688     vm_env->RegisterNatives(cls, methods, 2);
       
   689 }
       
   690 #endif