snichol 2002/09/11 14:21:24 Modified: java/src/org/apache/soap/providers/com COMProvider.dll RPCProvider.cpp RPCProvider.h Log: Avoid use of ws2mbs macro when handling strings. That macro makes a copy of the string on the stack, which is a problem for long strings. Revision Changes Path 1.5 +18 -9 xml-soap/java/src/org/apache/soap/providers/com/COMProvider.dll <<Binary file>> 1.4 +129 -30 xml-soap/java/src/org/apache/soap/providers/com/RPCProvider.cpp Index: RPCProvider.cpp =================================================================== RCS file: /home/cvs/xml-soap/java/src/org/apache/soap/providers/com/RPCProvider.cpp,v retrieving revision 1.3 retrieving revision 1.4 diff -u -r1.3 -r1.4 --- RPCProvider.cpp 16 Aug 2002 19:17:38 -0000 1.3 +++ RPCProvider.cpp 11 Sep 2002 21:21:23 -0000 1.4 @@ -74,12 +74,11 @@ using namespace std; - - HRESULT variant2object (JNIEnv *jenv, const VARIANT &var, jobject &ret, bool *localRefCreated= NULL); wchar_t ModuleName[MAX_PATH *2 ]={0}; HANDLE thisModule; + BOOL WINAPI DllMain(HINSTANCE hinstDll, DWORD fdwReason, LPVOID fImpLoad) { if(fdwReason == DLL_PROCESS_ATTACH) @@ -133,6 +132,9 @@ const short LOG_ERROR = 1; short eventLevel= LOG_ERROR; +/* + * Undoes an action when exiting scope. + */ struct Undoit { void (__stdcall*coinit )(void); @@ -147,14 +149,23 @@ } }; +/* + * The actual provider. + */ class COMProvider { jobject jPP; //the java pluggable provider JNIEnv *env; static const char* javaClass; public: + /* + * Constructor that initializes member variables. + */ COMProvider(JNIEnv *e, jobject jthis):jPP(jthis),env(e){}; - + /* + * Gets the dispatch type to handle property get/set as + * well as straight method calls. + */ WORD getMethodDispatchType( const wchar_t *mname) { WORD ret = DISPATCH_METHOD; @@ -162,13 +173,21 @@ else if(0 == wcsncmp(L"set_", mname, 4)) ret= DISPATCH_PROPERTYPUT; return ret; } - + /* + * Invokes a method on a COM object, translating parameters and results + * between Java types and COM types. + */ jobject invoke (jstring jthreadingModel, jstring jprogid, jstring jmethodName, jbyteArray parms_in) { eventlog(LOG_SUCCESS, msgCalledDLL, ModuleName ); wchar_t progid[256]; Undoit undoit; ZeroIt(undoit); + // + // Get a local copy of parameters. The Java code for the + // provider has already munged the Java parameters into the + // byte array (which is really a VARIANT array) we use here. + // jsize noParmsBytes= NULL == parms_in ? 0 : env->GetArrayLength( parms_in); unsigned noParms= noParmsBytes/ sizeof VARIANT; eventlog(LOG_SUCCESS, msgNoParms, noParms ); @@ -195,6 +214,9 @@ dumpVariant(vp[i]); } */ + // + // Initialize COM + // DWORD coInit= COINIT_MULTITHREADED; //The default. bool oleInit= false; jboolean isCopy; @@ -236,7 +258,9 @@ } undoit.coinit= CoUninitialize; //Ensure we uninitialize. } - + // + // Get the method name + // cstr= (wchar_t *)env->GetStringChars(jmethodName, &isCopy); wchar_t *methodName= _wcsdup(cstr); if(isCopy == JNI_TRUE) env->ReleaseStringChars(jmethodName, cstr); @@ -246,7 +270,9 @@ throwSoapException( msgFailedMemory); return NULL; } - + // + // Get the CLSID + // CLSID clsid; cstr= (wchar_t*) env->GetStringChars(jprogid, &isCopy); if( L'{' == cstr[0]) //clsid is specified as a string @@ -278,8 +304,9 @@ wcsncpy(progid, cstr, (sizeof(progid)/(sizeof progid[0]))-1); if(isCopy == JNI_TRUE) env->ReleaseStringChars(jprogid, cstr); - //Start doing COM stuff - + // + // Create an instance of the COM object + // hr= CoCreateInstance( clsid, NULL, CLSCTX_ALL, IID_IDispatch, (void **)&undoit.idisp ); if (ASSERT_FAILED(hr)) @@ -289,8 +316,9 @@ if(methodName) free(methodName); return NULL; } - - + // + // Get the dispatch id of the method + // DISPID dispid; ZeroIt(dispid); bool isSet= false; @@ -308,7 +336,9 @@ if(methodName) free(methodName); return NULL; } - + // + // Initialize the parameter info + // DISPPARAMS dispparams; ZeroIt( dispparams); dispparams.rgvarg= undoit.vp; @@ -319,15 +349,19 @@ dispparams.cNamedArgs= 1 ; dispparams.rgdispidNamedArgs= &didpp; } + // + // Invoke the COM method + // VARIANT result; ZeroIt(result); EXCEPINFO expInfo; ZeroIt( expInfo); unsigned parg; ZeroIt( parg); - hr= undoit.idisp->Invoke(dispid, IID_NULL, GetUserDefaultLCID(), getMethodDispatchType(methodName), &dispparams, &result, &expInfo, &parg); - + // + // Translate COM errors or exceptions to Java + // if(hr == DISP_E_EXCEPTION ) { unsigned long err= (unsigned long) expInfo.wCode; @@ -352,6 +386,9 @@ if(methodName) free(methodName); return NULL; } + // + // Convert the result to a variant + // jobject jresult= NULL; hr= variant2object (env, result, jresult); @@ -369,30 +406,47 @@ ::VariantClear(&result); return jresult; } - //Throw a Java SOAP Exception. + /* + * Throws a SOAP exception for a UNICODE string. + */ BOOL throwSoapException( const wchar_t *msg) { if(NULL== msg) msg= L"Exception thrown by COMProvider"; - jstring jmsg= env->NewStringUTF(ws2mbs(msg)); +// jstring jmsg= env->NewStringUTF(ws2mbs(msg)); + jstring jmsg= env->NewString(msg, wcslen(msg)); jclass jcASE= env->FindClass(javaClass); jmethodID mid= env->GetStaticMethodID(jcASE,"getSOAPException","(Ljava/lang/String;)Lorg/apache/soap/SOAPException;"); jthrowable jt= (jthrowable) env->CallStaticObjectMethod(jcASE,mid, jmsg); env->Throw(jt); return true; } - + /* + * Throws a SOAP exception for a string. + */ + BOOL throwSoapException( const char *msg) + { + if(NULL== msg) msg= "Exception thrown by COMProvider"; + jstring jmsg= env->NewStringUTF(msg); + jclass jcASE= env->FindClass(javaClass); + jmethodID mid= env->GetStaticMethodID(jcASE,"getSOAPException","(Ljava/lang/String;)Lorg/apache/soap/SOAPException;"); + jthrowable jt= (jthrowable) env->CallStaticObjectMethod(jcASE,mid, jmsg); + env->Throw(jt); + return true; + } + /* + * Throws a SOAP exception for a Win32 message id. + */ BOOL throwSoapException( int id, ...) { - va_list a; va_start( a, id); wchar_t *msgbuf= NULL; FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |FORMAT_MESSAGE_FROM_STRING , (wchar_t *)id, 0, 3, (wchar_t *) &msgbuf, 10000, &a); - if(NULL== msgbuf || *msgbuf == L'\0') msgbuf= L"Exception thrown by COMProvider"; - jstring jmsg= env->NewStringUTF(ws2mbs(msgbuf)); +// jstring jmsg= env->NewStringUTF(ws2mbs(msgbuf)); + jstring jmsg= env->NewString(msgbuf, wcslen(msgbuf)); LocalFree( msgbuf ); jclass jcASE= env->FindClass(javaClass); jmethodID mid= env->GetStaticMethodID(jcASE,"getSOAPException","(Ljava/lang/String;)Lorg/apache/soap/SOAPException;"); @@ -400,12 +454,13 @@ env->Throw(jt); env->DeleteLocalRef(jmsg); - return true; + return true; } - + /* + * Logs an event + */ BOOL eventlog(short eventtype, int id, ...) { - if( (eventtype & eventLevel) == 0 ) return false; va_list a; va_start( a, id); @@ -415,7 +470,8 @@ // fwprintf( stderr, L"%s\n", msgbuf); jclass spClass= env->GetObjectClass(jPP); - jstring jmsg= env->NewStringUTF(ws2mbs(msgbuf)); +// jstring jmsg= env->NewStringUTF(ws2mbs(msgbuf)); + jstring jmsg= env->NewString(msgbuf, wcslen(msgbuf)); jmethodID mid= env->GetMethodID(spClass, "logit", "(ILjava/lang/String;)V"); env->CallVoidMethod(jPP, mid, (jint)eventtype, jmsg); env->DeleteLocalRef(jmsg); @@ -424,11 +480,21 @@ return true; } };//class COMProvider - const char* COMProvider::javaClass= "org/apache/soap/providers/com/RPCProvider"; +/* + * Native methods + */ +const char* COMProvider::javaClass= "org/apache/soap/providers/com/RPCProvider"; + +/* + * org.apache.soap.providers.com.RPCProvider#invoke + * + * Invokes the COM method as the SOAP service. + */ extern "C" JNIEXPORT jobject JNICALL Java_org_apache_soap_providers_com_RPCProvider_invoke (JNIEnv *env, jobject jo, jstring threadingModel, jstring jprogid, jstring jmethodName, jbyteArray parms_in) { + // Instantiate a COMProvider (see above) and call its invoke member function. CRTDBGBRK COMProvider cp(env, jo); #ifdef NDEBUG //This also will to debug on demand so if we are debugging don't do the catch. @@ -439,6 +505,25 @@ return cp.invoke(threadingModel, jprogid, jmethodName, parms_in); #ifdef NDEBUG } + catch(wchar_t *wstr) + { + env->ExceptionClear(); //Ignore all previous errors. + cp.throwSoapException(wstr); + return NULL; + } + catch(char *str) + { + env->ExceptionClear(); //Ignore all previous errors. + cp.throwSoapException(str); + return NULL; + } + catch(unsigned int ui) + { + env->ExceptionClear(); //Ignore all previous errors. + wchar_t numbuf[16]; + cp.throwSoapException(_ultow(ui, numbuf, 10)); + return NULL; + } catch( ... ) { //Main point here is not to trap the JVM! env->ExceptionClear(); //Ignore all previous errors. @@ -447,10 +532,20 @@ } #endif } +/* + * org.apache.soap.providers.com.RPCProvider#initlog + * + * Sets the logging level. + */ extern "C" JNIEXPORT void JNICALL Java_org_apache_soap_providers_com_RPCProvider_initlog(JNIEnv *env, jclass jc, jshort jlvl) { eventLevel= jlvl; } +/* + * org.apache.soap.providers.com.RPCProvider#nativeConvertToBString + * + * Converts a Java string to a BSTR. + */ extern "C" JNIEXPORT jbyteArray JNICALL Java_org_apache_soap_providers_com_RPCProvider_nativeConvertToBString(JNIEnv *env, jclass jc, jstring s) { env->ExceptionClear(); //Let a calling thread to invoke a call record the error. @@ -466,8 +561,9 @@ return jByteArray; } -/* make objects from primitives */ - +/* + * Functions to create a Java Object from primitive types. + */ jobject bsf_makeBoolean (JNIEnv *jenv, int val) { jclass classobj = jenv->FindClass ( "java/lang/Boolean"); jmethodID constructor = @@ -486,8 +582,7 @@ jclass classobj = jenv->FindClass ( "java/lang/Short"); jmethodID constructor = jenv->GetMethodID ( classobj, "<init>", "(S)V"); - return jenv->NewObject ( classobj, constructor, (jshort) val); -} + return jenv->NewObject ( classobj, constructor, (jshort) val); } jobject bsf_makeInteger (JNIEnv *jenv, int val) { jclass classobj = jenv->FindClass ( "java/lang/Integer"); @@ -517,6 +612,9 @@ return jenv->NewObject ( classobj, constructor, (jdouble) val); } +/* + * Create a Java Object from VARIANT types. + */ HRESULT variant2object (JNIEnv *jenv, const VARIANT &var, jobject &jresult, bool *localRefCreated) { HRESULT result = S_OK; @@ -550,8 +648,9 @@ break; case VT_BSTR: /* if its a string with the right stuff, retract the object */ - buf= ws2mbs(var.bstrVal); - jresult = jenv->NewStringUTF (buf); +// buf= ws2mbs(var.bstrVal); +// jresult = jenv->NewStringUTF (buf); + jresult = jenv->NewString(var.bstrVal, wcslen(var.bstrVal)); break; case VT_BOOL: jresult = bsf_makeBoolean (jenv, (int) V_BOOL (&var)); 1.2 +2 -0 xml-soap/java/src/org/apache/soap/providers/com/RPCProvider.h Index: RPCProvider.h =================================================================== RCS file: /home/cvs/xml-soap/java/src/org/apache/soap/providers/com/RPCProvider.h,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- RPCProvider.h 14 Mar 2001 19:39:56 -0000 1.1 +++ RPCProvider.h 11 Sep 2002 21:21:23 -0000 1.2 @@ -127,6 +127,8 @@ return (char *) d; } +// TODO: this requires sufficient stack for a copy of the string, +// which may simply not be available. #define ws2mbs(s) (ws2mbsConvert((s), _alloca( ((2+(wcslen((const wchar_t *)(s))<<1)))))) template<class T> inline void ZeroIt(T &t){ memset(&t, 0, sizeof t);};
-- To unsubscribe, e-mail: <mailto:[EMAIL PROTECTED]> For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>