#include "de_mrbesen_cppplugins_CppPlugin.h" #include "de_mrbesen_cppplugins_CppPlugin_CppListener.h" #include #include //dynamic linking #include //basename #include //thread id #include "libplugin.h" #include "plugin.h" jclass CPPPLUGINCLASS; jclass EVENTCLASS; jclass MAPCLASS; jclass LISTENERCLASS; jfieldID EVENTDATAF; jfieldID EVENTNAMEF; jfieldID PLUGINIDF; jmethodID MAPGET; jmethodID MAPPUT; jmethodID MAPCLEAR; jmethodID LISTENERCONTR; jmethodID LISTENERSMALLCONTR; std::vector plugins; /* void fixcap(JNIEnv* env) { DEB("ensure 1024" ); env->EnsureLocalCapacity(1024); DEB("push frame 1024" ); env->PushLocalFrame(1024); }*/ CppPlugin* getPlugin(JNIEnv* env, jobject thisobj, int id) { //get id if(id < 0) { load(env, JNI_PLUGINIDFIELD); id = env->GetIntField(thisobj, PLUGINIDF); } return plugins.at(id); } void load(JNIEnv* env, long 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"); if(data & JNI_EVENTDATAFIELD) EVENTDATAF = env->GetFieldID(EVENTCLASS, "data", "Ljava/util/Map;"); if(data & JNI_EVENTNAMEFIELD) EVENTNAMEF = env->GetFieldID(EVENTCLASS, "name", "Ljava/lang/String;"); if(data & JNI_PLUGINIDFIELD) PLUGINIDF = env->GetFieldID(CPPPLUGINCLASS, "id", "I"); 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"); if(((!CPPPLUGINCLASS) + (!EVENTCLASS) + (!MAPCLASS) + (!LISTENERCLASS) //wenn eins == nullptr ist -> wird zu 1 -> endergebniss != 0 -> fehler + (!EVENTDATAF) + (!EVENTNAMEF) + (!PLUGINIDF) + (!MAPGET) + (!MAPPUT) + (!MAPCLEAR) + (!LISTENERCONTR) + (!LISTENERSMALLCONTR)) == 0) { DEB("Error loading a information: "); DEB("find classes: " << (!!CPPPLUGINCLASS) << (!!EVENTCLASS) << (!!MAPCLASS) << (!!LISTENERCLASS)); DEB("findfields: " << (!!EVENTDATAF) << (!!EVENTNAMEF) << (!!PLUGINIDF)); 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; } CppPlugin* plugin = initf(); plugin->handle = handle; //set name / handle id plugin->name = std::string(cpath); plugin->name = plugin->name.substr(plugin->name.rfind('/')); // add to vector plugins.push_back(plugin); //store id load(env, JNI_PLUGINIDFIELD); env->SetIntField(thisobj, PLUGINIDF, plugins.size()-1); 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) { DEB("lib::onLoad()"); getPlugin(env, thisobj)->onLoad(); } /* * Class: de_mrbesen_cppplugins_CppPlugin * Method: onEnable_ * Signature: ()V */ JNIEXPORT void JNICALL Java_de_mrbesen_cppplugins_CppPlugin_onEnable_1(JNIEnv* env, jobject thisobj) { DEB("lib::onEnable()"); getPlugin(env, thisobj)->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()" ); CppPlugin* plugin = getPlugin(env, thisobj); 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, getPlugin(env, thisobj), &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 = getPlugin(env, thisobj)->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; }