1 /* 2 * Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 #include "JavaTypes.h" 27 #include "PlatformString.h" 28 29 #include <list> 30 31 32 #ifdef DEBUG 33 TString JavaException::CreateExceptionMessage(JNIEnv* Env, 34 jthrowable Exception, jmethodID GetCauseMethod, 35 jmethodID GetStackTraceMethod, jmethodID ThrowableToTStringMethod, 36 jmethodID FrameToTStringMethod) { 37 38 TString result; 39 jobjectArray frames = 40 (jobjectArray)Env->CallObjectMethod(Exception, GetStackTraceMethod); 41 42 // Append Throwable.toTString(). 43 if (0 != frames) { 44 jstring jstr = (jstring)Env->CallObjectMethod(Exception, 45 ThrowableToTStringMethod); 46 const char* str = Env->GetStringUTFChars(jstr, 0); 47 result += PlatformString(str).toPlatformString(); 48 Env->ReleaseStringUTFChars(jstr, str); 49 Env->DeleteLocalRef(jstr); 50 } 51 52 // Append stack trace if one exists. 53 if (Env->GetArrayLength(frames) > 0) { 54 jsize i = 0; 55 56 for (i = 0; i < Env->GetArrayLength(frames); i++) { 57 // Get the string from the next frame and append it to 58 // the error message. 59 jobject frame = Env->GetObjectArrayElement(frames, i); 60 jstring obj = (jstring)Env->CallObjectMethod(frame, 61 FrameToTStringMethod); 62 const char* str = Env->GetStringUTFChars(obj, 0); 63 result += _T("\n "); 64 result += PlatformString(str).toPlatformString(); 65 Env->ReleaseStringUTFChars(obj, str); 66 Env->DeleteLocalRef(obj); 67 Env->DeleteLocalRef(frame); 68 } 69 } 70 71 // If Exception has a cause then append the stack trace messages. 72 if (0 != frames) { 73 jthrowable cause = 74 (jthrowable)Env->CallObjectMethod(Exception, GetCauseMethod); 75 76 if (cause != NULL) { 77 result += CreateExceptionMessage(Env, cause, GetCauseMethod, 78 GetStackTraceMethod, ThrowableToTStringMethod, 79 FrameToTStringMethod); 80 } 81 } 82 83 return result; 84 } 85 #endif //DEBUG 86 87 JavaException::JavaException() : Exception() {} 88 89 //#ifdef WINDOWS 90 JavaException::JavaException(JNIEnv *Env, 91 const TString Message) : Exception(Message) { 92 //#endif //WINDOWS 93 //#ifdef POSIX 94 //JavaException::JavaException(JNIEnv *Env, TString message) { 95 //#endif //POSIX 96 97 FEnv = Env; 98 FException = Env->ExceptionOccurred(); 99 Env->ExceptionClear(); 100 101 #ifdef DEBUG 102 Platform& platform = Platform::GetInstance(); 103 104 if (platform.GetDebugState() == dsNone) { 105 jclass ThrowableClass = Env->FindClass("java/lang/Throwable"); 106 107 if (FEnv->ExceptionCheck() == JNI_TRUE) { 108 Env->ExceptionClear(); 109 return; 110 } 111 112 jmethodID GetCauseMethod = Env->GetMethodID(ThrowableClass, 113 "getCause", "()Ljava/lang/Throwable;"); 114 115 if (FEnv->ExceptionCheck() == JNI_TRUE) { 116 Env->ExceptionClear(); 117 return; 118 } 119 120 jmethodID GetStackTraceMethod = Env->GetMethodID(ThrowableClass, 121 "getStackTrace", "()[Ljava/lang/StackTraceElement;"); 122 123 if (FEnv->ExceptionCheck() == JNI_TRUE) { 124 Env->ExceptionClear(); 125 return; 126 } 127 128 jmethodID ThrowableToTStringMethod = Env->GetMethodID(ThrowableClass, 129 "toString", "()Ljava/lang/String;"); 130 131 if (FEnv->ExceptionCheck() == JNI_TRUE) { 132 Env->ExceptionClear(); 133 return; 134 } 135 136 jclass FrameClass = Env->FindClass("java/lang/StackTraceElement"); 137 138 if (FEnv->ExceptionCheck() == JNI_TRUE) { 139 Env->ExceptionClear(); 140 return; 141 } 142 143 jmethodID FrameToTStringMethod = Env->GetMethodID(FrameClass, 144 "toString", "()Ljava/lang/String;"); 145 146 if (FEnv->ExceptionCheck() == JNI_TRUE) { 147 Env->ExceptionClear(); 148 return; 149 } 150 151 TString lmessage = CreateExceptionMessage(Env, FException, 152 GetCauseMethod, GetStackTraceMethod, ThrowableToTStringMethod, 153 FrameToTStringMethod); 154 SetMessage(lmessage); 155 } 156 #endif //DEBUG 157 } 158 159 void JavaException::Rethrow() { 160 FEnv->Throw(FException); 161 } 162 163 //---------------------------------------------------------------------------- 164 165 JavaStaticMethod::JavaStaticMethod(JNIEnv *Env, jclass Class, jmethodID Method) { 166 FEnv = Env; 167 FClass = Class; 168 FMethod = Method; 169 } 170 171 void JavaStaticMethod::CallVoidMethod(int Count, ...) { 172 va_list args; 173 va_start(args, Count); 174 FEnv->CallStaticVoidMethodV(FClass, FMethod, args); 175 va_end(args); 176 177 if (FEnv->ExceptionCheck() == JNI_TRUE) { 178 Messages& messages = Messages::GetInstance(); 179 throw JavaException(FEnv, messages.GetMessage(ERROR_INVOKING_METHOD)); 180 } 181 } 182 183 JavaStaticMethod::operator jmethodID () { 184 return FMethod; 185 } 186 187 //---------------------------------------------------------------------------- 188 189 JavaMethod::JavaMethod(JNIEnv *Env, jobject Obj, jmethodID Method) { 190 FEnv = Env; 191 FObj = Obj; 192 FMethod = Method; 193 } 194 195 void JavaMethod::CallVoidMethod(int Count, ...) { 196 va_list args; 197 va_start(args, Count); 198 FEnv->CallVoidMethodV(FObj, FMethod, args); 199 va_end(args); 200 201 if (FEnv->ExceptionCheck() == JNI_TRUE) { 202 Messages& messages = Messages::GetInstance(); 203 throw JavaException(FEnv, messages.GetMessage(ERROR_INVOKING_METHOD)); 204 } 205 } 206 207 JavaMethod::operator jmethodID () { 208 return FMethod; 209 } 210 211 //---------------------------------------------------------------------------- 212 213 JavaClass::JavaClass(JNIEnv *Env, TString Name) { 214 FEnv = Env; 215 FClassName = Name; 216 FClass = FEnv->FindClass(PlatformString(FClassName)); 217 218 if (FClass == NULL || FEnv->ExceptionCheck() == JNI_TRUE) { 219 Messages& messages = Messages::GetInstance(); 220 TString message = messages.GetMessage(CLASS_NOT_FOUND); 221 message = PlatformString::Format(message, FClassName.data()); 222 throw JavaException(FEnv, message); 223 } 224 } 225 226 JavaClass::~JavaClass() { 227 FEnv->DeleteLocalRef(FClass); 228 } 229 230 JavaStaticMethod JavaClass::GetStaticMethod(TString Name, TString Signature) { 231 jmethodID method = FEnv->GetStaticMethodID(FClass, PlatformString(Name), 232 PlatformString(Signature)); 233 234 if (method == NULL || FEnv->ExceptionCheck() == JNI_TRUE) { 235 Messages& messages = Messages::GetInstance(); 236 TString message = messages.GetMessage(METHOD_NOT_FOUND); 237 message = PlatformString::Format(message, Name.data(), 238 FClassName.data()); 239 throw JavaException(FEnv, message); 240 } 241 242 return JavaStaticMethod(FEnv, FClass, method); 243 } 244 245 JavaClass::operator jclass () { 246 return FClass; 247 } 248 249 //---------------------------------------------------------------------------- 250 251 void JavaStringArray::Initialize(size_t Size) { 252 JavaClass jstringClass(FEnv, _T("java/lang/String")); 253 254 if (FEnv->ExceptionCheck() == JNI_TRUE) { 255 Messages& messages = Messages::GetInstance(); 256 TString message = messages.GetMessage(CLASS_NOT_FOUND); 257 message = PlatformString::Format(message, _T("String")); 258 throw JavaException(FEnv, message.data()); 259 } 260 261 jstring str = PlatformString("").toJString(FEnv); 262 FData = (jobjectArray)FEnv->NewObjectArray((jsize)Size, jstringClass, str); 263 264 if (FEnv->ExceptionCheck() == JNI_TRUE) { 265 throw JavaException(FEnv, _T("Error")); 266 } 267 } 268 269 JavaStringArray::JavaStringArray(JNIEnv *Env, size_t Size) { 270 FEnv = Env; 271 Initialize(Size); 272 } 273 274 JavaStringArray::JavaStringArray(JNIEnv *Env, jobjectArray Data) { 275 FEnv = Env; 276 FData = Data; 277 } 278 279 JavaStringArray::JavaStringArray(JNIEnv *Env, std::list<TString> Items) { 280 FEnv = Env; 281 Initialize(Items.size()); 282 unsigned int index = 0; 283 284 for (std::list<TString>::const_iterator iterator = Items.begin(); 285 iterator != Items.end(); iterator++) { 286 TString item = *iterator; 287 SetValue(index, PlatformString(item).toJString(FEnv)); 288 index++; 289 } 290 } 291 292 jobjectArray JavaStringArray::GetData() { 293 return FData; 294 } 295 296 void JavaStringArray::SetValue(jsize Index, jstring Item) { 297 FEnv->SetObjectArrayElement(FData, Index, Item); 298 299 if (FEnv->ExceptionCheck() == JNI_TRUE) { 300 throw JavaException(FEnv, _T("Error")); 301 } 302 } 303 304 jstring JavaStringArray::GetValue(jsize Index) { 305 jstring result = (jstring)FEnv->GetObjectArrayElement(FData, Index); 306 307 if (FEnv->ExceptionCheck() == JNI_TRUE) { 308 throw JavaException(FEnv, _T("Error")); 309 } 310 311 return result; 312 } 313 314 unsigned int JavaStringArray::Count() { 315 unsigned int result = FEnv->GetArrayLength(FData); 316 317 if (FEnv->ExceptionCheck() == JNI_TRUE) { 318 throw JavaException(FEnv, _T("Error")); 319 } 320 321 return result; 322 }