6742159: (launcher) improve the java launching mechanism
Improves launching, also addresses 6694671 and 6749732 Reviewed-by: darcy, dholmes
This commit is contained in:
parent
6caae4568d
commit
d799afdc04
@ -50,11 +50,6 @@
|
||||
#define JAR_ERROR2 "Error: Unable to access jarfile %s"
|
||||
#define JAR_ERROR3 "Error: Invalid or corrupt jarfile %s"
|
||||
|
||||
#define CLS_ERROR1 "Error: Could not find the main class %s.\n" JNI_ERROR
|
||||
#define CLS_ERROR2 "Error: Failed to load Main Class: %s\n%s"
|
||||
#define CLS_ERROR3 "Error: No main method found in specified class.\n" GEN_ERROR
|
||||
#define CLS_ERROR4 "Error: Main method not public\n" GEN_ERROR
|
||||
|
||||
#define CFG_WARN1 "Warning: %s VM not supported; %s VM will be used"
|
||||
#define CFG_WARN2 "Warning: No leading - on line %d of `%s'"
|
||||
#define CFG_WARN3 "Warning: Missing VM type on line %d of `%s'"
|
||||
|
@ -102,8 +102,7 @@ static jboolean InitializeJVM(JavaVM **pvm, JNIEnv **penv,
|
||||
InvocationFunctions *ifn);
|
||||
static jstring NewPlatformString(JNIEnv *env, char *s);
|
||||
static jobjectArray NewPlatformStringArray(JNIEnv *env, char **strv, int strc);
|
||||
static jclass LoadClass(JNIEnv *env, char *name);
|
||||
static jstring GetMainClassName(JNIEnv *env, char *jarname);
|
||||
static jclass LoadMainClass(JNIEnv *env, jboolean isJar, char *name);
|
||||
|
||||
static void TranslateApplicationArgs(int jargc, const char **jargv, int *pargc, char ***pargv);
|
||||
static jboolean AddApplicationOptions(int cpathc, const char **cpathv);
|
||||
@ -301,6 +300,22 @@ JLI_Launch(int argc, char ** argv, /* main argc, argc */
|
||||
|
||||
}
|
||||
|
||||
#define CHECK_EXCEPTION_NULL_LEAVE(e) \
|
||||
if ((*env)->ExceptionOccurred(env)) { \
|
||||
JLI_ReportExceptionDescription(env); \
|
||||
goto leave; \
|
||||
} \
|
||||
if ((e) == NULL) { \
|
||||
JLI_ReportErrorMessage(JNI_ERROR); \
|
||||
goto leave; \
|
||||
}
|
||||
|
||||
#define CHECK_EXCEPTION_LEAVE(rv) \
|
||||
if ((*env)->ExceptionOccurred(env)) { \
|
||||
JLI_ReportExceptionDescription(env); \
|
||||
ret = (rv); \
|
||||
goto leave; \
|
||||
}
|
||||
|
||||
int JNICALL
|
||||
JavaMain(void * _args)
|
||||
@ -321,9 +336,7 @@ JavaMain(void * _args)
|
||||
int ret = 0;
|
||||
jlong start, end;
|
||||
|
||||
|
||||
/* Initialize the virtual machine */
|
||||
|
||||
start = CounterGet();
|
||||
if (!InitializeJVM(&vm, &env, &ifn)) {
|
||||
JLI_ReportErrorMessage(JVM_ERROR1);
|
||||
@ -332,11 +345,7 @@ JavaMain(void * _args)
|
||||
|
||||
if (printVersion || showVersion) {
|
||||
PrintJavaVersion(env, showVersion);
|
||||
if ((*env)->ExceptionOccurred(env)) {
|
||||
JLI_ReportExceptionDescription(env);
|
||||
JLI_ReportErrorMessage(JNI_ERROR);
|
||||
goto leave;
|
||||
}
|
||||
CHECK_EXCEPTION_LEAVE(0);
|
||||
if (printVersion) {
|
||||
ret = 0;
|
||||
goto leave;
|
||||
@ -346,11 +355,7 @@ JavaMain(void * _args)
|
||||
/* If the user specified neither a class name nor a JAR file */
|
||||
if (printXUsage || printUsage || (jarfile == 0 && classname == 0)) {
|
||||
PrintUsage(env, printXUsage);
|
||||
if ((*env)->ExceptionOccurred(env)) {
|
||||
JLI_ReportExceptionDescription(env);
|
||||
JLI_ReportErrorMessage(JNI_ERROR);
|
||||
ret=1;
|
||||
}
|
||||
CHECK_EXCEPTION_LEAVE(1);
|
||||
goto leave;
|
||||
}
|
||||
|
||||
@ -395,99 +400,25 @@ JavaMain(void * _args)
|
||||
* the environment (and remove these comments).
|
||||
*/
|
||||
if (jarfile != 0) {
|
||||
mainClassName = GetMainClassName(env, jarfile);
|
||||
if ((*env)->ExceptionOccurred(env)) {
|
||||
JLI_ReportExceptionDescription(env);
|
||||
JLI_ReportErrorMessage(JNI_ERROR);
|
||||
goto leave;
|
||||
}
|
||||
if (mainClassName == NULL) {
|
||||
JLI_ReportErrorMessage(JAR_ERROR1,jarfile, GEN_ERROR);
|
||||
goto leave;
|
||||
}
|
||||
classname = (char *)(*env)->GetStringUTFChars(env, mainClassName, 0);
|
||||
if (classname == NULL) {
|
||||
JLI_ReportExceptionDescription(env);
|
||||
JLI_ReportErrorMessage(JNI_ERROR);
|
||||
goto leave;
|
||||
}
|
||||
mainClass = LoadClass(env, classname);
|
||||
if(mainClass == NULL) { /* exception occured */
|
||||
JLI_ReportExceptionDescription(env);
|
||||
JLI_ReportErrorMessage(CLS_ERROR1, classname);
|
||||
goto leave;
|
||||
}
|
||||
(*env)->ReleaseStringUTFChars(env, mainClassName, classname);
|
||||
mainClass = LoadMainClass(env, JNI_TRUE, jarfile);
|
||||
} else {
|
||||
mainClassName = NewPlatformString(env, classname);
|
||||
if (mainClassName == NULL) {
|
||||
JLI_ReportErrorMessage(CLS_ERROR2, classname, GEN_ERROR);
|
||||
goto leave;
|
||||
}
|
||||
classname = (char *)(*env)->GetStringUTFChars(env, mainClassName, 0);
|
||||
if (classname == NULL) {
|
||||
JLI_ReportExceptionDescription(env);
|
||||
JLI_ReportErrorMessage(JNI_ERROR);
|
||||
goto leave;
|
||||
}
|
||||
mainClass = LoadClass(env, classname);
|
||||
if(mainClass == NULL) { /* exception occured */
|
||||
JLI_ReportExceptionDescription(env);
|
||||
JLI_ReportErrorMessage(CLS_ERROR1, classname);
|
||||
goto leave;
|
||||
}
|
||||
(*env)->ReleaseStringUTFChars(env, mainClassName, classname);
|
||||
mainClass = LoadMainClass(env, JNI_FALSE, classname);
|
||||
}
|
||||
CHECK_EXCEPTION_NULL_LEAVE(mainClass);
|
||||
|
||||
/* Get the application's main method */
|
||||
/*
|
||||
* The LoadMainClass not only loads the main class, it will also ensure
|
||||
* that the main method's signature is correct, therefore further checking
|
||||
* is not required. The main method is invoked here so that extraneous java
|
||||
* stacks are not in the application stack trace.
|
||||
*/
|
||||
mainID = (*env)->GetStaticMethodID(env, mainClass, "main",
|
||||
"([Ljava/lang/String;)V");
|
||||
if (mainID == NULL) {
|
||||
if ((*env)->ExceptionOccurred(env)) {
|
||||
JLI_ReportExceptionDescription(env);
|
||||
JLI_ReportErrorMessage(JNI_ERROR);
|
||||
} else {
|
||||
JLI_ReportErrorMessage(CLS_ERROR3);
|
||||
}
|
||||
goto leave;
|
||||
}
|
||||
|
||||
{ /* Make sure the main method is public */
|
||||
jint mods;
|
||||
jmethodID mid;
|
||||
jobject obj = (*env)->ToReflectedMethod(env, mainClass,
|
||||
mainID, JNI_TRUE);
|
||||
|
||||
if( obj == NULL) { /* exception occurred */
|
||||
JLI_ReportExceptionDescription(env);
|
||||
JLI_ReportErrorMessage(JNI_ERROR);
|
||||
goto leave;
|
||||
}
|
||||
|
||||
mid =
|
||||
(*env)->GetMethodID(env,
|
||||
(*env)->GetObjectClass(env, obj),
|
||||
"getModifiers", "()I");
|
||||
if ((*env)->ExceptionOccurred(env)) {
|
||||
JLI_ReportExceptionDescription(env);
|
||||
JLI_ReportErrorMessage(JNI_ERROR);
|
||||
goto leave;
|
||||
}
|
||||
|
||||
mods = (*env)->CallIntMethod(env, obj, mid);
|
||||
if ((mods & 1) == 0) { /* if (!Modifier.isPublic(mods)) ... */
|
||||
JLI_ReportErrorMessage(CLS_ERROR4);
|
||||
goto leave;
|
||||
}
|
||||
}
|
||||
CHECK_EXCEPTION_NULL_LEAVE(mainID);
|
||||
|
||||
/* Build argument array */
|
||||
mainArgs = NewPlatformStringArray(env, argv, argc);
|
||||
if (mainArgs == NULL) {
|
||||
JLI_ReportExceptionDescription(env);
|
||||
JLI_ReportErrorMessage(JNI_ERROR);
|
||||
goto leave;
|
||||
}
|
||||
CHECK_EXCEPTION_NULL_LEAVE(mainArgs);
|
||||
|
||||
/* Invoke main method. */
|
||||
(*env)->CallStaticVoidMethod(env, mainClass, mainID, mainArgs);
|
||||
@ -498,8 +429,9 @@ JavaMain(void * _args)
|
||||
*/
|
||||
ret = (*env)->ExceptionOccurred(env) == NULL ? 0 : 1;
|
||||
|
||||
leave:
|
||||
/*
|
||||
* Detach the main thread so that it appears to have ended when
|
||||
* Always detach the main thread so that it appears to have ended when
|
||||
* the application's main method exits. This will invoke the
|
||||
* uncaught exception handler machinery if main threw an
|
||||
* exception. An uncaught exception handler cannot change the
|
||||
@ -508,10 +440,7 @@ JavaMain(void * _args)
|
||||
if ((*vm)->DetachCurrentThread(vm) != 0) {
|
||||
JLI_ReportErrorMessage(JVM_ERROR2);
|
||||
ret = 1;
|
||||
goto leave;
|
||||
}
|
||||
|
||||
leave:
|
||||
/*
|
||||
* Wait for all non-daemon threads to end, then destroy the VM.
|
||||
* This will actually create a trivial new Java waiter thread
|
||||
@ -525,7 +454,6 @@ JavaMain(void * _args)
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Checks the command line options to find which JVM type was
|
||||
* specified. If no command line option was given for the JVM type,
|
||||
@ -1159,7 +1087,7 @@ static jstring getPlatformEncoding(JNIEnv *env) {
|
||||
if (propname) {
|
||||
jclass cls;
|
||||
jmethodID mid;
|
||||
NULL_CHECK0 (cls = (*env)->FindClass(env, "java/lang/System"));
|
||||
NULL_CHECK0 (cls = FindBootStrapClass(env, "java/lang/System"));
|
||||
NULL_CHECK0 (mid = (*env)->GetStaticMethodID(
|
||||
env, cls,
|
||||
"getProperty",
|
||||
@ -1174,7 +1102,7 @@ static jstring getPlatformEncoding(JNIEnv *env) {
|
||||
static jboolean isEncodingSupported(JNIEnv *env, jstring enc) {
|
||||
jclass cls;
|
||||
jmethodID mid;
|
||||
NULL_CHECK0 (cls = (*env)->FindClass(env, "java/nio/charset/Charset"));
|
||||
NULL_CHECK0 (cls = FindBootStrapClass(env, "java/nio/charset/Charset"));
|
||||
NULL_CHECK0 (mid = (*env)->GetStaticMethodID(
|
||||
env, cls,
|
||||
"isSupported",
|
||||
@ -1203,8 +1131,8 @@ NewPlatformString(JNIEnv *env, char *s)
|
||||
jstring str = 0;
|
||||
(*env)->SetByteArrayRegion(env, ary, 0, len, (jbyte *)s);
|
||||
if (!(*env)->ExceptionOccurred(env)) {
|
||||
NULL_CHECK0(cls = FindBootStrapClass(env, "java/lang/String"));
|
||||
if (isEncodingSupported(env, enc) == JNI_TRUE) {
|
||||
NULL_CHECK0(cls = (*env)->FindClass(env, "java/lang/String"));
|
||||
NULL_CHECK0(mid = (*env)->GetMethodID(env, cls, "<init>",
|
||||
"([BLjava/lang/String;)V"));
|
||||
str = (*env)->NewObject(env, cls, mid, ary, enc);
|
||||
@ -1215,7 +1143,6 @@ NewPlatformString(JNIEnv *env, char *s)
|
||||
the encoding name, in which the StringCoding class will
|
||||
pickup the iso-8859-1 as the fallback converter for us.
|
||||
*/
|
||||
NULL_CHECK0(cls = (*env)->FindClass(env, "java/lang/String"));
|
||||
NULL_CHECK0(mid = (*env)->GetMethodID(env, cls, "<init>",
|
||||
"([B)V"));
|
||||
str = (*env)->NewObject(env, cls, mid, ary);
|
||||
@ -1238,7 +1165,7 @@ NewPlatformStringArray(JNIEnv *env, char **strv, int strc)
|
||||
jarray ary;
|
||||
int i;
|
||||
|
||||
NULL_CHECK0(cls = (*env)->FindClass(env, "java/lang/String"));
|
||||
NULL_CHECK0(cls = FindBootStrapClass(env, "java/lang/String"));
|
||||
NULL_CHECK0(ary = (*env)->NewObjectArray(env, strc, cls, 0));
|
||||
for (i = 0; i < strc; i++) {
|
||||
jstring str = NewPlatformString(env, *strv++);
|
||||
@ -1250,25 +1177,26 @@ NewPlatformStringArray(JNIEnv *env, char **strv, int strc)
|
||||
}
|
||||
|
||||
/*
|
||||
* Loads a class, convert the '.' to '/'.
|
||||
* Loads a class and verifies that the main class is present and it is ok to
|
||||
* call it for more details refer to the java implementation.
|
||||
*/
|
||||
static jclass
|
||||
LoadClass(JNIEnv *env, char *name)
|
||||
LoadMainClass(JNIEnv *env, jboolean isJar, char *name)
|
||||
{
|
||||
char *buf = JLI_MemAlloc(JLI_StrLen(name) + 1);
|
||||
char *s = buf, *t = name, c;
|
||||
jclass cls;
|
||||
jmethodID mid;
|
||||
jstring str;
|
||||
jobject result;
|
||||
jlong start, end;
|
||||
|
||||
if (JLI_IsTraceLauncher())
|
||||
if (JLI_IsTraceLauncher()) {
|
||||
start = CounterGet();
|
||||
|
||||
do {
|
||||
c = *t++;
|
||||
*s++ = (c == '.') ? '/' : c;
|
||||
} while (c != '\0');
|
||||
cls = (*env)->FindClass(env, buf);
|
||||
JLI_MemFree(buf);
|
||||
}
|
||||
NULL_CHECK0(cls = FindBootStrapClass(env, "sun/launcher/LauncherHelper"));
|
||||
NULL_CHECK0(mid = (*env)->GetStaticMethodID(env, cls, "checkAndLoadMain",
|
||||
"(ZZLjava/lang/String;)Ljava/lang/Object;"));
|
||||
str = (*env)->NewStringUTF(env, name);
|
||||
result = (*env)->CallStaticObjectMethod(env, cls, mid, JNI_TRUE, isJar, str);
|
||||
|
||||
if (JLI_IsTraceLauncher()) {
|
||||
end = CounterGet();
|
||||
@ -1277,49 +1205,9 @@ LoadClass(JNIEnv *env, char *name)
|
||||
printf("----_JAVA_LAUNCHER_DEBUG----\n");
|
||||
}
|
||||
|
||||
return cls;
|
||||
return (jclass)result;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* For tools, convert command line args thus:
|
||||
* javac -cp foo:foo/"*" -J-ms32m ...
|
||||
@ -1522,7 +1410,7 @@ PrintJavaVersion(JNIEnv *env, jboolean extraLF)
|
||||
jclass ver;
|
||||
jmethodID print;
|
||||
|
||||
NULL_CHECK(ver = (*env)->FindClass(env, "sun/misc/Version"));
|
||||
NULL_CHECK(ver = FindBootStrapClass(env, "sun/misc/Version"));
|
||||
NULL_CHECK(print = (*env)->GetStaticMethodID(env,
|
||||
ver,
|
||||
(extraLF == JNI_TRUE) ? "println" : "print",
|
||||
@ -1534,7 +1422,7 @@ PrintJavaVersion(JNIEnv *env, jboolean extraLF)
|
||||
}
|
||||
|
||||
/*
|
||||
* Prints default usage or the Xusage message, see sun.launcher.LauncherHelp.java
|
||||
* Prints default usage or the Xusage message, see sun.launcher.LauncherHelper.java
|
||||
*/
|
||||
static void
|
||||
PrintUsage(JNIEnv* env, jboolean doXUsage)
|
||||
@ -1544,7 +1432,7 @@ PrintUsage(JNIEnv* env, jboolean doXUsage)
|
||||
jstring jprogname, vm1, vm2;
|
||||
int i;
|
||||
|
||||
NULL_CHECK(cls = (*env)->FindClass(env, "sun/launcher/LauncherHelp"));
|
||||
NULL_CHECK(cls = FindBootStrapClass(env, "sun/launcher/LauncherHelper"));
|
||||
|
||||
|
||||
if (doXUsage) {
|
||||
|
@ -180,4 +180,15 @@ static int ContinueInNewThread(InvocationFunctions* ifn, int argc, char** argv,
|
||||
*/
|
||||
void InitLauncher(jboolean javaw);
|
||||
|
||||
/*
|
||||
* This allows for finding classes from the VM's bootstrap class loader directly,
|
||||
* FindClass uses the application class loader internally, this will cause
|
||||
* unnecessary searching of the classpath for the required classes.
|
||||
*
|
||||
*/
|
||||
typedef jclass (JNICALL FindClassFromBootLoader_t(JNIEnv *env,
|
||||
const char *name,
|
||||
jboolean throwError));
|
||||
|
||||
jclass FindBootStrapClass(JNIEnv *env, const char *classname);
|
||||
#endif /* _JAVA_H_ */
|
||||
|
@ -1,138 +0,0 @@
|
||||
|
||||
/*
|
||||
* Copyright 2007 Sun Microsystems, Inc. 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. Sun designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
||||
* CA 95054 USA or visit www.sun.com if you need additional information or
|
||||
* have any questions.
|
||||
*/
|
||||
|
||||
package sun.launcher;
|
||||
|
||||
/*
|
||||
*
|
||||
* <p><b>This is NOT part of any API supported by Sun Microsystems.
|
||||
* If you write code that depends on this, you do so at your own
|
||||
* risk. This code and its internal interfaces are subject to change
|
||||
* or deletion without notice.</b>
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* A utility package for the java(1), javaw(1) launchers.
|
||||
*/
|
||||
import java.io.File;
|
||||
import java.io.PrintStream;
|
||||
import java.util.ResourceBundle;
|
||||
import java.text.MessageFormat;
|
||||
|
||||
public class LauncherHelp {
|
||||
|
||||
private static final String defaultBundleName = "sun.launcher.resources.launcher";
|
||||
private static ResourceBundle javarb = ResourceBundle.getBundle(defaultBundleName);
|
||||
|
||||
private static StringBuilder outBuf = new StringBuilder();
|
||||
|
||||
/** Creates a new instance of LauncherHelp, keep it a singleton */
|
||||
private LauncherHelp(){}
|
||||
|
||||
|
||||
/**
|
||||
* A private helper method to get a localized message and also
|
||||
* apply any arguments that we might pass.
|
||||
*/
|
||||
private static String getLocalizedMessage(String key, Object... args) {
|
||||
String msg = javarb.getString(key);
|
||||
return (args != null) ? MessageFormat.format(msg, args) : msg;
|
||||
}
|
||||
|
||||
/**
|
||||
* The java -help message is split into 3 parts, an invariant, followed
|
||||
* by a set of platform dependent variant messages, finally an invariant
|
||||
* set of lines.
|
||||
* This method initializes the help message for the first time, and also
|
||||
* assembles the invariant header part of the message.
|
||||
*/
|
||||
static void initHelpMessage(String progname) {
|
||||
outBuf = outBuf.append(getLocalizedMessage("java.launcher.opt.header", (progname == null) ? "java" : progname ));
|
||||
outBuf = outBuf.append(getLocalizedMessage("java.launcher.opt.datamodel", 32));
|
||||
outBuf = outBuf.append(getLocalizedMessage("java.launcher.opt.datamodel", 64));
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends the vm selection messages to the header, already created.
|
||||
* initHelpSystem must already be called.
|
||||
*/
|
||||
static void appendVmSelectMessage(String vm1, String vm2) {
|
||||
outBuf = outBuf.append(getLocalizedMessage("java.launcher.opt.vmselect", vm1, vm2));
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends the vm synoym message to the header, already created.
|
||||
* initHelpSystem must be called before using this method.
|
||||
*/
|
||||
static void appendVmSynonymMessage(String vm1, String vm2) {
|
||||
outBuf = outBuf.append(getLocalizedMessage("java.launcher.opt.hotspot", vm1, vm2));
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends the vm Ergo message to the header, already created.
|
||||
* initHelpSystem must be called before using this method.
|
||||
*/
|
||||
static void appendVmErgoMessage(boolean isServerClass, String vm) {
|
||||
outBuf = outBuf.append(getLocalizedMessage("java.launcher.ergo.message1", vm));
|
||||
outBuf = (isServerClass)
|
||||
? outBuf.append(",\n" + getLocalizedMessage("java.launcher.ergo.message2") + "\n\n")
|
||||
: outBuf.append(".\n\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends the last invariant part to the previously created messages,
|
||||
* and finishes up the printing to the desired output stream.
|
||||
* initHelpSystem must be called before using this method.
|
||||
*/
|
||||
static void printHelpMessage(boolean printToStderr) {
|
||||
PrintStream ostream = (printToStderr) ? System.err : System.out;
|
||||
outBuf = outBuf.append(getLocalizedMessage("java.launcher.opt.footer", File.pathSeparator));
|
||||
ostream.println(outBuf.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints the Xusage text to the desired output stream.
|
||||
*/
|
||||
static void printXUsageMessage(boolean printToStderr) {
|
||||
PrintStream ostream = (printToStderr) ? System.err : System.out;
|
||||
ostream.println(getLocalizedMessage("java.launcher.X.usage", File.pathSeparator));
|
||||
}
|
||||
|
||||
/* Test code */
|
||||
public static void main(String[] args) {
|
||||
initHelpMessage("java");
|
||||
appendVmSelectMessage("-client", "client");
|
||||
appendVmSelectMessage("-server", "server");
|
||||
appendVmSynonymMessage("-hotspot", "client");
|
||||
appendVmErgoMessage(true, "server");
|
||||
printHelpMessage(true);
|
||||
|
||||
System.err.println("------------------------------------");
|
||||
|
||||
printXUsageMessage(true);
|
||||
}
|
||||
}
|
238
jdk/src/share/classes/sun/launcher/LauncherHelper.java
Normal file
238
jdk/src/share/classes/sun/launcher/LauncherHelper.java
Normal file
@ -0,0 +1,238 @@
|
||||
|
||||
/*
|
||||
* Copyright 2007-2008 Sun Microsystems, Inc. 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. Sun designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
||||
* CA 95054 USA or visit www.sun.com if you need additional information or
|
||||
* have any questions.
|
||||
*/
|
||||
|
||||
package sun.launcher;
|
||||
|
||||
/*
|
||||
*
|
||||
* <p><b>This is NOT part of any API supported by Sun Microsystems.
|
||||
* If you write code that depends on this, you do so at your own
|
||||
* risk. This code and its internal interfaces are subject to change
|
||||
* or deletion without notice.</b>
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* A utility package for the java(1), javaw(1) launchers.
|
||||
* The following are helper methods that the native launcher uses
|
||||
* to perform checks etc. using JNI, see src/share/bin/java.c
|
||||
*/
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintStream;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.ResourceBundle;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.jar.Attributes;
|
||||
import java.util.jar.JarFile;
|
||||
import java.util.jar.Manifest;
|
||||
|
||||
public enum LauncherHelper {
|
||||
INSTANCE;
|
||||
private static final String defaultBundleName =
|
||||
"sun.launcher.resources.launcher";
|
||||
private static ResourceBundle javarb =
|
||||
ResourceBundle.getBundle(defaultBundleName);
|
||||
private static final String MAIN_CLASS = "Main-Class";
|
||||
|
||||
private static StringBuilder outBuf = new StringBuilder();
|
||||
|
||||
/**
|
||||
* A private helper method to get a localized message and also
|
||||
* apply any arguments that we might pass.
|
||||
*/
|
||||
private static String getLocalizedMessage(String key, Object... args) {
|
||||
String msg = javarb.getString(key);
|
||||
return (args != null) ? MessageFormat.format(msg, args) : msg;
|
||||
}
|
||||
|
||||
/**
|
||||
* The java -help message is split into 3 parts, an invariant, followed
|
||||
* by a set of platform dependent variant messages, finally an invariant
|
||||
* set of lines.
|
||||
* This method initializes the help message for the first time, and also
|
||||
* assembles the invariant header part of the message.
|
||||
*/
|
||||
static void initHelpMessage(String progname) {
|
||||
outBuf = outBuf.append(getLocalizedMessage("java.launcher.opt.header",
|
||||
(progname == null) ? "java" : progname ));
|
||||
outBuf = outBuf.append(getLocalizedMessage("java.launcher.opt.datamodel",
|
||||
32));
|
||||
outBuf = outBuf.append(getLocalizedMessage("java.launcher.opt.datamodel",
|
||||
64));
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends the vm selection messages to the header, already created.
|
||||
* initHelpSystem must already be called.
|
||||
*/
|
||||
static void appendVmSelectMessage(String vm1, String vm2) {
|
||||
outBuf = outBuf.append(getLocalizedMessage("java.launcher.opt.vmselect",
|
||||
vm1, vm2));
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends the vm synoym message to the header, already created.
|
||||
* initHelpSystem must be called before using this method.
|
||||
*/
|
||||
static void appendVmSynonymMessage(String vm1, String vm2) {
|
||||
outBuf = outBuf.append(getLocalizedMessage("java.launcher.opt.hotspot",
|
||||
vm1, vm2));
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends the vm Ergo message to the header, already created.
|
||||
* initHelpSystem must be called before using this method.
|
||||
*/
|
||||
static void appendVmErgoMessage(boolean isServerClass, String vm) {
|
||||
outBuf = outBuf.append(getLocalizedMessage("java.launcher.ergo.message1",
|
||||
vm));
|
||||
outBuf = (isServerClass)
|
||||
? outBuf.append(",\n" +
|
||||
getLocalizedMessage("java.launcher.ergo.message2") + "\n\n")
|
||||
: outBuf.append(".\n\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends the last invariant part to the previously created messages,
|
||||
* and finishes up the printing to the desired output stream.
|
||||
* initHelpSystem must be called before using this method.
|
||||
*/
|
||||
static void printHelpMessage(boolean printToStderr) {
|
||||
PrintStream ostream = (printToStderr) ? System.err : System.out;
|
||||
outBuf = outBuf.append(getLocalizedMessage("java.launcher.opt.footer",
|
||||
File.pathSeparator));
|
||||
ostream.println(outBuf.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints the Xusage text to the desired output stream.
|
||||
*/
|
||||
static void printXUsageMessage(boolean printToStderr) {
|
||||
PrintStream ostream = (printToStderr) ? System.err : System.out;
|
||||
ostream.println(getLocalizedMessage("java.launcher.X.usage",
|
||||
File.pathSeparator));
|
||||
}
|
||||
|
||||
static String getMainClassFromJar(String jarname) throws IOException {
|
||||
JarFile jarFile = null;
|
||||
try {
|
||||
jarFile = new JarFile(jarname);
|
||||
Manifest manifest = jarFile.getManifest();
|
||||
if (manifest == null) {
|
||||
throw new IOException("manifest not found in " + jarname);
|
||||
}
|
||||
Attributes mainAttrs = manifest.getMainAttributes();
|
||||
if (mainAttrs == null) {
|
||||
throw new IOException("no main mainifest attributes, in " +
|
||||
jarname);
|
||||
}
|
||||
return mainAttrs.getValue(MAIN_CLASS);
|
||||
} finally {
|
||||
if (jarFile != null) {
|
||||
jarFile.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method does the following:
|
||||
* 1. gets the classname from a Jar's manifest, if necessary
|
||||
* 2. loads the class using the System ClassLoader
|
||||
* 3. ensures the availability and accessibility of the main method,
|
||||
* using signatureDiagnostic method.
|
||||
* a. does the class exist
|
||||
* b. is there a main
|
||||
* c. is the main public
|
||||
* d. is the main static
|
||||
* c. does the main take a String array for args
|
||||
* 4. and off we go......
|
||||
*
|
||||
* @param printToStderr
|
||||
* @param isJar
|
||||
* @param name
|
||||
* @return
|
||||
* @throws java.lang.Exception
|
||||
*/
|
||||
public static Object checkAndLoadMain(boolean printToStderr,
|
||||
boolean isJar, String name) throws Exception {
|
||||
// get the class name
|
||||
String classname = (isJar) ? getMainClassFromJar(name) : name;
|
||||
classname = classname.replace('/', '.');
|
||||
ClassLoader loader = ClassLoader.getSystemClassLoader();
|
||||
Class<?> clazz = null;
|
||||
PrintStream ostream = (printToStderr) ? System.err : System.out;
|
||||
try {
|
||||
clazz = loader.loadClass(classname);
|
||||
} catch (ClassNotFoundException cnfe) {
|
||||
ostream.println(getLocalizedMessage("java.launcher.cls.error1", classname));
|
||||
throw new RuntimeException("Could not find the main class " + classname);
|
||||
}
|
||||
signatureDiagnostic(ostream, clazz);
|
||||
return clazz;
|
||||
}
|
||||
|
||||
static void signatureDiagnostic(PrintStream ostream, Class<?> clazz) {
|
||||
String classname = clazz.getName();
|
||||
Method method = null;
|
||||
try {
|
||||
method = clazz.getMethod("main", String[].class);
|
||||
} catch (Exception e) {
|
||||
ostream.println(getLocalizedMessage("java.launcher.cls.error4",
|
||||
classname));
|
||||
throw new RuntimeException("Main method not found in " + classname);
|
||||
}
|
||||
/*
|
||||
* Usually the getMethod (above) will choose the correct method, based
|
||||
* on its modifiers and parameter types, the only check required is the
|
||||
* getReturnType check as getMethod does not check for this, all the
|
||||
* other modifier tests are redundant, and are simply here for safety.
|
||||
*/
|
||||
int mod = method.getModifiers();
|
||||
if (!Modifier.isStatic(mod)) {
|
||||
ostream.println(getLocalizedMessage("java.launcher.cls.error2",
|
||||
"static", classname));
|
||||
throw new RuntimeException("Main method is not static in class " +
|
||||
classname);
|
||||
}
|
||||
if (!Modifier.isPublic(mod)) {
|
||||
ostream.println(getLocalizedMessage("java.launcher.cls.error2",
|
||||
"public", classname));
|
||||
throw new RuntimeException("Main method is not public in class " +
|
||||
classname);
|
||||
}
|
||||
Class<?> rType = method.getReturnType();
|
||||
if (!rType.isPrimitive() || !rType.getName().equals("void")) {
|
||||
ostream.println(getLocalizedMessage("java.launcher.cls.error3",
|
||||
classname));
|
||||
throw new RuntimeException("Main method must return a value" +
|
||||
" of type void in class " +
|
||||
classname);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright 2007 Sun Microsystems, Inc. All Rights Reserved.
|
||||
# Copyright 2007-2008 Sun Microsystems, Inc. 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
|
||||
@ -99,3 +99,18 @@ java.launcher.X.usage=\
|
||||
\ -Xshare:auto use shared class data if possible (default)\n\
|
||||
\ -Xshare:on require using shared class data, otherwise fail.\n\n\
|
||||
The -X options are non-standard and subject to change without notice.\n
|
||||
|
||||
java.launcher.cls.error1=\
|
||||
Error: Could not find main class {0}
|
||||
java.launcher.cls.error2=\
|
||||
Error: Main method is not {0} in class {1}, please define the main method as:\n\
|
||||
\ public static void main(String[] args)
|
||||
java.launcher.cls.error3=\
|
||||
Error: Main method must return a value of type void in class {0}, please \n\
|
||||
define the main method as:\n\
|
||||
\ public static void main(String[] args)
|
||||
java.launcher.cls.error4=\
|
||||
Error: Main method not found in class {0}, please define the main method as:\n\
|
||||
\ public static void main(String[] args)
|
||||
|
||||
|
||||
|
@ -1312,3 +1312,24 @@ InitLauncher(jboolean javaw)
|
||||
{
|
||||
JLI_SetTraceLauncher();
|
||||
}
|
||||
|
||||
/*
|
||||
* The implementation for finding classes from the bootstrap
|
||||
* class loader, refer to java.h
|
||||
*/
|
||||
static FindClassFromBootLoader_t *findBootClass = NULL;
|
||||
|
||||
jclass
|
||||
FindBootStrapClass(JNIEnv *env, const char* classname)
|
||||
{
|
||||
if (findBootClass == NULL) {
|
||||
findBootClass = (FindClassFromBootLoader_t *)dlsym(RTLD_DEFAULT,
|
||||
"JVM_FindClassFromBootLoader");
|
||||
if (findBootClass == NULL) {
|
||||
JLI_ReportErrorMessage(DLL_ERROR4,
|
||||
"JVM_FindClassFromBootLoader");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
return findBootClass(env, classname, JNI_FALSE);
|
||||
}
|
||||
|
@ -993,9 +993,34 @@ ContinueInNewThread0(int (JNICALL *continuation)(void *), jlong stack_size, void
|
||||
return rslt;
|
||||
}
|
||||
|
||||
/* Linux only, empty on windows. */
|
||||
/* Unix only, empty on windows. */
|
||||
void SetJavaLauncherPlatformProps() {}
|
||||
|
||||
/*
|
||||
* The implementation for finding classes from the bootstrap
|
||||
* class loader, refer to java.h
|
||||
*/
|
||||
static FindClassFromBootLoader_t *findBootClass = NULL;
|
||||
|
||||
jclass FindBootStrapClass(JNIEnv *env, const char *classname)
|
||||
{
|
||||
HMODULE hJvm;
|
||||
|
||||
if (findBootClass == NULL) {
|
||||
hJvm = GetModuleHandle(JVM_DLL);
|
||||
if (hJvm == NULL) return NULL;
|
||||
/* need to use the demangled entry point */
|
||||
findBootClass = (FindClassFromBootLoader_t *)GetProcAddress(hJvm,
|
||||
"JVM_FindClassFromBootLoader");
|
||||
if (findBootClass == NULL) {
|
||||
JLI_ReportErrorMessage(DLL_ERROR4,
|
||||
"JVM_FindClassBootLoader");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
return findBootClass(env, classname, JNI_FALSE);
|
||||
}
|
||||
|
||||
void
|
||||
InitLauncher(boolean javaw)
|
||||
{
|
||||
|
@ -21,57 +21,47 @@
|
||||
* have any questions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @compile -XDignore.symbol.file Arrrghs.java TestHelper.java
|
||||
* @bug 5030233 6214916 6356475 6571029 6684582
|
||||
* @run main Arrrghs
|
||||
* @summary Argument parsing validation.
|
||||
*/
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
public class Arrrghs {
|
||||
|
||||
private Arrrghs(){}
|
||||
/**
|
||||
* This class provides various tests for arguments processing.
|
||||
* A group of tests to ensure that arguments are passed correctly to
|
||||
* a child java process upon a re-exec, this typically happens when
|
||||
* a version other than the one being executed is requested by the user.
|
||||
*
|
||||
* History: these set of tests were part of Arrrghs.sh. The MKS shell
|
||||
* implementations are notoriously buggy. Implementing these tests purely
|
||||
* implementations were notoriously buggy. Implementing these tests purely
|
||||
* in Java is not only portable but also robust.
|
||||
*
|
||||
*/
|
||||
|
||||
/* Do not instantiate */
|
||||
private Arrrghs() {}
|
||||
|
||||
static String javaCmd;
|
||||
|
||||
// The version string to force a re-exec
|
||||
final static String VersionStr = "-version:1.1+";
|
||||
|
||||
// The Cookie or the pattern we match in the debug output.
|
||||
final static String Cookie = "ReExec Args: ";
|
||||
|
||||
private static boolean _debug = Boolean.getBoolean("Arrrghs.Debug");
|
||||
private static boolean isWindows = System.getProperty("os.name", "unknown").startsWith("Windows");
|
||||
private static int exitValue = 0;
|
||||
|
||||
private static void doUsage(String message) {
|
||||
if (message != null) System.out.println("Error: " + message);
|
||||
System.out.println("Usage: Arrrghs path_to_java");
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
/*
|
||||
* SIGH, On Windows all strings are quoted, we need to unwrap it
|
||||
*/
|
||||
private static String removeExtraQuotes(String in) {
|
||||
if (isWindows) {
|
||||
if (TestHelper.isWindows) {
|
||||
// Trim the string and remove the enclosed quotes if any.
|
||||
in = in.trim();
|
||||
if (in.startsWith("\"") && in.endsWith("\"")) {
|
||||
@ -81,27 +71,29 @@ public class Arrrghs {
|
||||
return in;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* This method detects the cookie in the output stream of the process.
|
||||
*/
|
||||
private static boolean detectCookie(InputStream istream, String expectedArguments) throws IOException {
|
||||
private static boolean detectCookie(InputStream istream,
|
||||
String expectedArguments) throws IOException {
|
||||
BufferedReader rd = new BufferedReader(new InputStreamReader(istream));
|
||||
boolean retval = false;
|
||||
|
||||
String in = rd.readLine();
|
||||
while (in != null) {
|
||||
if (_debug) System.out.println(in);
|
||||
if (TestHelper.debug) System.out.println(in);
|
||||
if (in.startsWith(Cookie)) {
|
||||
String detectedArgument = removeExtraQuotes(in.substring(Cookie.length()));
|
||||
if (expectedArguments.equals(detectedArgument)) {
|
||||
retval = true;
|
||||
} else {
|
||||
System.out.println("Error: Expected Arguments\t:'" + expectedArguments + "'");
|
||||
System.out.println(" Detected Arguments\t:'" + detectedArgument + "'");
|
||||
System.out.println("Error: Expected Arguments\t:'" +
|
||||
expectedArguments + "'");
|
||||
System.out.println(" Detected Arguments\t:'" +
|
||||
detectedArgument + "'");
|
||||
}
|
||||
// Return the value asap if not in debug mode.
|
||||
if (!_debug) {
|
||||
if (!TestHelper.debug) {
|
||||
rd.close();
|
||||
istream.close();
|
||||
return retval;
|
||||
@ -112,7 +104,7 @@ public class Arrrghs {
|
||||
return retval;
|
||||
}
|
||||
|
||||
private static boolean doExec0(ProcessBuilder pb, String expectedArguments) {
|
||||
private static boolean doTest0(ProcessBuilder pb, String expectedArguments) {
|
||||
boolean retval = false;
|
||||
try {
|
||||
pb.redirectErrorStream(true);
|
||||
@ -131,72 +123,199 @@ public class Arrrghs {
|
||||
* This method return true if the expected and detected arguments are the same.
|
||||
* Quoting could cause dissimilar testArguments and expected arguments.
|
||||
*/
|
||||
static boolean doExec(String testArguments, String expectedPattern) {
|
||||
ProcessBuilder pb = new ProcessBuilder(javaCmd, VersionStr, testArguments);
|
||||
static int doTest(String testArguments, String expectedPattern) {
|
||||
ProcessBuilder pb = new ProcessBuilder(TestHelper.javaCmd,
|
||||
VersionStr, testArguments);
|
||||
|
||||
Map<String, String> env = pb.environment();
|
||||
env.put("_JAVA_LAUNCHER_DEBUG", "true");
|
||||
return doExec0(pb, testArguments);
|
||||
return doTest0(pb, testArguments) ? 0 : 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* A convenience method for identical test pattern and expected arguments
|
||||
*/
|
||||
static boolean doExec(String testPattern) {
|
||||
return doExec(testPattern, testPattern);
|
||||
static int doTest(String testPattern) {
|
||||
return doTest(testPattern, testPattern);
|
||||
}
|
||||
|
||||
static void quoteParsingTests() {
|
||||
/*
|
||||
* Tests for 6214916
|
||||
* These tests require that a JVM (any JVM) be installed in the system registry.
|
||||
* If none is installed, skip this test.
|
||||
*/
|
||||
TestHelper.TestResult tr =
|
||||
TestHelper.doExec(TestHelper.javaCmd, VersionStr, "-version");
|
||||
if (!tr.isOK()) {
|
||||
System.err.println("Warning:Argument Passing Tests were skipped, " +
|
||||
"no java found in system registry.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Basic test
|
||||
TestHelper.testExitValue += doTest("-a -b -c -d");
|
||||
|
||||
// Basic test with many spaces
|
||||
TestHelper.testExitValue += doTest("-a -b -c -d");
|
||||
|
||||
// Quoted whitespace does matter ?
|
||||
TestHelper.testExitValue += doTest("-a \"\"-b -c\"\" -d");
|
||||
|
||||
|
||||
// Escaped quotes outside of quotes as literals
|
||||
TestHelper.testExitValue += doTest("-a \\\"-b -c\\\" -d");
|
||||
|
||||
// Check for escaped quotes inside of quotes as literal
|
||||
TestHelper.testExitValue += doTest("-a \"-b \\\"stuff\\\"\" -c -d");
|
||||
|
||||
// A quote preceeded by an odd number of slashes is a literal quote
|
||||
TestHelper.testExitValue += doTest("-a -b\\\\\\\" -c -d");
|
||||
|
||||
// A quote preceeded by an even number of slashes is a literal quote
|
||||
// see 6214916.
|
||||
TestHelper.testExitValue += doTest("-a -b\\\\\\\\\" -c -d");
|
||||
|
||||
// Make sure that whitespace doesn't interfere with the removal of the
|
||||
// appropriate tokens. (space-tab-space preceeds -jre-restict-search).
|
||||
TestHelper.testExitValue += doTest("-a -b \t -jre-restrict-search -c -d","-a -b -c -d");
|
||||
|
||||
// Make sure that the mJRE tokens being stripped, aren't stripped if
|
||||
// they happen to appear as arguments to the main class.
|
||||
TestHelper.testExitValue += doTest("foo -version:1.1+");
|
||||
|
||||
System.out.println("Completed arguments quoting tests with " +
|
||||
TestHelper.testExitValue + " errors");
|
||||
}
|
||||
|
||||
/*
|
||||
* These tests are usually run on non-existent targets to check error results
|
||||
*/
|
||||
static void runBasicErrorMessageTests() {
|
||||
// Tests for 5030233
|
||||
TestHelper.TestResult tr = TestHelper.doExec(TestHelper.javaCmd, "-cp");
|
||||
tr.checkNegative();
|
||||
tr.isNotZeroOutput();
|
||||
System.out.println(tr);
|
||||
|
||||
tr = TestHelper.doExec(TestHelper.javaCmd, "-classpath");
|
||||
tr.checkNegative();
|
||||
tr.isNotZeroOutput();
|
||||
System.out.println(tr);
|
||||
|
||||
tr = TestHelper.doExec(TestHelper.javaCmd, "-jar");
|
||||
tr.checkNegative();
|
||||
tr.isNotZeroOutput();
|
||||
System.out.println(tr);
|
||||
|
||||
tr = TestHelper.doExec(TestHelper.javacCmd, "-cp");
|
||||
tr.checkNegative();
|
||||
tr.isNotZeroOutput();
|
||||
System.out.println(tr);
|
||||
|
||||
// Test for 6356475 "REGRESSION:"java -X" from cmdline fails"
|
||||
tr = TestHelper.doExec(TestHelper.javaCmd, "-X");
|
||||
tr.checkPositive();
|
||||
tr.isNotZeroOutput();
|
||||
System.out.println(tr);
|
||||
|
||||
tr = TestHelper.doExec(TestHelper.javaCmd, "-help");
|
||||
tr.checkPositive();
|
||||
tr.isNotZeroOutput();
|
||||
System.out.println(tr);
|
||||
}
|
||||
|
||||
/*
|
||||
* A set of tests which tests various dispositions of the main method.
|
||||
*/
|
||||
static void runMainMethodTests() throws FileNotFoundException {
|
||||
TestHelper.TestResult tr = null;
|
||||
|
||||
// a missing class
|
||||
TestHelper.createJar(new File("some.jar"), new File("Foo"), (String[])null);
|
||||
tr = TestHelper.doExec(TestHelper.javaCmd, "-jar", "some.jar");
|
||||
tr.contains("MIA");
|
||||
System.out.println(tr);
|
||||
// use classpath to check
|
||||
tr = TestHelper.doExec(TestHelper.javaCmd, "-cp", "some.jar", "MIA");
|
||||
tr.contains("Error: Could not find main class MIA");
|
||||
System.out.println(tr);
|
||||
|
||||
// incorrect method access
|
||||
TestHelper.createJar(new File("some.jar"), new File("Foo"),
|
||||
"private static void main(String[] args){}");
|
||||
tr = TestHelper.doExec(TestHelper.javaCmd, "-jar", "some.jar");
|
||||
tr.contains("Error: Main method not found in class Foo");
|
||||
System.out.println(tr);
|
||||
// use classpath to check
|
||||
tr = TestHelper.doExec(TestHelper.javaCmd, "-cp", "some.jar", "Foo");
|
||||
tr.contains("Error: Main method not found in class Foo");
|
||||
System.out.println(tr);
|
||||
|
||||
// incorrect return type
|
||||
TestHelper.createJar(new File("some.jar"), new File("Foo"),
|
||||
"public static int main(String[] args){return 1;}");
|
||||
tr = TestHelper.doExec(TestHelper.javaCmd, "-jar", "some.jar");
|
||||
tr.contains("Error: Main method must return a value of type void in class Foo");
|
||||
System.out.println(tr);
|
||||
// use classpath to check
|
||||
tr = TestHelper.doExec(TestHelper.javaCmd, "-cp", "some.jar", "Foo");
|
||||
tr.contains("Error: Main method must return a value of type void in class Foo");
|
||||
System.out.println(tr);
|
||||
|
||||
// incorrect parameter type
|
||||
TestHelper.createJar(new File("some.jar"), new File("Foo"),
|
||||
"public static void main(Object[] args){}");
|
||||
tr = TestHelper.doExec(TestHelper.javaCmd, "-jar", "some.jar");
|
||||
tr.contains("Error: Main method not found in class Foo");
|
||||
System.out.println(tr);
|
||||
// use classpath to check
|
||||
tr = TestHelper.doExec(TestHelper.javaCmd, "-cp", "some.jar", "Foo");
|
||||
tr.contains("Error: Main method not found in class Foo");
|
||||
System.out.println(tr);
|
||||
|
||||
// incorrect method type - non-static
|
||||
TestHelper.createJar(new File("some.jar"), new File("Foo"),
|
||||
"public void main(Object[] args){}");
|
||||
tr = TestHelper.doExec(TestHelper.javaCmd, "-jar", "some.jar");
|
||||
tr.contains("Error: Main method not found in class Foo");
|
||||
System.out.println(tr);
|
||||
// use classpath to check
|
||||
tr = TestHelper.doExec(TestHelper.javaCmd, "-cp", "some.jar", "Foo");
|
||||
tr.contains("Error: Main method not found in class Foo");
|
||||
System.out.println(tr);
|
||||
|
||||
// amongst a potpourri of kindred main methods, is the right one chosen ?
|
||||
TestHelper.createJar(new File("some.jar"), new File("Foo"),
|
||||
"void main(Object[] args){}",
|
||||
"int main(Float[] args){return 1;}",
|
||||
"private void main() {}",
|
||||
"private static void main(int x) {}",
|
||||
"public int main(int argc, String[] argv) {return 1;}",
|
||||
"public static void main(String[] args) {System.out.println(\"THE_CHOSEN_ONE\");}");
|
||||
tr = TestHelper.doExec(TestHelper.javaCmd, "-jar", "some.jar");
|
||||
tr.contains("THE_CHOSEN_ONE");
|
||||
System.out.println(tr);
|
||||
// use classpath to check
|
||||
tr = TestHelper.doExec(TestHelper.javaCmd, "-cp", "some.jar", "Foo");
|
||||
tr.contains("THE_CHOSEN_ONE");
|
||||
System.out.println(tr);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param args the command line arguments
|
||||
* @throws java.io.FileNotFoundException
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
if (args.length < 1 && args[0] == null) {
|
||||
doUsage("Invalid number of arguments");
|
||||
public static void main(String[] args) throws FileNotFoundException {
|
||||
if (TestHelper.debug) System.out.println("Starting Arrrghs tests");
|
||||
quoteParsingTests();
|
||||
runBasicErrorMessageTests();
|
||||
runMainMethodTests();
|
||||
if (TestHelper.testExitValue > 0) {
|
||||
System.out.println("Total of " + TestHelper.testExitValue + " failed");
|
||||
System.exit(1);
|
||||
} else {
|
||||
System.out.println("All tests pass");
|
||||
}
|
||||
|
||||
javaCmd = args[0];
|
||||
|
||||
if (!new File(javaCmd).canExecute()) {
|
||||
if (isWindows && new File(javaCmd + ".exe").canExecute()) {
|
||||
javaCmd = javaCmd + ".exe";
|
||||
} else {
|
||||
doUsage("The java executable must exist");
|
||||
}
|
||||
}
|
||||
|
||||
if (_debug) System.out.println("Starting Arrrghs tests");
|
||||
// Basic test
|
||||
if (!doExec("-a -b -c -d")) exitValue++;
|
||||
|
||||
// Basic test with many spaces
|
||||
if (!doExec("-a -b -c -d")) exitValue++;
|
||||
|
||||
// Quoted whitespace does matter ?
|
||||
if (!doExec("-a \"\"-b -c\"\" -d")) exitValue++;
|
||||
|
||||
// Escaped quotes outside of quotes as literals
|
||||
if (!doExec("-a \\\"-b -c\\\" -d")) exitValue++;
|
||||
|
||||
// Check for escaped quotes inside of quotes as literal
|
||||
if (!doExec("-a \"-b \\\"stuff\\\"\" -c -d")) exitValue++;
|
||||
|
||||
// A quote preceeded by an odd number of slashes is a literal quote
|
||||
if (!doExec("-a -b\\\\\\\" -c -d")) exitValue++;
|
||||
|
||||
// A quote preceeded by an even number of slashes is a literal quote
|
||||
// see 6214916.
|
||||
if (!doExec("-a -b\\\\\\\\\" -c -d")) exitValue++;
|
||||
|
||||
// Make sure that whitespace doesn't interfere with the removal of the
|
||||
// appropriate tokens. (space-tab-space preceeds -jre-restict-search).
|
||||
if (!doExec("-a -b \t -jre-restrict-search -c -d","-a -b -c -d")) exitValue++;
|
||||
|
||||
// Make sure that the mJRE tokens being stripped, aren't stripped if
|
||||
// they happen to appear as arguments to the main class.
|
||||
if (!doExec("foo -version:1.1+")) exitValue++;
|
||||
|
||||
System.out.println("Completed Arrrghs arguments quoting/matching tests with " + exitValue + " errors");
|
||||
System.exit(exitValue);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,176 +0,0 @@
|
||||
#!/bin/sh
|
||||
# @test Arrrghs.sh
|
||||
# @bug 5030233 6214916 6356475 6571029 6684582
|
||||
# @build Arrrghs
|
||||
# @run shell Arrrghs.sh
|
||||
# @summary Argument parsing validation.
|
||||
# @author Joseph E. Kowalski
|
||||
|
||||
#
|
||||
# Copyright 2004-2008 Sun Microsystems, Inc. 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.
|
||||
#
|
||||
# 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
||||
# CA 95054 USA or visit www.sun.com if you need additional information or
|
||||
# have any questions.
|
||||
#
|
||||
|
||||
#
|
||||
# This test is intended to validate generic argument parsing and
|
||||
# handling.
|
||||
#
|
||||
# Oh yes, since the response to argument parsing errors is often
|
||||
# a visceral one, the name Arrrghs (pronounced "args") seems rather
|
||||
# appropriate.
|
||||
#
|
||||
|
||||
# Verify directory context variables are set
|
||||
if [ "${TESTJAVA}" = "" ]
|
||||
then
|
||||
echo "TESTJAVA not set. Test cannot execute. Failed."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "${TESTSRC}" = "" ]
|
||||
then
|
||||
echo "TESTSRC not set. Test cannot execute. Failed."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "${TESTCLASSES}" = "" ]
|
||||
then
|
||||
echo "TESTCLASSES not set. Test cannot execute. Failed."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
#
|
||||
# Shell routine to test for the proper handling of the cp/classpath
|
||||
# option is correct (see 5030233). This option is unique in that it
|
||||
# is the only option to the java command (and friends) which is
|
||||
# separated from its option argument by a space, rather than an
|
||||
# equals sign.
|
||||
#
|
||||
# Parameters:
|
||||
# $1 cmd utility name to be tested (java, javac, ...)
|
||||
# $2 option either the -cp or -classpath option to be
|
||||
# tested.
|
||||
#
|
||||
TestCP() {
|
||||
mess="`$TESTJAVA/bin/$1 $2 2>&1 1>/dev/null`"
|
||||
if [ $? -eq 0 ]; then
|
||||
echo "Invalid $1 $2 syntax accepted"
|
||||
exit 1
|
||||
fi
|
||||
if [ -z "$mess" ]; then
|
||||
echo "No Usage message from invalid $1 $2 syntax"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
#
|
||||
# Test for 6356475 "REGRESSION:"java -X" from cmdline fails"
|
||||
#
|
||||
TestXUsage() {
|
||||
$TESTJAVA/bin/java -X > /dev/null 2>&1
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "-X option failed"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
#
|
||||
# Test if java -help works
|
||||
#
|
||||
TestHelp() {
|
||||
$TESTJAVA/bin/java -help > /dev/null 2>&1
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "-help option failed"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
#
|
||||
# Test to ensure that a missing main class is indicated in the error message
|
||||
#
|
||||
TestMissingMainClass() {
|
||||
# First create a small jar file with no main
|
||||
printf "public class Foo {}\n" > Foo.java
|
||||
$TESTJAVA/bin/javac Foo.java
|
||||
if [ $? -ne 0 ]; then
|
||||
printf "Error: compilation of Foo.java failed\n"
|
||||
exit 1
|
||||
fi
|
||||
printf "Main-Class: Bar\n" > manifest
|
||||
$TESTJAVA/bin/jar -cvfm some.jar manifest Foo.class
|
||||
if [ ! -f some.jar ]; then
|
||||
printf "Error: did not find some.jar\n"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# test a non-existence main-class using -jar
|
||||
mess="`$TESTJAVA/bin/java -jar some.jar 2>&1 1>/dev/null`"
|
||||
echo $mess | grep 'Bar' 2>&1 > /dev/null
|
||||
if [ $? -ne 0 ]; then
|
||||
printf "Error: did not find main class missing message\n"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# test a non-existent main-class using classpath
|
||||
mess="`$TESTJAVA/bin/java -cp some.jar Bar 2>&1 1>/dev/null`"
|
||||
echo $mess | grep 'Bar' 2>&1 > /dev/null
|
||||
if [ $? -ne 0 ]; then
|
||||
printf "Error: did not find main class missing message\n"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# cleanup
|
||||
rm -f some.jar Foo.* manifest
|
||||
}
|
||||
|
||||
#
|
||||
# Main processing:
|
||||
#
|
||||
|
||||
#
|
||||
# Tests for 5030233
|
||||
#
|
||||
TestCP java -cp
|
||||
TestCP java -classpath
|
||||
TestCP java -jar
|
||||
TestCP javac -cp
|
||||
TestCP javac -classpath
|
||||
TestXUsage
|
||||
TestHelp
|
||||
TestMissingMainClass
|
||||
|
||||
#
|
||||
# Tests for 6214916
|
||||
#
|
||||
#
|
||||
# These tests require that a JVM (any JVM) be installed in the system registry.
|
||||
# If none is installed, skip this test.
|
||||
$TESTJAVA/bin/java -version:1.1+ -version >/dev/null 2>&1
|
||||
if [ $? -eq 0 ]; then
|
||||
$TESTJAVA/bin/java -classpath $TESTCLASSES Arrrghs $TESTJAVA/bin/java
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "Argument Passing Tests failed"
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
printf "Warning:Argument Passing Tests were skipped, no java found in system registry."
|
||||
fi
|
||||
exit 0
|
228
jdk/test/tools/launcher/TestHelper.java
Normal file
228
jdk/test/tools/launcher/TestHelper.java
Normal file
@ -0,0 +1,228 @@
|
||||
|
||||
/*
|
||||
* Copyright 2008 Sun Microsystems, Inc. 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.
|
||||
*
|
||||
* 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
||||
* CA 95054 USA or visit www.sun.com if you need additional information or
|
||||
* have any questions.
|
||||
*/
|
||||
|
||||
import javax.tools.ToolProvider;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.PrintStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import javax.tools.JavaCompiler;
|
||||
|
||||
/**
|
||||
* This class provides some common utilites for the launcher tests.
|
||||
*/
|
||||
public enum TestHelper {
|
||||
INSTANCE;
|
||||
static final String JAVAHOME = System.getProperty("java.home", ".");
|
||||
static final boolean isSDK = JAVAHOME.endsWith("jre");
|
||||
static final String javaCmd;
|
||||
static final String javacCmd;
|
||||
static final JavaCompiler compiler;
|
||||
|
||||
static final boolean debug = Boolean.getBoolean("Arrrghs.Debug");
|
||||
static final boolean isWindows =
|
||||
System.getProperty("os.name", "unknown").startsWith("Windows");
|
||||
static int testExitValue = 0;
|
||||
|
||||
static {
|
||||
compiler = ToolProvider.getSystemJavaCompiler();
|
||||
File binDir = (isSDK) ? new File((new File(JAVAHOME)).getParentFile(), "bin")
|
||||
: new File(JAVAHOME, "bin");
|
||||
File javaCmdFile = (isWindows)
|
||||
? new File(binDir, "java.exe")
|
||||
: new File(binDir, "java");
|
||||
javaCmd = javaCmdFile.getAbsolutePath();
|
||||
if (!javaCmdFile.canExecute()) {
|
||||
throw new RuntimeException("java <" + TestHelper.javaCmd + "> must exist");
|
||||
}
|
||||
|
||||
File javacCmdFile = (isWindows)
|
||||
? new File(binDir, "javac.exe")
|
||||
: new File(binDir, "javac");
|
||||
javacCmd = javacCmdFile.getAbsolutePath();
|
||||
if (!javacCmdFile.canExecute()) {
|
||||
throw new RuntimeException("java <" + javacCmd + "> must exist");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* A generic jar file creator which creates the java file, compiles it
|
||||
* and jar's it up for use.
|
||||
*/
|
||||
static void createJar(File jarName, File mainClass, String... mainDefs)
|
||||
throws FileNotFoundException {
|
||||
createJar(null, jarName, mainClass, mainDefs);
|
||||
}
|
||||
|
||||
/*
|
||||
* A method which takes manifest entry to specify a specific manifest
|
||||
* Main-Class name.
|
||||
*/
|
||||
static void createJar(String mEntry, File jarName, File mainClass, String... mainDefs)
|
||||
throws FileNotFoundException {
|
||||
if (jarName.exists()) {
|
||||
jarName.delete();
|
||||
}
|
||||
PrintStream ps = new PrintStream(new FileOutputStream(mainClass + ".java"));
|
||||
ps.println("public class Foo {");
|
||||
if (mainDefs != null) {
|
||||
for (String x : mainDefs) {
|
||||
ps.println(x);
|
||||
}
|
||||
}
|
||||
ps.println("}");
|
||||
ps.close();
|
||||
|
||||
String compileArgs[] = {
|
||||
mainClass + ".java"
|
||||
};
|
||||
if (compiler.run(null, null, null, compileArgs) != 0) {
|
||||
throw new RuntimeException("compilation failed " + mainClass + ".java");
|
||||
}
|
||||
|
||||
if (mEntry == null && mainDefs == null) {
|
||||
mEntry = "MIA";
|
||||
} else {
|
||||
mEntry = mainClass.getName();
|
||||
}
|
||||
String jarArgs[] = {
|
||||
(debug) ? "cvfe" : "cfe",
|
||||
jarName.getAbsolutePath(),
|
||||
mEntry,
|
||||
mainClass.getName() + ".class"
|
||||
};
|
||||
sun.tools.jar.Main jarTool =
|
||||
new sun.tools.jar.Main(System.out, System.err, "JarCreator");
|
||||
if (!jarTool.run(jarArgs)) {
|
||||
throw new RuntimeException("jar creation failed " + jarName);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* A method which executes a java cmd and returs the results in a container
|
||||
*/
|
||||
static TestResult doExec(String...cmds) {
|
||||
String cmdStr = "";
|
||||
for (String x : cmds) {
|
||||
cmdStr = cmdStr.concat(x + " ");
|
||||
}
|
||||
ProcessBuilder pb = new ProcessBuilder(cmds);
|
||||
Map<String, String> env = pb.environment();
|
||||
BufferedReader rdr = null;
|
||||
try {
|
||||
List<String> outputList = new ArrayList<String>();
|
||||
pb.redirectErrorStream(true);
|
||||
Process p = pb.start();
|
||||
rdr = new BufferedReader(new InputStreamReader(p.getInputStream()));
|
||||
String in = rdr.readLine();
|
||||
while (in != null) {
|
||||
outputList.add(in);
|
||||
in = rdr.readLine();
|
||||
}
|
||||
p.waitFor();
|
||||
p.destroy();
|
||||
return new TestHelper.TestResult(cmdStr, p.exitValue(), outputList);
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
throw new RuntimeException(ex.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* A class to encapsulate the test results and stuff, with some ease
|
||||
* of use methods to check the test results.
|
||||
*/
|
||||
static class TestResult {
|
||||
StringBuilder status;
|
||||
int exitValue;
|
||||
List<String> testOutput;
|
||||
|
||||
public TestResult(String str, int rv, List<String> oList) {
|
||||
status = new StringBuilder(str);
|
||||
exitValue = rv;
|
||||
testOutput = oList;
|
||||
}
|
||||
|
||||
void checkNegative() {
|
||||
if (exitValue == 0) {
|
||||
status = status.append(" Error: test must not return 0 exit value");
|
||||
testExitValue++;
|
||||
}
|
||||
}
|
||||
|
||||
void checkPositive() {
|
||||
if (exitValue != 0) {
|
||||
status = status.append(" Error: test did not return 0 exit value");
|
||||
testExitValue++;
|
||||
}
|
||||
}
|
||||
|
||||
boolean isOK() {
|
||||
return exitValue == 0;
|
||||
}
|
||||
|
||||
boolean isZeroOutput() {
|
||||
if (!testOutput.isEmpty()) {
|
||||
status = status.append(" Error: No message from cmd please");
|
||||
testExitValue++;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
boolean isNotZeroOutput() {
|
||||
if (testOutput.isEmpty()) {
|
||||
status = status.append(" Error: Missing message");
|
||||
testExitValue++;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
if (debug) {
|
||||
for (String x : testOutput) {
|
||||
status = status.append(x + "\n");
|
||||
}
|
||||
}
|
||||
return status.toString();
|
||||
}
|
||||
|
||||
boolean contains(String str) {
|
||||
for (String x : testOutput) {
|
||||
if (x.contains(str)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
status = status.append(" Error: string <" + str + "> not found ");
|
||||
testExitValue++;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user