#include "de_mrbesen_cppplugins_CppPlugin.h" #include "de_mrbesen_cppplugins_CppPlugin_CppListener.h" #include #include //dynamic linking #include //thread id #include "libplugin.h" #include "plugin.h" jclass CPPPLUGINCLASS; jclass EVENTCLASS; jclass MAPCLASS; jclass LISTENERCLASS; jfieldID EVENTDATAF; jfieldID EVENTNAMEF; jmethodID MAPGET; jmethodID MAPPUT; jmethodID MAPCLEAR; jmethodID LISTENERCONTR; jmethodID LISTENERSMALLCONTR; CppPlugin* plugin; //what happens, with more than one plugin? /* jint JNI_OnLoad(JavaVM *vm, void *reserved) { DEB("onload" ); JNIEnv* env; vm->GetEnv((void**) &env, JNI_VERSION_1_8); return JNI_VERSION_1_8; }*/ void fixcap(JNIEnv* env) { DEB("ensure 1024" ); env->EnsureLocalCapacity(1024); DEB("push frame 1024" ); env->PushLocalFrame(1024); } /* operator long()(JNIDATA d) { return (long) d; } long operator|(JNIDATA a, JNIDATA b) { return (long) a | (long) b; } long operator|(long a, JNIDATA b) { return a | (long) b; } long operator&(long a, JNIDATA b) { return a & (long) b; }*/ void load(JNIEnv* env, long data) { DEB("loading with mask: " << data); if(data & JNI_PLUGINCLASS) CPPPLUGINCLASS = env->FindClass("de/mrbesen/cppplugins/CppPlugin"); if(data & JNI_EVENTCLASS) EVENTCLASS = env->FindClass("de/mrbesen/cppplugins/CppEvent"); if(data & JNI_MAPCLASS) MAPCLASS = env->FindClass("java/util/Map"); if(data & JNI_LISTENERCLASS) LISTENERCLASS = env->FindClass("de/mrbesen/cppplugins/CppPlugin$CppListener"); DEB("find classes: " << (!!CPPPLUGINCLASS) << (!!EVENTCLASS) << (!!MAPCLASS) << (!!LISTENERCLASS)); if(data & JNI_EVENTDATAFIELD) EVENTDATAF = env->GetFieldID(EVENTCLASS, "data", "Ljava/util/Map;"); if(data & JNI_EVENTNAMEFIELD) EVENTNAMEF = env->GetFieldID(EVENTCLASS, "name", "Ljava/lang/String;"); DEB("findfields: " << (!!EVENTDATAF) << (!!EVENTNAMEF)); if(data & JNI_MAPGETMETH) MAPGET = env->GetMethodID(MAPCLASS, "get", "(Ljava/lang/Object;)Ljava/lang/Object;"); if(data & JNI_MAPPUTMETH) MAPPUT = env->GetMethodID(MAPCLASS, "put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"); if(data & JNI_MAPCLEARMETH) MAPCLEAR = env->GetMethodID(MAPCLASS, "clear", "()V"); if(data & JNI_LISTENERCONSTR) LISTENERCONTR = env->GetMethodID(LISTENERCLASS, "", "(Ljava/lang/String;J)V"); if(data & JNI_LISTENERSMALLCONSTR) LISTENERSMALLCONTR = env->GetMethodID(LISTENERCLASS, "", "()V"); DEB("find methods: " << (!!MAPGET) << (!!MAPPUT) << (!!MAPCLEAR) << (!!LISTENERCONTR) << (!!LISTENERSMALLCONTR)); } JNIEXPORT jboolean JNICALL Java_de_mrbesen_cppplugins_CppPlugin_init_1(JNIEnv* env, jobject thisobj) { load(env, JNI_ALL); return true; } /** * Class: de_mrbesen_cppplugins_CppPlugin * Method: loadPlugin * Signature: (Ljava/lang/String;)Z */ JNIEXPORT jboolean JNICALL Java_de_mrbesen_cppplugins_CppPlugin_loadPlugin(JNIEnv* env, jobject thisobj, jstring path) { const char* cpath = env->GetStringUTFChars(path, 0); //open plugin DEB("open plugin " << cpath ); void* handle = dlopen(cpath, RTLD_LAZY); if (!handle) { std::cout << "could not create handle of: " << cpath << " error: " << dlerror() << std::endl; return false; } //throw std::string("Error: plugin could not be opend. ") + dlerror(); //load function pointer initfptr initf = (initfptr) dlsym(handle, "init"); if(!initf) { std::cout << "Could not find function init: " << dlerror() << std::endl; dlclose(handle); return false; } plugin = initf(); plugin->handle = handle; //store data //setData(data, env, thisobj); DEB("plugin: " << (bool)plugin); return (bool) plugin; // converted to boolean here } /* * Class: de_mrbesen_cppplugins_CppPlugin * Method: onLoad * Signature: ()V */ JNIEXPORT void JNICALL Java_de_mrbesen_cppplugins_CppPlugin_onLoad(JNIEnv* env, jobject thisobj) { //TODO DEB("lib::onLoad()"); plugin->onLoad(); } /* * Class: de_mrbesen_cppplugins_CppPlugin * Method: onEnable_ * Signature: ()V */ JNIEXPORT void JNICALL Java_de_mrbesen_cppplugins_CppPlugin_onEnable_1(JNIEnv* env, jobject thisobj) { //TODO DEB("lib::onEnable()"); plugin->onEnable(); } /* * Class: de_mrbesen_cppplugins_CppPlugin * Method: onDisable_ * Signature: ()V */ JNIEXPORT void JNICALL Java_de_mrbesen_cppplugins_CppPlugin_onDisable_1(JNIEnv* env, jobject thisobj) { //TODO DEB("lib::onDisable()" ); plugin->onDisable(); dlclose(plugin->handle); } /* * Class: de_mrbesen_cppplugins_CppPlugin * Method: fireEvent * Signature: (Lde/mrbesen/cppplugins/CppEvent;I)Lde/mrbesen/cppplugins/CppEvent; */ JNIEXPORT jobject JNICALL Java_de_mrbesen_cppplugins_CppPlugin_fireEvent(JNIEnv* env, jobject thisobj, jobject jevent, jlong functionid) { DEB("lib::fireEvent()" ); if(functionid == 0) { DEB("invalid function id"); return jevent; } load(env, JNI_EVENT | JNI_MAP); //cast function eventfptr f = reinterpret_cast(functionid); //cast event Event event(env, jevent); //call it f(env, plugin, &event); //put changed fields back in the jevent event.reapply(env, jevent); return jevent; } /* * Class: de_mrbesen_cppplugins_CppPlugin * Method: onCmd * Signature: (Lorg/bukkit/command/CommandSender;Lorg/bukkit/command/Command;Ljava/lang/String;[Ljava/lang/String;)Z */ JNIEXPORT jboolean JNICALL Java_de_mrbesen_cppplugins_CppPlugin_onCmd(JNIEnv* env, jobject thisobj, jobject sender, jobject cmd, jstring label, jobjectArray args) { //TODO return false; } /* * Class: de_mrbesen_cppplugins_CppPlugin * Method: getListener * Signature: ()[Lde/mrbesen/cppplugins/CppPlugin/CppListener; */ JNIEXPORT jobjectArray JNICALL Java_de_mrbesen_cppplugins_CppPlugin_getListener(JNIEnv* env, jobject thisobj) { load(env, JNI_LISTENER); //call getEvents std::map events = plugin->getEvents(); DEB("found " << events.size() << " Events"); //create array jobject initial = env->NewObject(LISTENERCLASS, LISTENERSMALLCONTR); jobjectArray arr = env->NewObjectArray(events.size(), LISTENERCLASS, initial); DEB("populate array"); //populate array int i = 0; for(auto it : events) { //create object jstring eventname = env->NewStringUTF(it.first.c_str()); jobject listener = env->NewObject(LISTENERCLASS, LISTENERCONTR, eventname, it.second); env->DeleteLocalRef(eventname); //set array env->SetObjectArrayElement(arr, i++, listener); } DEB("Array finished"); return arr; }