1 /* 2 * Copyright (c) 2014, Oracle and/or its affiliates. 3 * All rights reserved. Use is subject to license terms. 4 * 5 * This file is available and licensed under the following license: 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * - Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * - Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in 15 * the documentation and/or other materials provided with the distribution. 16 * - Neither the name of Oracle Corporation nor the names of its 17 * contributors may be used to endorse or promote products derived 18 * from this software without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 34 #include "Java.h" 35 #include "PlatformString.h" 36 37 #include <list> 38 39 40 //-------------------------------------------------------------------------------------------------- 41 42 #ifdef DEBUG 43 TString JavaException::CreateExceptionMessage(JNIEnv* Env, jthrowable Exception, 44 jmethodID GetCauseMethod, jmethodID GetStackTraceMethod, jmethodID ThrowableToTStringMethod, 45 jmethodID FrameToTStringMethod) { 46 47 TString result; 48 jobjectArray frames = (jobjectArray)Env->CallObjectMethod(Exception, GetStackTraceMethod); 49 50 // Append Throwable.toTString(). 51 if (0 != frames) { 52 jstring jstr = (jstring)Env->CallObjectMethod(Exception, ThrowableToTStringMethod); 53 const char* str = Env->GetStringUTFChars(jstr, 0); 54 result += PlatformString(str).toPlatformString(); 55 Env->ReleaseStringUTFChars(jstr, str); 56 Env->DeleteLocalRef(jstr); 57 } 58 59 // Append stack trace if one exists. 60 if (Env->GetArrayLength(frames) > 0) { 61 jsize i = 0; 62 63 for (i = 0; i < Env->GetArrayLength(frames); i++) { 64 // Get the string from the next frame and append it to 65 // the error message. 66 jobject frame = Env->GetObjectArrayElement(frames, i); 67 jstring obj = (jstring)Env->CallObjectMethod(frame, FrameToTStringMethod); 68 const char* str = Env->GetStringUTFChars(obj, 0); 69 result += _T("\n "); 70 result += PlatformString(str).toPlatformString(); 71 Env->ReleaseStringUTFChars(obj, str); 72 Env->DeleteLocalRef(obj); 73 Env->DeleteLocalRef(frame); 74 } 75 } 76 77 // If Exception has a cause then append the stack trace messages. 78 if (0 != frames) { 79 jthrowable cause = (jthrowable)Env->CallObjectMethod(Exception, GetCauseMethod); 80 81 if (cause != NULL) { 82 result += CreateExceptionMessage(Env, cause, GetCauseMethod, 83 GetStackTraceMethod, ThrowableToTStringMethod, 84 FrameToTStringMethod); 85 } 86 } 87 88 return result; 89 } 90 #endif //DEBUG 91 92 JavaException::JavaException() : Exception() {} 93 94 //#ifdef WINDOWS 95 JavaException::JavaException(JNIEnv *Env, const TString Message) : Exception(Message) { 96 //#endif //WINDOWS 97 //#ifdef POSIX 98 //JavaException::JavaException(JNIEnv *Env, TString message) { 99 //#endif //POSIX 100 101 FEnv = Env; 102 FException = Env->ExceptionOccurred(); 103 Env->ExceptionClear(); 104 105 #ifdef DEBUG 106 Platform& platform = Platform::GetInstance(); 107 108 if (platform.GetDebugState() == dsNone) { 109 jclass ThrowableClass = Env->FindClass("java/lang/Throwable"); 110 111 if (FEnv->ExceptionCheck() == JNI_TRUE) { 112 Env->ExceptionClear(); 113 return; 114 } 115 116 jmethodID GetCauseMethod = Env->GetMethodID(ThrowableClass, 117 "getCause", 118 "()Ljava/lang/Throwable;"); 119 120 if (FEnv->ExceptionCheck() == JNI_TRUE) { 121 Env->ExceptionClear(); 122 return; 123 } 124 125 jmethodID GetStackTraceMethod = Env->GetMethodID(ThrowableClass, 126 "getStackTrace", 127 "()[Ljava/lang/StackTraceElement;"); 128 129 if (FEnv->ExceptionCheck() == JNI_TRUE) { 130 Env->ExceptionClear(); 131 return; 132 } 133 134 jmethodID ThrowableToTStringMethod = Env->GetMethodID(ThrowableClass, 135 "toString", 136 "()Ljava/lang/String;"); 137 138 if (FEnv->ExceptionCheck() == JNI_TRUE) { 139 Env->ExceptionClear(); 140 return; 141 } 142 143 jclass FrameClass = Env->FindClass("java/lang/StackTraceElement"); 144 145 if (FEnv->ExceptionCheck() == JNI_TRUE) { 146 Env->ExceptionClear(); 147 return; 148 } 149 150 jmethodID FrameToTStringMethod = Env->GetMethodID(FrameClass, 151 "toString", 152 "()Ljava/lang/String;"); 153 154 if (FEnv->ExceptionCheck() == JNI_TRUE) { 155 Env->ExceptionClear(); 156 return; 157 } 158 159 TString lmessage = CreateExceptionMessage(Env, FException, GetCauseMethod, 160 GetStackTraceMethod, ThrowableToTStringMethod, FrameToTStringMethod); 161 SetMessage(lmessage); 162 } 163 #endif //DEBUG 164 } 165 166 void JavaException::Rethrow() { 167 FEnv->Throw(FException); 168 } 169 170 //-------------------------------------------------------------------------------------------------- 171 172 JavaStaticMethod::JavaStaticMethod(JNIEnv *Env, jclass Class, jmethodID Method) { 173 FEnv = Env; 174 FClass = Class; 175 FMethod = Method; 176 } 177 178 void JavaStaticMethod::CallVoidMethod(int Count, ...) { 179 va_list args; 180 va_start(args, Count); 181 FEnv->CallStaticVoidMethodV(FClass, FMethod, args); 182 va_end(args); 183 184 if (FEnv->ExceptionCheck() == JNI_TRUE) { 185 Messages& messages = Messages::GetInstance(); 186 throw JavaException(FEnv, messages.GetMessage(ERROR_INVOKING_METHOD)); 187 } 188 } 189 190 JavaStaticMethod::operator jmethodID () { 191 return FMethod; 192 } 193 194 //-------------------------------------------------------------------------------------------------- 195 196 JavaMethod::JavaMethod(JNIEnv *Env, jobject Obj, jmethodID Method) { 197 FEnv = Env; 198 FObj = Obj; 199 FMethod = Method; 200 } 201 202 void JavaMethod::CallVoidMethod(int Count, ...) { 203 va_list args; 204 va_start(args, Count); 205 FEnv->CallVoidMethodV(FObj, FMethod, args); 206 va_end(args); 207 208 if (FEnv->ExceptionCheck() == JNI_TRUE) { 209 Messages& messages = Messages::GetInstance(); 210 throw JavaException(FEnv, messages.GetMessage(ERROR_INVOKING_METHOD)); 211 } 212 } 213 214 JavaMethod::operator jmethodID () { 215 return FMethod; 216 } 217 218 //-------------------------------------------------------------------------------------------------- 219 220 JavaClass::JavaClass(JNIEnv *Env, TString Name) { 221 FEnv = Env; 222 FClassName = Name; 223 FClass = FEnv->FindClass(PlatformString(FClassName)); 224 225 if (FClass == NULL || FEnv->ExceptionCheck() == JNI_TRUE) { 226 Messages& messages = Messages::GetInstance(); 227 TString message = messages.GetMessage(CLASS_NOT_FOUND); 228 message = PlatformString::Format(message, FClassName.data()); 229 throw JavaException(FEnv, message); 230 } 231 } 232 233 JavaClass::~JavaClass() { 234 FEnv->DeleteLocalRef(FClass); 235 236 if (FEnv->ExceptionCheck() == JNI_TRUE) { 237 throw JavaException(FEnv, _T("Error")); 238 } 239 } 240 241 JavaStaticMethod JavaClass::GetStaticMethod(TString Name, TString Signature) { 242 jmethodID method = FEnv->GetStaticMethodID(FClass, PlatformString(Name), PlatformString(Signature)); 243 244 if (method == NULL || FEnv->ExceptionCheck() == JNI_TRUE) { 245 Messages& messages = Messages::GetInstance(); 246 TString message = messages.GetMessage(METHOD_NOT_FOUND); 247 message = PlatformString::Format(message, Name.data(), FClassName.data()); 248 throw JavaException(FEnv, message); 249 } 250 251 return JavaStaticMethod(FEnv, FClass, method); 252 } 253 254 JavaClass::operator jclass () { 255 return FClass; 256 } 257 258 //-------------------------------------------------------------------------------------------------- 259 260 void JavaStringArray::Initialize(size_t Size) { 261 JavaClass jstringClass(FEnv, _T("java/lang/String")); 262 263 if (FEnv->ExceptionCheck() == JNI_TRUE) { 264 Messages& messages = Messages::GetInstance(); 265 TString message = messages.GetMessage(CLASS_NOT_FOUND); 266 message = PlatformString::Format(message, _T("String")); 267 throw JavaException(FEnv, message.data()); 268 } 269 270 jstring str = PlatformString("").toJString(FEnv); 271 FData = (jobjectArray)FEnv->NewObjectArray((jsize)Size, jstringClass, str); 272 273 if (FEnv->ExceptionCheck() == JNI_TRUE) { 274 throw JavaException(FEnv, _T("Error")); 275 } 276 } 277 278 JavaStringArray::JavaStringArray(JNIEnv *Env, size_t Size) { 279 FEnv = Env; 280 Initialize(Size); 281 } 282 283 JavaStringArray::JavaStringArray(JNIEnv *Env, jobjectArray Data) { 284 FEnv = Env; 285 FData = Data; 286 } 287 288 JavaStringArray::JavaStringArray(JNIEnv *Env, std::list<TString> Items) { 289 FEnv = Env; 290 Initialize(Items.size()); 291 unsigned int index = 0; 292 293 for (std::list<TString>::const_iterator iterator = Items.begin(); iterator != Items.end(); iterator++) { 294 TString item = *iterator; 295 SetValue(index, PlatformString(item).toJString(FEnv)); 296 index++; 297 } 298 } 299 300 jobjectArray JavaStringArray::GetData() { 301 return FData; 302 } 303 304 void JavaStringArray::SetValue(jsize Index, jstring Item) { 305 FEnv->SetObjectArrayElement(FData, Index, Item); 306 307 if (FEnv->ExceptionCheck() == JNI_TRUE) { 308 throw JavaException(FEnv, _T("Error")); 309 } 310 } 311 312 jstring JavaStringArray::GetValue(jsize Index) { 313 jstring result = (jstring)FEnv->GetObjectArrayElement(FData, Index); 314 315 if (FEnv->ExceptionCheck() == JNI_TRUE) { 316 throw JavaException(FEnv, _T("Error")); 317 } 318 319 return result; 320 } 321 322 unsigned int JavaStringArray::Count() { 323 unsigned int result = FEnv->GetArrayLength(FData); 324 325 if (FEnv->ExceptionCheck() == JNI_TRUE) { 326 throw JavaException(FEnv, _T("Error")); 327 } 328 329 return result; 330 } 331 332 //--------------------------------------------------------------------------------------------------