/* * Returns the main class name for the specified jar file. */ static jstring GetMainClassName(JNIEnv *env, char *jarname) { #define MAIN_CLASS "Main-Class" jclass cls; jmethodID mid; jobject jar, man, attr; jstring str, result = 0; NULL_CHECK0(cls = (*env)->FindClass(env, "java/util/jar/JarFile")); NULL_CHECK0(mid = (*env)->GetMethodID(env, cls, "<init>", "(Ljava/lang/String;)V")); NULL_CHECK0(str = NewPlatformString(env, jarname)); NULL_CHECK0(jar = (*env)->NewObject(env, cls, mid, str)); NULL_CHECK0(mid = (*env)->GetMethodID(env, cls, "getManifest", "()Ljava/util/jar/Manifest;")); man = (*env)->CallObjectMethod(env, jar, mid); if (man != 0) { NULL_CHECK0(mid = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, man), "getMainAttributes", "()Ljava/util/jar/Attributes;")); attr = (*env)->CallObjectMethod(env, man, mid); if (attr != 0) { NULL_CHECK0(mid = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, attr), "getValue", "(Ljava/lang/String;)Ljava/lang/String;")); NULL_CHECK0(str = NewPlatformString(env, MAIN_CLASS)); result = (*env)->CallObjectMethod(env, attr, mid, str); } } return result; }
/* * Returns a new array of Java string objects for the specified * array of platform strings. */ static jobjectArray NewPlatformStringArray(JNIEnv *env, char **strv, int strc) { jarray cls; jarray ary; int i; NULL_CHECK0(cls = (*env)->FindClass(env, "java/lang/String")); NULL_CHECK0(ary = (*env)->NewObjectArray(env, strc, cls, 0)); for (i = 0; i < strc; i++) { jstring str = NewPlatformString(env, *strv++); NULL_CHECK0(str); (*env)->SetObjectArrayElement(env, ary, i, str); (*env)->DeleteLocalRef(env, str); } return ary; }
/* * Returns a new Java string object for the specified platform string. */ static jstring NewPlatformString(JNIEnv *env, char *s) { int len = (int)strlen(s); jclass cls; jmethodID mid; jbyteArray ary; if (s == NULL) return 0; NULL_CHECK0(cls = (*env)->FindClass(env, "java/lang/String")); NULL_CHECK0(mid = (*env)->GetMethodID(env, cls, "<init>", "([B)V")); ary = (*env)->NewByteArray(env, len); if (ary != 0) { jstring str = 0; (*env)->SetByteArrayRegion(env, ary, 0, len, (jbyte *)s); if (!(*env)->ExceptionOccurred(env)) { str = (*env)->NewObject(env, cls, mid, ary); } (*env)->DeleteLocalRef(env, ary); return str; } return 0; }
/* * At this point we have the arguments to the application, and we need to * check with original stdargs in order to compare which of these truly * needs expansion. cmdtoargs will specify this if it finds a bare * (unquoted) argument containing a glob character(s) ie. * or ? */ jobjectArray CreateApplicationArgs(JNIEnv *env, char **strv, int argc) { int i, j, idx; size_t tlen; jobjectArray outArray, inArray; char *arg, **nargv; jboolean needs_expansion = JNI_FALSE; jmethodID mid; int stdargc; StdArg *stdargs; int *appArgIdx; int isTool; jclass cls = GetLauncherHelperClass(env); NULL_CHECK0(cls); if (argc == 0) { return NewPlatformStringArray(env, strv, argc); } // the holy grail we need to compare with. stdargs = JLI_GetStdArgs(); stdargc = JLI_GetStdArgc(); // sanity check, this should never happen if (argc > stdargc) { JLI_TraceLauncher("Warning: app args is larger than the original, %d %d\n", argc, stdargc); JLI_TraceLauncher("passing arguments as-is.\n"); return NewPlatformStringArray(env, strv, argc); } // sanity check, match the args we have, to the holy grail idx = JLI_GetAppArgIndex(); isTool = (idx == 0); if (isTool) { idx++; } // skip tool name JLI_TraceLauncher("AppArgIndex: %d points to %s\n", idx, stdargs[idx].arg); appArgIdx = calloc(argc, sizeof(int)); for (i = idx, j = 0; i < stdargc; i++) { if (isTool) { // filter -J used by tools to pass JVM options arg = stdargs[i].arg; if (arg[0] == '-' && arg[1] == 'J') { continue; } } appArgIdx[j++] = i; } // sanity check, ensure same number of arguments for application if (j != argc) { JLI_TraceLauncher("Warning: app args count doesn't match, %d %d\n", j, argc); JLI_TraceLauncher("passing arguments as-is.\n"); JLI_MemFree(appArgIdx); return NewPlatformStringArray(env, strv, argc); } // make a copy of the args which will be expanded in java if required. nargv = (char **)JLI_MemAlloc(argc * sizeof(char*)); for (i = 0; i < argc; i++) { jboolean arg_expand; j = appArgIdx[i]; arg_expand = (JLI_StrCmp(stdargs[j].arg, strv[i]) == 0) ? stdargs[j].has_wildcard : JNI_FALSE; if (needs_expansion == JNI_FALSE) needs_expansion = arg_expand; // indicator char + String + NULL terminator, the java method will strip // out the first character, the indicator character, so no matter what // we add the indicator tlen = 1 + JLI_StrLen(strv[i]) + 1; nargv[i] = (char *) JLI_MemAlloc(tlen); if (JLI_Snprintf(nargv[i], tlen, "%c%s", arg_expand ? 'T' : 'F', strv[i]) < 0) { return NULL; } JLI_TraceLauncher("%s\n", nargv[i]); } if (!needs_expansion) { // clean up any allocated memory and return back the old arguments for (i = 0 ; i < argc ; i++) { JLI_MemFree(nargv[i]); } JLI_MemFree(nargv); JLI_MemFree(appArgIdx); return NewPlatformStringArray(env, strv, argc); } NULL_CHECK0(mid = (*env)->GetStaticMethodID(env, cls, "expandArgs", "([Ljava/lang/String;)[Ljava/lang/String;")); // expand the arguments that require expansion, the java method will strip // out the indicator character. NULL_CHECK0(inArray = NewPlatformStringArray(env, nargv, argc)); outArray = (*env)->CallStaticObjectMethod(env, cls, mid, inArray); for (i = 0; i < argc; i++) { JLI_MemFree(nargv[i]); } JLI_MemFree(nargv); JLI_MemFree(appArgIdx); return outArray; }
/* * At this point we have the arguments to the application, and we need to * check with original stdargs in order to compare which of these truly * needs expansion. cmdtoargs will specify this if it finds a bare * (unquoted) argument containing a glob character(s) ie. * or ? */ jobjectArray CreateApplicationArgs(JNIEnv *env, char **strv, int argc) { int i, j, idx, tlen; jobjectArray outArray, inArray; char *ostart, *astart, **nargv; jboolean needs_expansion = JNI_FALSE; jmethodID mid; int stdargc; StdArg *stdargs; jclass cls = GetLauncherHelperClass(env); NULL_CHECK0(cls); if (argc == 0) { return NewPlatformStringArray(env, strv, argc); } // the holy grail we need to compare with. stdargs = JLI_GetStdArgs(); stdargc = JLI_GetStdArgc(); // sanity check, this should never happen if (argc > stdargc) { JLI_TraceLauncher("Warning: app args is larger than the original, %d %d\n", argc, stdargc); JLI_TraceLauncher("passing arguments as-is.\n"); return NewPlatformStringArray(env, strv, argc); } // sanity check, match the args we have, to the holy grail idx = stdargc - argc; ostart = stdargs[idx].arg; astart = strv[0]; // sanity check, ensure that the first argument of the arrays are the same if (JLI_StrCmp(ostart, astart) != 0) { // some thing is amiss the args don't match JLI_TraceLauncher("Warning: app args parsing error\n"); JLI_TraceLauncher("passing arguments as-is\n"); return NewPlatformStringArray(env, strv, argc); } // make a copy of the args which will be expanded in java if required. nargv = (char **)JLI_MemAlloc(argc * sizeof(char*)); for (i = 0, j = idx; i < argc; i++, j++) { jboolean arg_expand = (JLI_StrCmp(stdargs[j].arg, strv[i]) == 0) ? stdargs[j].has_wildcard : JNI_FALSE; if (needs_expansion == JNI_FALSE) needs_expansion = arg_expand; // indicator char + String + NULL terminator, the java method will strip // out the first character, the indicator character, so no matter what // we add the indicator tlen = 1 + JLI_StrLen(strv[i]) + 1; nargv[i] = (char *) JLI_MemAlloc(tlen); if (JLI_Snprintf(nargv[i], tlen, "%c%s", arg_expand ? 'T' : 'F', strv[i]) < 0) { return NULL; } JLI_TraceLauncher("%s\n", nargv[i]); } if (!needs_expansion) { // clean up any allocated memory and return back the old arguments for (i = 0 ; i < argc ; i++) { JLI_MemFree(nargv[i]); } JLI_MemFree(nargv); return NewPlatformStringArray(env, strv, argc); } NULL_CHECK0(mid = (*env)->GetStaticMethodID(env, cls, "expandArgs", "([Ljava/lang/String;)[Ljava/lang/String;")); // expand the arguments that require expansion, the java method will strip // out the indicator character. inArray = NewPlatformStringArray(env, nargv, argc); outArray = (*env)->CallStaticObjectMethod(env, cls, mid, inArray); for (i = 0; i < argc; i++) { JLI_MemFree(nargv[i]); } JLI_MemFree(nargv); return outArray; }