--- /dev/null 2018-10-22 10:44:49.000000000 -0400 +++ new/src/jdk.packager/share/native/library/common/JavaTypes.cpp 2018-10-22 10:44:47.679182700 -0400 @@ -0,0 +1,322 @@ +/* + * Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#include "JavaTypes.h" +#include "PlatformString.h" + +#include + + +#ifdef DEBUG +TString JavaException::CreateExceptionMessage(JNIEnv* Env, + jthrowable Exception, jmethodID GetCauseMethod, + jmethodID GetStackTraceMethod, jmethodID ThrowableToTStringMethod, + jmethodID FrameToTStringMethod) { + + TString result; + jobjectArray frames = + (jobjectArray)Env->CallObjectMethod(Exception, GetStackTraceMethod); + + // Append Throwable.toTString(). + if (0 != frames) { + jstring jstr = (jstring)Env->CallObjectMethod(Exception, + ThrowableToTStringMethod); + const char* str = Env->GetStringUTFChars(jstr, 0); + result += PlatformString(str).toPlatformString(); + Env->ReleaseStringUTFChars(jstr, str); + Env->DeleteLocalRef(jstr); + } + + // Append stack trace if one exists. + if (Env->GetArrayLength(frames) > 0) { + jsize i = 0; + + for (i = 0; i < Env->GetArrayLength(frames); i++) { + // Get the string from the next frame and append it to + // the error message. + jobject frame = Env->GetObjectArrayElement(frames, i); + jstring obj = (jstring)Env->CallObjectMethod(frame, + FrameToTStringMethod); + const char* str = Env->GetStringUTFChars(obj, 0); + result += _T("\n "); + result += PlatformString(str).toPlatformString(); + Env->ReleaseStringUTFChars(obj, str); + Env->DeleteLocalRef(obj); + Env->DeleteLocalRef(frame); + } + } + + // If Exception has a cause then append the stack trace messages. + if (0 != frames) { + jthrowable cause = + (jthrowable)Env->CallObjectMethod(Exception, GetCauseMethod); + + if (cause != NULL) { + result += CreateExceptionMessage(Env, cause, GetCauseMethod, + GetStackTraceMethod, ThrowableToTStringMethod, + FrameToTStringMethod); + } + } + + return result; +} +#endif //DEBUG + +JavaException::JavaException() : Exception() {} + +//#ifdef WINDOWS +JavaException::JavaException(JNIEnv *Env, + const TString Message) : Exception(Message) { +//#endif //WINDOWS +//#ifdef POSIX +//JavaException::JavaException(JNIEnv *Env, TString message) { +//#endif //POSIX + + FEnv = Env; + FException = Env->ExceptionOccurred(); + Env->ExceptionClear(); + +#ifdef DEBUG + Platform& platform = Platform::GetInstance(); + + if (platform.GetDebugState() == dsNone) { + jclass ThrowableClass = Env->FindClass("java/lang/Throwable"); + + if (FEnv->ExceptionCheck() == JNI_TRUE) { + Env->ExceptionClear(); + return; + } + + jmethodID GetCauseMethod = Env->GetMethodID(ThrowableClass, + "getCause", "()Ljava/lang/Throwable;"); + + if (FEnv->ExceptionCheck() == JNI_TRUE) { + Env->ExceptionClear(); + return; + } + + jmethodID GetStackTraceMethod = Env->GetMethodID(ThrowableClass, + "getStackTrace", "()[Ljava/lang/StackTraceElement;"); + + if (FEnv->ExceptionCheck() == JNI_TRUE) { + Env->ExceptionClear(); + return; + } + + jmethodID ThrowableToTStringMethod = Env->GetMethodID(ThrowableClass, + "toString", "()Ljava/lang/String;"); + + if (FEnv->ExceptionCheck() == JNI_TRUE) { + Env->ExceptionClear(); + return; + } + + jclass FrameClass = Env->FindClass("java/lang/StackTraceElement"); + + if (FEnv->ExceptionCheck() == JNI_TRUE) { + Env->ExceptionClear(); + return; + } + + jmethodID FrameToTStringMethod = Env->GetMethodID(FrameClass, + "toString", "()Ljava/lang/String;"); + + if (FEnv->ExceptionCheck() == JNI_TRUE) { + Env->ExceptionClear(); + return; + } + + TString lmessage = CreateExceptionMessage(Env, FException, + GetCauseMethod, GetStackTraceMethod, ThrowableToTStringMethod, + FrameToTStringMethod); + SetMessage(lmessage); + } +#endif //DEBUG +} + +void JavaException::Rethrow() { + FEnv->Throw(FException); +} + +//---------------------------------------------------------------------------- + +JavaStaticMethod::JavaStaticMethod(JNIEnv *Env, jclass Class, jmethodID Method) { + FEnv = Env; + FClass = Class; + FMethod = Method; +} + +void JavaStaticMethod::CallVoidMethod(int Count, ...) { + va_list args; + va_start(args, Count); + FEnv->CallStaticVoidMethodV(FClass, FMethod, args); + va_end(args); + + if (FEnv->ExceptionCheck() == JNI_TRUE) { + Messages& messages = Messages::GetInstance(); + throw JavaException(FEnv, messages.GetMessage(ERROR_INVOKING_METHOD)); + } +} + +JavaStaticMethod::operator jmethodID () { + return FMethod; +} + +//---------------------------------------------------------------------------- + +JavaMethod::JavaMethod(JNIEnv *Env, jobject Obj, jmethodID Method) { + FEnv = Env; + FObj = Obj; + FMethod = Method; +} + +void JavaMethod::CallVoidMethod(int Count, ...) { + va_list args; + va_start(args, Count); + FEnv->CallVoidMethodV(FObj, FMethod, args); + va_end(args); + + if (FEnv->ExceptionCheck() == JNI_TRUE) { + Messages& messages = Messages::GetInstance(); + throw JavaException(FEnv, messages.GetMessage(ERROR_INVOKING_METHOD)); + } +} + +JavaMethod::operator jmethodID () { + return FMethod; +} + +//---------------------------------------------------------------------------- + +JavaClass::JavaClass(JNIEnv *Env, TString Name) { + FEnv = Env; + FClassName = Name; + FClass = FEnv->FindClass(PlatformString(FClassName)); + + if (FClass == NULL || FEnv->ExceptionCheck() == JNI_TRUE) { + Messages& messages = Messages::GetInstance(); + TString message = messages.GetMessage(CLASS_NOT_FOUND); + message = PlatformString::Format(message, FClassName.data()); + throw JavaException(FEnv, message); + } +} + +JavaClass::~JavaClass() { + FEnv->DeleteLocalRef(FClass); +} + +JavaStaticMethod JavaClass::GetStaticMethod(TString Name, TString Signature) { + jmethodID method = FEnv->GetStaticMethodID(FClass, PlatformString(Name), + PlatformString(Signature)); + + if (method == NULL || FEnv->ExceptionCheck() == JNI_TRUE) { + Messages& messages = Messages::GetInstance(); + TString message = messages.GetMessage(METHOD_NOT_FOUND); + message = PlatformString::Format(message, Name.data(), + FClassName.data()); + throw JavaException(FEnv, message); + } + + return JavaStaticMethod(FEnv, FClass, method); +} + +JavaClass::operator jclass () { + return FClass; +} + +//---------------------------------------------------------------------------- + +void JavaStringArray::Initialize(size_t Size) { + JavaClass jstringClass(FEnv, _T("java/lang/String")); + + if (FEnv->ExceptionCheck() == JNI_TRUE) { + Messages& messages = Messages::GetInstance(); + TString message = messages.GetMessage(CLASS_NOT_FOUND); + message = PlatformString::Format(message, _T("String")); + throw JavaException(FEnv, message.data()); + } + + jstring str = PlatformString("").toJString(FEnv); + FData = (jobjectArray)FEnv->NewObjectArray((jsize)Size, jstringClass, str); + + if (FEnv->ExceptionCheck() == JNI_TRUE) { + throw JavaException(FEnv, _T("Error")); + } +} + +JavaStringArray::JavaStringArray(JNIEnv *Env, size_t Size) { + FEnv = Env; + Initialize(Size); +} + +JavaStringArray::JavaStringArray(JNIEnv *Env, jobjectArray Data) { + FEnv = Env; + FData = Data; +} + +JavaStringArray::JavaStringArray(JNIEnv *Env, std::list Items) { + FEnv = Env; + Initialize(Items.size()); + unsigned int index = 0; + + for (std::list::const_iterator iterator = Items.begin(); + iterator != Items.end(); iterator++) { + TString item = *iterator; + SetValue(index, PlatformString(item).toJString(FEnv)); + index++; + } +} + +jobjectArray JavaStringArray::GetData() { + return FData; +} + +void JavaStringArray::SetValue(jsize Index, jstring Item) { + FEnv->SetObjectArrayElement(FData, Index, Item); + + if (FEnv->ExceptionCheck() == JNI_TRUE) { + throw JavaException(FEnv, _T("Error")); + } +} + +jstring JavaStringArray::GetValue(jsize Index) { + jstring result = (jstring)FEnv->GetObjectArrayElement(FData, Index); + + if (FEnv->ExceptionCheck() == JNI_TRUE) { + throw JavaException(FEnv, _T("Error")); + } + + return result; +} + +unsigned int JavaStringArray::Count() { + unsigned int result = FEnv->GetArrayLength(FData); + + if (FEnv->ExceptionCheck() == JNI_TRUE) { + throw JavaException(FEnv, _T("Error")); + } + + return result; +}