From: <net...@us...> - 2003-02-15 13:32:06
|
Update of /cvsroot/cpptool/rfta/src/eclipseplugin/CppBridge In directory sc8-pr-cvs1:/tmp/cvs-serv29669 Added Files: EclipsePluginError.h EclipsePluginError.cpp EclipseHandler.h EclipseHandler.cpp EclipseDocumentHelper.h EclipseDocumentHelper.cpp EclipseBridge_RenameLocaleVariable.cpp Log Message: eclipse plugin native code sources --- NEW FILE: EclipsePluginError.h --- #include <stdexcept> class EclipsePluginError : public std::runtime_error { public: EclipsePluginError(std::string reason); const char *what() const throw(); private: std::string reason; }; --- NEW FILE: EclipsePluginError.cpp --- #include "EclipsePluginError.h" EclipsePluginError::EclipsePluginError(std::string reason):runtime_error(reason) { this->reason = reason; } const char * EclipsePluginError::what() const throw() { return reason.c_str(); } --- NEW FILE: EclipseHandler.h --- // ////////////////////////////////////////////////////////////////////////// // (c)Copyright 2003, Andre Baresel // Created: 2003/02/08 // ////////////////////////////////////////////////////////////////////////// class EclipseHandler; #ifndef __ECLIPSEHANDLER_H__ #define __ECLIPSEHANDLER_H__ #include <jni.h> #include <string> #include "EclipseDocumentHelper.h" /** * class is responsible to store and control an eclipse plugin connection * an object of this class should be created right after the native code * routine is called * (e.g. Java_org_eclipse_cpprefactoring_internal_EclipseBridge_applyRftaRenameLocaleVariable) */ class EclipseHandler { public: /** * creates the singleton eclipse handler connected to the given JNI * environment and the eclipse bridge object. It's possible to use this * handler during one native call 'session'. Don't forget to dispose the * handler before returing from the native routine. */ static EclipseHandler * createEclipseHandler(JNIEnv * env,jobject bridge); /** * does destroy an initialized eclipse handler, so that next sessions * can be handled correctly. This has to be the last call before returning * to java, because exception throwing is based on the handler information. */ static void disposeEclipseHandler(); /** * returns the singleton handler object * throws plugin-exception if handler is not initialized */ static EclipseHandler * getEclipseHandler(); ~EclipseHandler(); /** * function does write log information which can be seen in the * debugging environment of eclipse. */ void LogMessage(std::string msg); /** * function does return the methodID and catching any JAVA-Exception * (e.g. method not found) and converting java-exceptions into CplusPlus * PluginExceptions. */ jmethodID SafeGetMethodID(jclass clazz, const char * methodname, const char * sig); /** * function does return the methodID and catching any JAVA-Exception * (e.g. method not found) and converting java-exceptions into CplusPlus * PluginExceptions. */ jmethodID SafeGetStaticMethodID(jclass clazz, const char * methodname, const char * sig); /** * function does return the jclass object for the requested class name and * catches any JAVA-Exception (e.g. class not found) and converting the * java-exceptions into CplusPlus PluginExceptions. */ jclass SafeGetClass(const char * clazzname); /** * function does return the fieldID and catching any JAVA-Exception * (e.g. field not found) and converting java-exceptions into CplusPlus * PluginExceptions. */ jfieldID SafeGetFieldID(jclass clazz, const char * fieldname, const char * sig); jobject SafeGetObjectField(jobject obj, jfieldID classmember); EclipseDocumentHelper getActiveDocument(); jclass getJavaExceptionClass(); JNIEnv* getJNIEnv(); jobject getJavaStringBufferObject(); std::string getStringBufferContent(jobject buffer); protected: // EclipseHandler is a Singleton... EclipseHandler(JNIEnv * env,jobject bridge); JNIEnv* env; // current jni-environment jobject bridge; // object that has called the native routine jclass JavaException; // java exception class for throwing in java environment jclass bridgeclass; // class of the object that has called the native routine jobject docProviderRef; // eclipse document provider interface for the active editor jmethodID mid_logmessage; // method-id for calling LogMessage() a java routine jmethodID mid_stringbuffer_init; // method-id for constructing a stringbuffer object jmethodID mid_stringbuffer_tostring; // method-id for converting a stringbuffer into a string jclass jStringBufferClass; // string buffer class object }; #endif --- NEW FILE: EclipseHandler.cpp --- #include "EclipseHandler.h" #include "EclipsePluginError.h" /** * class is responsible to store and control an eclipse plugin connection * an object of this class should be created right after the native code * routine is called * (e.g. Java_org_eclipse_cpprefactoring_internal_EclipseBridge_applyRftaRenameLocaleVariable) */ EclipseHandler::EclipseHandler(JNIEnv * env,jobject bridge) { if (env==NULL) throw EclipsePluginError("Invalid Java-Native-Interface-Environment passed."); this->env = env; this->bridge = bridge; // find exception class for throwing java exceptions: JavaException = env->FindClass("java/lang/Exception"); // findout string buffer class for parameter passing jStringBufferClass = SafeGetClass("java/lang/StringBuffer"); mid_stringbuffer_init = SafeGetMethodID(jStringBufferClass, "<init>", "()V"); mid_stringbuffer_tostring = SafeGetMethodID(jStringBufferClass, "toString", "()Ljava/lang/String;"); // find out bridge methods & fields: bridgeclass = env->GetObjectClass(bridge); mid_logmessage = SafeGetMethodID(bridgeclass, "LogMessage", "(Ljava/lang/String;)V"); jfieldID fid = SafeGetFieldID (bridgeclass, "docProvider", "Lorg/eclipse/cpprefactoring/internal/RefactoringTextDocumentProvider;"); docProviderRef = SafeGetObjectField(bridge, fid); } EclipseHandler::~EclipseHandler() { } static EclipseHandler * singleton = NULL; EclipseHandler * EclipseHandler::createEclipseHandler(JNIEnv * env,jobject bridge) { // dispose a session that was not closed if (singleton!=NULL) { singleton->disposeEclipseHandler(); } // create the handler: try { singleton= new EclipseHandler(env,bridge); return singleton; } catch (EclipsePluginError e) { throw e; } catch (...) { throw EclipsePluginError("Not identified exception has occured in EclipseHandler::EclipseHandler"); } } void EclipseHandler::disposeEclipseHandler() { if (singleton==NULL) return; delete singleton; singleton=NULL; } EclipseHandler * EclipseHandler::getEclipseHandler() { if (singleton==NULL) { throw EclipsePluginError("EclipseHandler was not initialized correctly at native routine."); } return singleton; } /** * function does send log messages to the java environment * (the messages can be seen in debugging console) */ void EclipseHandler::LogMessage(std::string msg) { if (mid_logmessage==0) return; try { jstring par = env->NewStringUTF(msg.c_str()); env->CallVoidMethod(bridge, mid_logmessage , par ); } catch (...) { } } /** * function does return the methodID and catching any JAVA-Exception * (e.g. method not found) and converting java-exceptions into CplusPlus * PluginExceptions. */ jmethodID EclipseHandler::SafeGetMethodID(jclass clazz, const char * methodname, const char * sig) { jmethodID res=0; res = env->GetMethodID(clazz, methodname, sig); if (env->ExceptionOccurred()) { env->ExceptionDescribe(); env->ExceptionClear(); throw EclipsePluginError(std::string("Method '")+methodname+"' not found. Signature: "+sig); } return res; } /** * function does return the methodID and catching any JAVA-Exception * (e.g. method not found) and converting java-exceptions into CplusPlus * PluginExceptions. */ jmethodID EclipseHandler::SafeGetStaticMethodID(jclass clazz, const char * methodname, const char * sig) { jmethodID res=0; res = env->GetStaticMethodID(clazz, methodname, sig); if (env->ExceptionOccurred()) { env->ExceptionDescribe(); env->ExceptionClear(); throw EclipsePluginError(std::string("Method '")+methodname+"' not found. Signature: "+sig); } return res; } /** * function does return the jclass object for the requested class name and * catches any JAVA-Exception (e.g. class not found) and converting the * java-exceptions into CplusPlus PluginExceptions. */ jclass EclipseHandler::SafeGetClass(const char * clazzname) { jclass clazz = env->FindClass(clazzname); if (env->ExceptionOccurred()) { env->ExceptionDescribe(); env->ExceptionClear(); throw EclipsePluginError("class '"+std::string(clazzname)+"' not found."); } return clazz; } /** * function does return the fieldID and catching any JAVA-Exception * (e.g. field not found) and converting java-exceptions into CplusPlus * PluginExceptions. */ jfieldID EclipseHandler::SafeGetFieldID(jclass clazz, const char * fieldname, const char * sig) { jfieldID res=0; res = env->GetFieldID(clazz, fieldname, sig); if (env->ExceptionOccurred()) { env->ExceptionDescribe(); env->ExceptionClear(); throw EclipsePluginError(std::string("Field '")+fieldname+std::string("' not found. Signatur: ")+sig); } return res; } /** * function does return the value of the class member stored in java object 'obj' * any java exception (e.g. field not accessible) will be catched and mapped to * a PluginException. */ jobject EclipseHandler::SafeGetObjectField(jobject obj, jfieldID classmember) { jobject result = env->GetObjectField(obj,classmember); if (env->ExceptionOccurred()) { env->ExceptionDescribe(); env->ExceptionClear(); // don't know yet how to display more throw EclipsePluginError(std::string("Accessing a field of a java object has cause a java exception.")); } return result; } jclass EclipseHandler::getJavaExceptionClass() { return this->JavaException; } JNIEnv* EclipseHandler::getJNIEnv() { return env; } jobject EclipseHandler::getJavaStringBufferObject() { return env->NewObject(jStringBufferClass,mid_stringbuffer_init); } std::string EclipseHandler::getStringBufferContent(jobject buffer) { jstring newstr = (jstring)env->CallObjectMethod(buffer,mid_stringbuffer_tostring); std::string res; res.assign(env->GetStringUTFChars(newstr,0)); env->ReleaseStringUTFChars(newstr,0); return res; } EclipseDocumentHelper EclipseHandler::getActiveDocument() { EclipseDocumentHelper doc(env,docProviderRef); return doc; } --- NEW FILE: EclipseDocumentHelper.h --- // ////////////////////////////////////////////////////////////////////////// // (c)Copyright 2003, Andre Baresel // Created: 2003/01/28 // ////////////////////////////////////////////////////////////////////////// class EclipseDocumentHelper; #ifndef __ECLIPSEDOCUMENTHELPER_H__ #define __ECLIPSEDOCUMENTHELPER_H__ #include <jni.h> #include <string> #include <rfta/refactoring/TextDocument.h> class EclipseDocumentHelper: public Refactoring::TextDocument { protected: jobject targetDocument; jclass targetDocumentClass; jclass jSourceRangeClass; JNIEnv * env; // method IDs to call corresponding java functions in 'RefactoringTextDocumentProvider' class jmethodID mid_getAllText; jmethodID mid_getSelection; jmethodID mid_replaceSelection; jmethodID mid_getSelectionRange; jmethodID mid_setSelectionRange; jmethodID mid_moveTo; jmethodID mid_sourcerange_init; jfieldID fid_range_start; jfieldID fid_range_end; public: EclipseDocumentHelper(JNIEnv * _env, jobject _targetDocument); /*! Gets the text of the document. * \return Text of the document. EOL are in the original text format. * \warning Discard current selection. */ virtual const std::string getAllText() const; /*! Gets the selected text. * \return Selected text. EOL are in the original text format. */ virtual const std::string getSelection() const; /*! Replace current selection text with the specified text. * \param text The selection is replaced with that text. If no * text is selected, then the specified text is * inserted at the selection location. */ virtual void replaceSelection( const std::string &text ); /*! Gets the selected range. * \return The location range of the selection. * \warning Discard current selection. */ virtual Refactoring::SourceRange getSelectionRange() const; /*! Select a specified range of text. * Line and column are zero-based. * \param from Location the selection begins at. * \param to Location the selection ends (not included). */ virtual void setSelectionRange( const Refactoring::SourceRange &selection ); /*! Move to a specific location. * Set the selection to an empty selection at the specified location. * Equivalent to selectText( to, to ). * \param toLocation Location the next setSelectedText() operation will insert * text at. */ void moveTo( int toLocation ); }; #endif // __ECLIPSEDOCUMENTHELPER_H__ --- NEW FILE: EclipseDocumentHelper.cpp --- // ////////////////////////////////////////////////////////////////////////// // (c)Copyright 2003, Andre Baresel // Created: 2003/01/28 // ////////////////////////////////////////////////////////////////////////// #include "EclipseHandler.h" #include "EclipseDocumentHelper.h" #include <rfta/refactoring/RenameTempRefactoring.h> #include "EclipsePluginError.h" EclipseDocumentHelper::EclipseDocumentHelper(JNIEnv * _env, jobject _targetDocument) { EclipseHandler* hdl = EclipseHandler::getEclipseHandler(); targetDocument = _targetDocument; env = _env; // Ljava/lang/String; jclass documentProvider = hdl->SafeGetClass("org/eclipse/cpprefactoring/internal/RefactoringTextDocumentProvider"); if (!env->IsInstanceOf(targetDocument,documentProvider)) throw EclipsePluginError("Passed argument is not an instance of 'RefactoringTextDocumentProvider'."); targetDocumentClass = env->GetObjectClass(targetDocument); // get reference to source-range class on java side: jSourceRangeClass = hdl->SafeGetClass("org/eclipse/cpprefactoring/internal/RefactoringSourceRange"); mid_sourcerange_init = hdl->SafeGetMethodID(jSourceRangeClass, "<init>", "(II)V"); fid_range_start = hdl->SafeGetFieldID(jSourceRangeClass,"startIndex_","I"); fid_range_end = hdl->SafeGetFieldID(jSourceRangeClass,"length_","I"); // try to get the methodIDs of the corresponding java class... mid_getAllText = hdl->SafeGetMethodID(targetDocumentClass, "getAllText", "()Ljava/lang/String;"); mid_getSelection = hdl->SafeGetMethodID(targetDocumentClass, "getSelection", "()Ljava/lang/String;"); mid_replaceSelection = hdl->SafeGetMethodID(targetDocumentClass, "replaceSelection","(Ljava/lang/String;)V"); mid_getSelectionRange = hdl->SafeGetMethodID(targetDocumentClass, "getSelectionRange", "()Lorg/eclipse/cpprefactoring/internal/RefactoringSourceRange;"); mid_setSelectionRange = hdl->SafeGetMethodID(targetDocumentClass, "setSelectionRange","(Lorg/eclipse/cpprefactoring/internal/RefactoringSourceRange;)V"); mid_moveTo = hdl->SafeGetMethodID(targetDocumentClass, "moveTo","(I)V"); } /*! Gets the text of the document. * \return Text of the document. EOL are in the original text format. * \warning Discard current selection. */ const std::string EclipseDocumentHelper::getAllText() const { // call the java class method: jstring jres = (jstring)env->CallObjectMethod(targetDocument, mid_getAllText ); // convert the string: const char * cp = env->GetStringUTFChars(jres,0); std::string result; if (cp != NULL) result = cp; env->ReleaseStringUTFChars(jres,0); return result; } /*! Gets the selected text. * \return Selected text. EOL are in the original text format. */ const std::string EclipseDocumentHelper::getSelection() const { // call the java class method: jstring jres = (jstring)env->CallObjectMethod(targetDocument, mid_getSelection ); // convert the string: const char * cp = env->GetStringUTFChars(jres,0); std::string result; if (cp != NULL) result = cp; env->ReleaseStringUTFChars(jres,0); return result; } /*! Replace current selection text with the specified text. * \param text The selection is replaced with that text. If no * text is selected, then the specified text is * inserted at the selection location. */ void EclipseDocumentHelper::replaceSelection( const std::string &text ) { jstring par = env->NewStringUTF(text.c_str()); env->CallVoidMethod(targetDocument, mid_replaceSelection , par ); } /*! Gets the selected range. * \return The location range of the selection. * \warning Discard current selection. */ Refactoring::SourceRange EclipseDocumentHelper::getSelectionRange() const { // call the java class method: jobject jres = (jobject)env->CallObjectMethod(targetDocument, mid_getSelectionRange ); if (!env->IsInstanceOf(jres,jSourceRangeClass)) { throw EclipsePluginError("returned value of 'getSelectionRange' is not an instance of 'RefactoringSourceRange'."); } jint i1 = env->GetIntField(jres,fid_range_start); jint i2 = env->GetIntField(jres,fid_range_end); //return result; return Refactoring::SourceRange(i1,i2); } /*! Select a specified range of text. * Line and column are zero-based. * \param from Location the selection begins at. * \param to Location the selection ends (not included). */ void EclipseDocumentHelper::setSelectionRange( const Refactoring::SourceRange &selection ) { jint start=selection.getStartIndex(),len=selection.getLength(); // create a new object of source range class: jobject jrange = env->NewObject(jSourceRangeClass,mid_sourcerange_init,start,len); // call the java class method: env->CallVoidMethod(targetDocument, mid_setSelectionRange, jrange ); if (env->ExceptionOccurred()) { env->ExceptionDescribe(); env->ExceptionClear(); } } /*! Move to a specific location. * Set the selection to an empty selection at the specified location. * Equivalent to selectText( to, to ). * \param toLocation Location the next setSelectedText() operation will insert * text at. */ void EclipseDocumentHelper::moveTo( int toLocation ) { jint to=toLocation; // call the java class method: env->CallVoidMethod(targetDocument, mid_moveTo, to ); } --- NEW FILE: EclipseBridge_RenameLocaleVariable.cpp --- // ////////////////////////////////////////////////////////////////////////// // (c)Copyright 2003, Andre Baresel // Created: 2003/01/28 // ////////////////////////////////////////////////////////////////////////// #include <windows.h> #include <jni.h> #include <rfta/refactoring/RefactoringError.h> #include <rfta/refactoring/RenameTempRefactoring.h> #include "..\generatedcode\org_eclipse_cpprefactoring_internal_EclipseBridge.h" #include "EclipseHandler.h" #include "EclipseDocumentHelper.h" #include "EclipsePluginError.h" /** * callback routine to open the 'rename local variable' dialog in eclipse ide. */ bool OpenRenameLocalVariableDialog(jclass dialogclass, std::string var2rename,std::string& newname); #ifdef _DEBUG LONG _stdcall testexc(struct _EXCEPTION_POINTERS *ExceptionInfo) { MessageBox(NULL,"Userdefined C++ Exception Handler. Choose CANCEL in next dialog to debug.","C++ Exception Catched",MB_OK); return EXCEPTION_CONTINUE_SEARCH; } #endif #ifdef _DEBUG #define RESTORE_EXCEPTIONFILTER SetUnhandledExceptionFilter(flt); #else #define RESTORE_EXCEPTIONFILTER #endif /** * function is called from eclipse environment and does * apply RenameLocalVar-Refactoring. */ JNIEXPORT void JNICALL Java_org_eclipse_cpprefactoring_internal_EclipseBridge_applyRftaRenameLocaleVariable (JNIEnv * env, jobject this_, jclass dialogclass) { #ifdef _DEBUG SetErrorMode(0); LPTOP_LEVEL_EXCEPTION_FILTER flt = SetUnhandledExceptionFilter(testexc); DebugBreak(); #endif jclass JavaException = 0; EclipseHandler * hdl = 0; try { std::string oldname; hdl = EclipseHandler::createEclipseHandler(env,this_); JavaException = hdl->getJavaExceptionClass(); try { EclipseDocumentHelper& doc = hdl->getActiveDocument(); Refactoring::RenameTempRefactoring refactoring( doc, doc.getSelectionRange().getStartIndex() ); oldname = refactoring.getOldVariableName().c_str(); std::string newname; if (OpenRenameLocalVariableDialog(dialogclass,oldname,newname)) { refactoring.apply( newname ); } EclipseHandler::disposeEclipseHandler(); RESTORE_EXCEPTIONFILTER; return; // back to JAVA } catch ( Refactoring::RefactoringError &e ) { RESTORE_EXCEPTIONFILTER; std::string message( "An error occurred during refactoring:\n" ); message += e.what(); if (JavaException == 0) { /* Unable to find the new exception class, give up. */ hdl->LogMessage(message); return; } EclipseHandler::disposeEclipseHandler(); env->ThrowNew(JavaException, message.c_str() ); return; } } catch (EclipsePluginError& pluginerror) { RESTORE_EXCEPTIONFILTER; hdl = EclipseHandler::getEclipseHandler(); if (hdl==NULL) { JavaException = env->FindClass("java/lang/Exception"); } env->ThrowNew(JavaException, (std::string("Plugin-Error: ")+pluginerror.what()).c_str() ); return; } catch (...) { try { RESTORE_EXCEPTIONFILTER; hdl = EclipseHandler::getEclipseHandler(); if (hdl==NULL) { // TODO: report a problem without the handler return; } env->ExceptionDescribe(); env->ExceptionClear(); hdl->LogMessage("An unexpected exception has occured in CPP-code.\n"); env->ExceptionDescribe(); env->ExceptionClear(); return; } catch (...) { // excection within exception handler -- no chance, // get back to java silently return; } } } /** * function does use the call back routine to open a dialog in eclipse * asking the user for the new variable name * * @return true, if the renaming was ackknowledged by the user */ bool OpenRenameLocalVariableDialog(jclass dialogclass, std::string var2rename,std::string& newname) { EclipseHandler * hdl = EclipseHandler::getEclipseHandler(); jmethodID mid_callback_RenameLocalVariableDialog=0; mid_callback_RenameLocalVariableDialog = hdl->SafeGetStaticMethodID(dialogclass, "callback_userrequest", "(Ljava/lang/String;Ljava/lang/StringBuffer;)Z"); if (mid_callback_RenameLocalVariableDialog==0) return false; try { JNIEnv * env = hdl->getJNIEnv(); jstring oldval = env->NewStringUTF(var2rename.c_str()); jobject newval = hdl->getJavaStringBufferObject(); jboolean ok = env->CallStaticBooleanMethod(dialogclass, mid_callback_RenameLocalVariableDialog, oldval, newval ); newname = hdl->getStringBufferContent(newval); return (ok!=JNI_FALSE); } catch (...) { return false; } } |