/* indent-tabs-mode: nil -*- */
/*
qore Python module
Copyright (C) 2020 - 2021 Qore Technologies, s.r.o.
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 2.1 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
*/
#include "JavaLoader.h"
#include "QoreMetaPathFinder.h"
#include "QorePythonProgram.h"
#include "PythonQoreClass.h"
#include "ModuleNamespace.h"
#include
#include
QorePythonManualReferenceHolder JavaLoader::loader_cls;
QorePythonManualReferenceHolder JavaLoader::loader;
static PyMethodDef JavaLoader_methods[] = {
{"create_module", JavaLoader::create_module, METH_VARARGS, "JavaLoader.create_module() implementation"},
{"exec_module", JavaLoader::exec_module, METH_VARARGS, "JavaLoader.exec_module() implementation"},
{nullptr, nullptr},
};
PyDoc_STRVAR(JavaLoader_doc,
"JavaLoader()\n\
\n\
Python modules for Java through the Qore library.");
PyTypeObject JavaLoader_Type = {
PyVarObject_HEAD_INIT(nullptr, 0)
"JavaLoader", // tp_name
0, // tp_basicsize
0, // tp_itemsize
// Slots
(destructor)JavaLoader::dealloc, // tp_dealloc
0, // tp_vectorcall_offset
0, // tp_getattr
0, // tp_setattr
0, // tp_as_async
JavaLoader::repr, // tp_repr
0, // tp_as_number
0, // tp_as_sequence
0, // tp_as_mapping
0, // tp_hash
0, // tp_call
0, // tp_str
PyObject_GenericGetAttr, // tp_getattro
0, // tp_setattro
0, // tp_as_buffer
Py_TPFLAGS_DEFAULT, // tp_flags
JavaLoader_doc, // tp_doc
0, // tp_traverse
0, // tp_clear
0, // tp_richcompare
0, // tp_weaklistoffset
0, // tp_iter
0, // tp_iternext
JavaLoader_methods, // tp_methods
0, // tp_members
0, // tp_getset
&PyBaseObject_Type, // tp_base
0, // tp_dict
0, // tp_descr_get
0, // tp_descr_set
0, // tp_dictoffset
0, // tp_init
PyType_GenericAlloc, // tp_alloc
PyType_GenericNew, // tp_new
PyObject_Del, // tp_free
};
int JavaLoader::init() {
if (initModuleNamespace()) {
return -1;
}
if (PyType_Ready(&JavaLoader_Type) < 0) {
printd(5, "JavaLoader::init() type initialization failed\n");
return -1;
}
QorePythonReferenceHolder args(PyTuple_New(0));
loader = PyObject_CallObject((PyObject*)&JavaLoader_Type, *args);
//loader = PyObject_CallObject((PyObject*)*loader_cls, *args);
if (PyType_Ready(&PythonQoreException_Type) < 0) {
return -1;
}
return 0;
}
void JavaLoader::del() {
loader.purge();
loader_cls.purge();
}
PyObject* JavaLoader::getLoaderRef() {
assert(*loader);
Py_INCREF(*loader);
return *loader;
}
PyObject* JavaLoader::getLoader() {
assert(*loader);
return *loader;
}
void JavaLoader::dealloc(PyObject* self) {
//PyObject_GC_UnTrack(self);
Py_TYPE(self)->tp_free(self);
}
PyObject* JavaLoader::repr(PyObject* obj) {
QoreStringMaker str("JavaLoader object %p", obj);
return PyUnicode_FromStringAndSize(str.c_str(), str.size());
}
// class method functions
PyObject* JavaLoader::create_module(PyObject* self, PyObject* args) {
typedef QoreNamespace* (*jni_module_find_create_java_namespace_t)(QoreString& arg, QoreProgram* pgm);
static jni_module_find_create_java_namespace_t jni_module_find_create_java_namespace = nullptr;
QorePythonProgram* qore_python_pgm = QorePythonProgram::getContext();
if (!jni_module_find_create_java_namespace) {
if (load_jni_module(qore_python_pgm)) {
return nullptr;
}
jni_module_find_create_java_namespace = (jni_module_find_create_java_namespace_t)dlsym(RTLD_DEFAULT,
"jni_module_find_create_java_namespace");
if (!jni_module_find_create_java_namespace) {
PyErr_SetString(PyExc_ValueError, "cannot find required symbol 'jni_module_find_create_java_namespace'");
return nullptr;
}
}
QorePythonReferenceHolder argstr(PyObject_Repr(args));
printd(5, "JavaLoader::create_module() self: %p args: %s\n", self, PyUnicode_AsUTF8(*argstr));
if (!args || !PyTuple_Check(args) || !PyTuple_Size(args)) {
PyErr_SetString(PyExc_ValueError, "missing ModuleSpec arg to 'JavaLoader.create_module()'");
return nullptr;
}
// returns a borrowed reference
PyObject* spec = PyTuple_GetItem(args, 0);
// get name
QorePythonReferenceHolder name(PyObject_GetAttrString(spec, "name"));
if (!name || !PyUnicode_Check(*name)) {
PyErr_SetString(PyExc_ValueError, "ModuleSpec has no 'name' attribute");
return nullptr;
}
QoreString mname(PyUnicode_AsUTF8(*name));
assert(mname.equalPartial("java"));
// create new namespace
QoreProgram* mod_pgm = qore_python_pgm->getQoreProgram();
if (mname == "java") {
return qore_python_pgm->newModule("java", mod_pgm->getRootNS()->findLocalNamespace("Jni"));
}
// get the full Python module name
QoreString py_name = mname;
// remove "java." from the beginning of the string
mname.replace(0, 5, "");
// replace "." with "::"
mname.replaceAll(".", "::");
QoreNamespace* ns = jni_module_find_create_java_namespace(mname, mod_pgm);
if (!ns) {
QoreStringMaker desc("failed to create Java namespace '%s' in JavaLoader.create_module()", mname.c_str());
PyErr_SetString(PyExc_ValueError, desc.c_str());
return nullptr;
}
printd(5, "JavaLoader::create_module() '%s' ns: %s\n", py_name.c_str(), ns->getName());
return qore_python_pgm->newModule(py_name.c_str(), ns);
}
PyObject* JavaLoader::exec_module(PyObject* self, PyObject* args) {
assert(PyTuple_Check(args));
#ifdef _QORE_PYTHON_DEBUG_EXEC_MODULE_ARGS
QorePythonReferenceHolder argstr(PyObject_Repr(args));
assert(PyUnicode_Check(*argstr));
printd(5, "JavaLoader::exec_module() self: %p args: %s\n", self, PyUnicode_AsUTF8(*argstr));
#endif
// get module
// returns a borrowed reference
PyObject* mod = PyTuple_GetItem(args, 0);
assert(PyModule_Check(mod));
// get module name
assert(PyObject_HasAttrString(mod, "__name__"));
QorePythonReferenceHolder name(PyObject_GetAttrString(mod, "__name__"));
assert(PyUnicode_Check(*name));
const char* name_str = PyUnicode_AsUTF8(*name);
printd(5, "JavaLoader::exec_module() mod: '%s'\n", name_str);
QorePythonProgram* qore_python_pgm = QorePythonProgram::getContext();
QoreProgram* mod_pgm = qore_python_pgm->getQoreProgram();
printd(5, "JavaLoader::exec_module() qore_python_pgm: %p mod pgm: %p\n", qore_python_pgm, mod_pgm);
if (load_jni_module(qore_python_pgm)) {
return nullptr;
}
Py_INCREF(Py_None);
return Py_None;
}