8001533: java launcher must launch javafx applications
Reviewed-by: ksrini, mchung, kcr, alanb
This commit is contained in:
parent
0bb98e7294
commit
5f0debc005
jdk
src/share
test/tools/launcher
@ -105,6 +105,7 @@ static jboolean InitializeJVM(JavaVM **pvm, JNIEnv **penv,
|
|||||||
InvocationFunctions *ifn);
|
InvocationFunctions *ifn);
|
||||||
static jstring NewPlatformString(JNIEnv *env, char *s);
|
static jstring NewPlatformString(JNIEnv *env, char *s);
|
||||||
static jclass LoadMainClass(JNIEnv *env, int mode, char *name);
|
static jclass LoadMainClass(JNIEnv *env, int mode, char *name);
|
||||||
|
static jclass GetApplicationClass(JNIEnv *env);
|
||||||
|
|
||||||
static void TranslateApplicationArgs(int jargc, const char **jargv, int *pargc, char ***pargv);
|
static void TranslateApplicationArgs(int jargc, const char **jargv, int *pargc, char ***pargv);
|
||||||
static jboolean AddApplicationOptions(int cpathc, const char **cpathv);
|
static jboolean AddApplicationOptions(int cpathc, const char **cpathv);
|
||||||
@ -346,6 +347,7 @@ JavaMain(void * _args)
|
|||||||
JavaVM *vm = 0;
|
JavaVM *vm = 0;
|
||||||
JNIEnv *env = 0;
|
JNIEnv *env = 0;
|
||||||
jclass mainClass = NULL;
|
jclass mainClass = NULL;
|
||||||
|
jclass appClass = NULL; // actual application class being launched
|
||||||
jmethodID mainID;
|
jmethodID mainID;
|
||||||
jobjectArray mainArgs;
|
jobjectArray mainArgs;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
@ -419,10 +421,28 @@ JavaMain(void * _args)
|
|||||||
* all environments,
|
* all environments,
|
||||||
* 2) Remove the vestages of maintaining main_class through
|
* 2) Remove the vestages of maintaining main_class through
|
||||||
* the environment (and remove these comments).
|
* the environment (and remove these comments).
|
||||||
|
*
|
||||||
|
* This method also correctly handles launching existing JavaFX
|
||||||
|
* applications that may or may not have a Main-Class manifest entry.
|
||||||
*/
|
*/
|
||||||
mainClass = LoadMainClass(env, mode, what);
|
mainClass = LoadMainClass(env, mode, what);
|
||||||
CHECK_EXCEPTION_NULL_LEAVE(mainClass);
|
CHECK_EXCEPTION_NULL_LEAVE(mainClass);
|
||||||
PostJVMInit(env, mainClass, vm);
|
/*
|
||||||
|
* In some cases when launching an application that needs a helper, e.g., a
|
||||||
|
* JavaFX application with no main method, the mainClass will not be the
|
||||||
|
* applications own main class but rather a helper class. To keep things
|
||||||
|
* consistent in the UI we need to track and report the application main class.
|
||||||
|
*/
|
||||||
|
appClass = GetApplicationClass(env);
|
||||||
|
NULL_CHECK(appClass);
|
||||||
|
/*
|
||||||
|
* PostJVMInit uses the class name as the application name for GUI purposes,
|
||||||
|
* for example, on OSX this sets the application name in the menu bar for
|
||||||
|
* both SWT and JavaFX. So we'll pass the actual application class here
|
||||||
|
* instead of mainClass as that may be a launcher or helper class instead
|
||||||
|
* of the application class.
|
||||||
|
*/
|
||||||
|
PostJVMInit(env, appClass, vm);
|
||||||
/*
|
/*
|
||||||
* The LoadMainClass not only loads the main class, it will also ensure
|
* The LoadMainClass not only loads the main class, it will also ensure
|
||||||
* that the main method's signature is correct, therefore further checking
|
* that the main method's signature is correct, therefore further checking
|
||||||
@ -1215,6 +1235,20 @@ LoadMainClass(JNIEnv *env, int mode, char *name)
|
|||||||
return (jclass)result;
|
return (jclass)result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static jclass
|
||||||
|
GetApplicationClass(JNIEnv *env)
|
||||||
|
{
|
||||||
|
jmethodID mid;
|
||||||
|
jobject result;
|
||||||
|
jclass cls = GetLauncherHelperClass(env);
|
||||||
|
NULL_CHECK0(cls);
|
||||||
|
NULL_CHECK0(mid = (*env)->GetStaticMethodID(env, cls,
|
||||||
|
"getApplicationClass",
|
||||||
|
"()Ljava/lang/Class;"));
|
||||||
|
|
||||||
|
return (*env)->CallStaticObjectMethod(env, cls, mid);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* For tools, convert command line args thus:
|
* For tools, convert command line args thus:
|
||||||
* javac -cp foo:foo/"*" -J-ms32m ...
|
* javac -cp foo:foo/"*" -J-ms32m ...
|
||||||
|
@ -69,7 +69,6 @@ import java.util.jar.Manifest;
|
|||||||
public enum LauncherHelper {
|
public enum LauncherHelper {
|
||||||
INSTANCE;
|
INSTANCE;
|
||||||
private static final String MAIN_CLASS = "Main-Class";
|
private static final String MAIN_CLASS = "Main-Class";
|
||||||
|
|
||||||
private static StringBuilder outBuf = new StringBuilder();
|
private static StringBuilder outBuf = new StringBuilder();
|
||||||
|
|
||||||
private static final String INDENT = " ";
|
private static final String INDENT = " ";
|
||||||
@ -87,6 +86,9 @@ public enum LauncherHelper {
|
|||||||
private static final ResourceBundle RB =
|
private static final ResourceBundle RB =
|
||||||
ResourceBundle.getBundle(defaultBundleName);
|
ResourceBundle.getBundle(defaultBundleName);
|
||||||
}
|
}
|
||||||
|
private static PrintStream ostream;
|
||||||
|
private static final ClassLoader scloader = ClassLoader.getSystemClassLoader();
|
||||||
|
private static Class<?> appClass; // application class, for GUI/reporting purposes
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* A method called by the launcher to print out the standard settings,
|
* A method called by the launcher to print out the standard settings,
|
||||||
@ -114,27 +116,27 @@ public enum LauncherHelper {
|
|||||||
long initialHeapSize, long maxHeapSize, long stackSize,
|
long initialHeapSize, long maxHeapSize, long stackSize,
|
||||||
boolean isServer) {
|
boolean isServer) {
|
||||||
|
|
||||||
PrintStream ostream = (printToStderr) ? System.err : System.out;
|
initOutput(printToStderr);
|
||||||
String opts[] = optionFlag.split(":");
|
String opts[] = optionFlag.split(":");
|
||||||
String optStr = (opts.length > 1 && opts[1] != null)
|
String optStr = (opts.length > 1 && opts[1] != null)
|
||||||
? opts[1].trim()
|
? opts[1].trim()
|
||||||
: "all";
|
: "all";
|
||||||
switch (optStr) {
|
switch (optStr) {
|
||||||
case "vm":
|
case "vm":
|
||||||
printVmSettings(ostream, initialHeapSize, maxHeapSize,
|
printVmSettings(initialHeapSize, maxHeapSize,
|
||||||
stackSize, isServer);
|
stackSize, isServer);
|
||||||
break;
|
break;
|
||||||
case "properties":
|
case "properties":
|
||||||
printProperties(ostream);
|
printProperties();
|
||||||
break;
|
break;
|
||||||
case "locale":
|
case "locale":
|
||||||
printLocale(ostream);
|
printLocale();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
printVmSettings(ostream, initialHeapSize, maxHeapSize,
|
printVmSettings(initialHeapSize, maxHeapSize, stackSize,
|
||||||
stackSize, isServer);
|
isServer);
|
||||||
printProperties(ostream);
|
printProperties();
|
||||||
printLocale(ostream);
|
printLocale();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -142,7 +144,7 @@ public enum LauncherHelper {
|
|||||||
/*
|
/*
|
||||||
* prints the main vm settings subopt/section
|
* prints the main vm settings subopt/section
|
||||||
*/
|
*/
|
||||||
private static void printVmSettings(PrintStream ostream,
|
private static void printVmSettings(
|
||||||
long initialHeapSize, long maxHeapSize,
|
long initialHeapSize, long maxHeapSize,
|
||||||
long stackSize, boolean isServer) {
|
long stackSize, boolean isServer) {
|
||||||
|
|
||||||
@ -172,14 +174,14 @@ public enum LauncherHelper {
|
|||||||
/*
|
/*
|
||||||
* prints the properties subopt/section
|
* prints the properties subopt/section
|
||||||
*/
|
*/
|
||||||
private static void printProperties(PrintStream ostream) {
|
private static void printProperties() {
|
||||||
Properties p = System.getProperties();
|
Properties p = System.getProperties();
|
||||||
ostream.println(PROP_SETTINGS);
|
ostream.println(PROP_SETTINGS);
|
||||||
List<String> sortedPropertyKeys = new ArrayList<>();
|
List<String> sortedPropertyKeys = new ArrayList<>();
|
||||||
sortedPropertyKeys.addAll(p.stringPropertyNames());
|
sortedPropertyKeys.addAll(p.stringPropertyNames());
|
||||||
Collections.sort(sortedPropertyKeys);
|
Collections.sort(sortedPropertyKeys);
|
||||||
for (String x : sortedPropertyKeys) {
|
for (String x : sortedPropertyKeys) {
|
||||||
printPropertyValue(ostream, x, p.getProperty(x));
|
printPropertyValue(x, p.getProperty(x));
|
||||||
}
|
}
|
||||||
ostream.println();
|
ostream.println();
|
||||||
}
|
}
|
||||||
@ -188,8 +190,7 @@ public enum LauncherHelper {
|
|||||||
return key.endsWith(".dirs") || key.endsWith(".path");
|
return key.endsWith(".dirs") || key.endsWith(".path");
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void printPropertyValue(PrintStream ostream,
|
private static void printPropertyValue(String key, String value) {
|
||||||
String key, String value) {
|
|
||||||
ostream.print(INDENT + key + " = ");
|
ostream.print(INDENT + key + " = ");
|
||||||
if (key.equals("line.separator")) {
|
if (key.equals("line.separator")) {
|
||||||
for (byte b : value.getBytes()) {
|
for (byte b : value.getBytes()) {
|
||||||
@ -229,7 +230,7 @@ public enum LauncherHelper {
|
|||||||
/*
|
/*
|
||||||
* prints the locale subopt/section
|
* prints the locale subopt/section
|
||||||
*/
|
*/
|
||||||
private static void printLocale(PrintStream ostream) {
|
private static void printLocale() {
|
||||||
Locale locale = Locale.getDefault();
|
Locale locale = Locale.getDefault();
|
||||||
ostream.println(LOCALE_SETTINGS);
|
ostream.println(LOCALE_SETTINGS);
|
||||||
ostream.println(INDENT + "default locale = " +
|
ostream.println(INDENT + "default locale = " +
|
||||||
@ -238,11 +239,11 @@ public enum LauncherHelper {
|
|||||||
Locale.getDefault(Category.DISPLAY).getDisplayName());
|
Locale.getDefault(Category.DISPLAY).getDisplayName());
|
||||||
ostream.println(INDENT + "default format locale = " +
|
ostream.println(INDENT + "default format locale = " +
|
||||||
Locale.getDefault(Category.FORMAT).getDisplayName());
|
Locale.getDefault(Category.FORMAT).getDisplayName());
|
||||||
printLocales(ostream);
|
printLocales();
|
||||||
ostream.println();
|
ostream.println();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void printLocales(PrintStream ostream) {
|
private static void printLocales() {
|
||||||
Locale[] tlocales = Locale.getAvailableLocales();
|
Locale[] tlocales = Locale.getAvailableLocales();
|
||||||
final int len = tlocales == null ? 0 : tlocales.length;
|
final int len = tlocales == null ? 0 : tlocales.length;
|
||||||
if (len < 1 ) {
|
if (len < 1 ) {
|
||||||
@ -370,7 +371,7 @@ public enum LauncherHelper {
|
|||||||
* initHelpSystem must be called before using this method.
|
* initHelpSystem must be called before using this method.
|
||||||
*/
|
*/
|
||||||
static void printHelpMessage(boolean printToStderr) {
|
static void printHelpMessage(boolean printToStderr) {
|
||||||
PrintStream ostream = (printToStderr) ? System.err : System.out;
|
initOutput(printToStderr);
|
||||||
outBuf = outBuf.append(getLocalizedMessage("java.launcher.opt.footer",
|
outBuf = outBuf.append(getLocalizedMessage("java.launcher.opt.footer",
|
||||||
File.pathSeparator));
|
File.pathSeparator));
|
||||||
ostream.println(outBuf.toString());
|
ostream.println(outBuf.toString());
|
||||||
@ -380,7 +381,7 @@ public enum LauncherHelper {
|
|||||||
* Prints the Xusage text to the desired output stream.
|
* Prints the Xusage text to the desired output stream.
|
||||||
*/
|
*/
|
||||||
static void printXUsageMessage(boolean printToStderr) {
|
static void printXUsageMessage(boolean printToStderr) {
|
||||||
PrintStream ostream = (printToStderr) ? System.err : System.out;
|
initOutput(printToStderr);
|
||||||
ostream.println(getLocalizedMessage("java.launcher.X.usage",
|
ostream.println(getLocalizedMessage("java.launcher.X.usage",
|
||||||
File.pathSeparator));
|
File.pathSeparator));
|
||||||
if (System.getProperty("os.name").contains("OS X")) {
|
if (System.getProperty("os.name").contains("OS X")) {
|
||||||
@ -389,36 +390,32 @@ public enum LauncherHelper {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static String getMainClassFromJar(PrintStream ostream, String jarname) {
|
static void initOutput(boolean printToStderr) {
|
||||||
try {
|
ostream = (printToStderr) ? System.err : System.out;
|
||||||
JarFile jarFile = null;
|
}
|
||||||
try {
|
|
||||||
jarFile = new JarFile(jarname);
|
static String getMainClassFromJar(String jarname) {
|
||||||
Manifest manifest = jarFile.getManifest();
|
String mainValue = null;
|
||||||
if (manifest == null) {
|
try (JarFile jarFile = new JarFile(jarname)) {
|
||||||
abort(ostream, null, "java.launcher.jar.error2", jarname);
|
Manifest manifest = jarFile.getManifest();
|
||||||
}
|
if (manifest == null) {
|
||||||
Attributes mainAttrs = manifest.getMainAttributes();
|
abort(null, "java.launcher.jar.error2", jarname);
|
||||||
if (mainAttrs == null) {
|
|
||||||
abort(ostream, null, "java.launcher.jar.error3", jarname);
|
|
||||||
}
|
|
||||||
String mainValue = mainAttrs.getValue(MAIN_CLASS);
|
|
||||||
if (mainValue == null) {
|
|
||||||
abort(ostream, null, "java.launcher.jar.error3", jarname);
|
|
||||||
}
|
|
||||||
return mainValue.trim();
|
|
||||||
} finally {
|
|
||||||
if (jarFile != null) {
|
|
||||||
jarFile.close();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
Attributes mainAttrs = manifest.getMainAttributes();
|
||||||
|
if (mainAttrs == null) {
|
||||||
|
abort(null, "java.launcher.jar.error3", jarname);
|
||||||
|
}
|
||||||
|
mainValue = mainAttrs.getValue(MAIN_CLASS);
|
||||||
|
if (mainValue == null) {
|
||||||
|
abort(null, "java.launcher.jar.error3", jarname);
|
||||||
|
}
|
||||||
|
return mainValue.trim();
|
||||||
} catch (IOException ioe) {
|
} catch (IOException ioe) {
|
||||||
abort(ostream, ioe, "java.launcher.jar.error1", jarname);
|
abort(ioe, "java.launcher.jar.error1", jarname);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// From src/share/bin/java.c:
|
// From src/share/bin/java.c:
|
||||||
// enum LaunchMode { LM_UNKNOWN = 0, LM_CLASS, LM_JAR };
|
// enum LaunchMode { LM_UNKNOWN = 0, LM_CLASS, LM_JAR };
|
||||||
|
|
||||||
@ -426,7 +423,7 @@ public enum LauncherHelper {
|
|||||||
private static final int LM_CLASS = 1;
|
private static final int LM_CLASS = 1;
|
||||||
private static final int LM_JAR = 2;
|
private static final int LM_JAR = 2;
|
||||||
|
|
||||||
static void abort(PrintStream ostream, Throwable t, String msgKey, Object... args) {
|
static void abort(Throwable t, String msgKey, Object... args) {
|
||||||
if (msgKey != null) {
|
if (msgKey != null) {
|
||||||
ostream.println(getLocalizedMessage(msgKey, args));
|
ostream.println(getLocalizedMessage(msgKey, args));
|
||||||
}
|
}
|
||||||
@ -450,19 +447,22 @@ public enum LauncherHelper {
|
|||||||
* b. is there a main
|
* b. is there a main
|
||||||
* c. is the main public
|
* c. is the main public
|
||||||
* d. is the main static
|
* d. is the main static
|
||||||
* c. does the main take a String array for args
|
* e. does the main take a String array for args
|
||||||
* 4. and off we go......
|
* 4. if no main method and if the class extends FX Application, then call
|
||||||
|
* on FXHelper to determine the main class to launch
|
||||||
|
* 5. and off we go......
|
||||||
*
|
*
|
||||||
* @param printToStderr
|
* @param printToStderr if set, all output will be routed to stderr
|
||||||
* @param isJar
|
* @param mode LaunchMode as determined by the arguments passed on the
|
||||||
* @param name
|
* command line
|
||||||
* @return
|
* @param what either the jar file to launch or the main class when using
|
||||||
|
* LM_CLASS mode
|
||||||
|
* @return the application's main class
|
||||||
*/
|
*/
|
||||||
public static Class<?> checkAndLoadMain(boolean printToStderr,
|
public static Class<?> checkAndLoadMain(boolean printToStderr,
|
||||||
int mode,
|
int mode,
|
||||||
String what) {
|
String what) {
|
||||||
final PrintStream ostream = (printToStderr) ? System.err : System.out;
|
initOutput(printToStderr);
|
||||||
final ClassLoader ld = ClassLoader.getSystemClassLoader();
|
|
||||||
// get the class name
|
// get the class name
|
||||||
String cn = null;
|
String cn = null;
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
@ -470,44 +470,75 @@ public enum LauncherHelper {
|
|||||||
cn = what;
|
cn = what;
|
||||||
break;
|
break;
|
||||||
case LM_JAR:
|
case LM_JAR:
|
||||||
cn = getMainClassFromJar(ostream, what);
|
cn = getMainClassFromJar(what);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
// should never happen
|
// should never happen
|
||||||
throw new InternalError("" + mode + ": Unknown launch mode");
|
throw new InternalError("" + mode + ": Unknown launch mode");
|
||||||
}
|
}
|
||||||
cn = cn.replace('/', '.');
|
cn = cn.replace('/', '.');
|
||||||
Class<?> c = null;
|
Class<?> mainClass = null;
|
||||||
try {
|
try {
|
||||||
c = ld.loadClass(cn);
|
mainClass = scloader.loadClass(cn);
|
||||||
} catch (ClassNotFoundException cnfe) {
|
} catch (NoClassDefFoundError | ClassNotFoundException cnfe) {
|
||||||
abort(ostream, cnfe, "java.launcher.cls.error1", cn);
|
abort(cnfe, "java.launcher.cls.error1", cn);
|
||||||
}
|
}
|
||||||
getMainMethod(ostream, c);
|
// set to mainClass, FXHelper may return something else
|
||||||
return c;
|
appClass = mainClass;
|
||||||
|
|
||||||
|
Method m = getMainMethod(mainClass);
|
||||||
|
if (m != null) {
|
||||||
|
// this will abort if main method has the wrong signature
|
||||||
|
validateMainMethod(m);
|
||||||
|
return mainClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if FXHelper can launch it using the FX launcher
|
||||||
|
Class<?> fxClass = FXHelper.getFXMainClass(mainClass);
|
||||||
|
if (fxClass != null) {
|
||||||
|
return fxClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
// not an FX application either, abort with an error
|
||||||
|
abort(null, "java.launcher.cls.error4", mainClass.getName(),
|
||||||
|
FXHelper.JAVAFX_APPLICATION_CLASS_NAME);
|
||||||
|
return null; // avoid compiler error...
|
||||||
}
|
}
|
||||||
|
|
||||||
static Method getMainMethod(PrintStream ostream, Class<?> clazz) {
|
/*
|
||||||
String classname = clazz.getName();
|
* Accessor method called by the launcher after getting the main class via
|
||||||
Method method = null;
|
* checkAndLoadMain(). The "application class" is the class that is finally
|
||||||
|
* executed to start the application and in this case is used to report
|
||||||
|
* the correct application name, typically for UI purposes.
|
||||||
|
*/
|
||||||
|
public static Class<?> getApplicationClass() {
|
||||||
|
return appClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for main method or return null if not found
|
||||||
|
static Method getMainMethod(Class<?> clazz) {
|
||||||
try {
|
try {
|
||||||
method = clazz.getMethod("main", String[].class);
|
return clazz.getMethod("main", String[].class);
|
||||||
} catch (NoSuchMethodException nsme) {
|
} catch (NoSuchMethodException nsme) {}
|
||||||
abort(ostream, null, "java.launcher.cls.error4", classname);
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check the signature of main and abort if it's incorrect
|
||||||
|
static void validateMainMethod(Method mainMethod) {
|
||||||
/*
|
/*
|
||||||
* getMethod (above) will choose the correct method, based
|
* getMethod (above) will choose the correct method, based
|
||||||
* on its name and parameter type, however, we still have to
|
* on its name and parameter type, however, we still have to
|
||||||
* ensure that the method is static and returns a void.
|
* ensure that the method is static and returns a void.
|
||||||
*/
|
*/
|
||||||
int mod = method.getModifiers();
|
int mod = mainMethod.getModifiers();
|
||||||
if (!Modifier.isStatic(mod)) {
|
if (!Modifier.isStatic(mod)) {
|
||||||
abort(ostream, null, "java.launcher.cls.error2", "static", classname);
|
abort(null, "java.launcher.cls.error2", "static",
|
||||||
|
mainMethod.getDeclaringClass().getName());
|
||||||
}
|
}
|
||||||
if (method.getReturnType() != java.lang.Void.TYPE) {
|
if (mainMethod.getReturnType() != java.lang.Void.TYPE) {
|
||||||
abort(ostream, null, "java.launcher.cls.error3", classname);
|
abort(null, "java.launcher.cls.error3",
|
||||||
|
mainMethod.getDeclaringClass().getName());
|
||||||
}
|
}
|
||||||
return method;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final String encprop = "sun.jnu.encoding";
|
private static final String encprop = "sun.jnu.encoding";
|
||||||
@ -519,7 +550,7 @@ public enum LauncherHelper {
|
|||||||
* previously implemented as a native method in the launcher.
|
* previously implemented as a native method in the launcher.
|
||||||
*/
|
*/
|
||||||
static String makePlatformString(boolean printToStderr, byte[] inArray) {
|
static String makePlatformString(boolean printToStderr, byte[] inArray) {
|
||||||
final PrintStream ostream = (printToStderr) ? System.err : System.out;
|
initOutput(printToStderr);
|
||||||
if (encoding == null) {
|
if (encoding == null) {
|
||||||
encoding = System.getProperty(encprop);
|
encoding = System.getProperty(encprop);
|
||||||
isCharsetSupported = Charset.isSupported(encoding);
|
isCharsetSupported = Charset.isSupported(encoding);
|
||||||
@ -530,7 +561,7 @@ public enum LauncherHelper {
|
|||||||
: new String(inArray);
|
: new String(inArray);
|
||||||
return out;
|
return out;
|
||||||
} catch (UnsupportedEncodingException uee) {
|
} catch (UnsupportedEncodingException uee) {
|
||||||
abort(ostream, uee, null);
|
abort(uee, null);
|
||||||
}
|
}
|
||||||
return null; // keep the compiler happy
|
return null; // keep the compiler happy
|
||||||
}
|
}
|
||||||
@ -611,5 +642,65 @@ public enum LauncherHelper {
|
|||||||
return "StdArg{" + "arg=" + arg + ", needsExpansion=" + needsExpansion + '}';
|
return "StdArg{" + "arg=" + arg + ", needsExpansion=" + needsExpansion + '}';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static final class FXHelper {
|
||||||
|
private static final String JAVAFX_APPLICATION_CLASS_NAME =
|
||||||
|
"javafx.application.Application";
|
||||||
|
private static final String JAVAFX_LAUNCHER_CLASS_NAME =
|
||||||
|
"com.sun.javafx.application.LauncherImpl";
|
||||||
|
|
||||||
|
/*
|
||||||
|
* FX application launcher and launch method, so we can launch
|
||||||
|
* applications with no main method.
|
||||||
|
*/
|
||||||
|
private static Class<?> fxLauncherClass = null;
|
||||||
|
private static Method fxLauncherMethod = null;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We can assume that the class does NOT have a main method or it would
|
||||||
|
* have been handled already. We do, however, need to check if the class
|
||||||
|
* extends Application and the launcher is available and abort with an
|
||||||
|
* error if it's not.
|
||||||
|
*/
|
||||||
|
private static Class<?> getFXMainClass(Class<?> mainClass) {
|
||||||
|
// Check if mainClass extends Application
|
||||||
|
if (!doesExtendFXApplication(mainClass)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for the FX launcher classes
|
||||||
|
try {
|
||||||
|
fxLauncherClass = scloader.loadClass(JAVAFX_LAUNCHER_CLASS_NAME);
|
||||||
|
fxLauncherMethod = fxLauncherClass.getMethod("launchApplication",
|
||||||
|
Class.class, String[].class);
|
||||||
|
} catch (ClassNotFoundException | NoSuchMethodException ex) {
|
||||||
|
abort(ex, "java.launcher.cls.error5", ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
// That's all, return this class so we can launch later
|
||||||
|
return FXHelper.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check if the given class is a JavaFX Application class. This is done
|
||||||
|
* in a way that does not cause the Application class to load or throw
|
||||||
|
* ClassNotFoundException if the JavaFX runtime is not available.
|
||||||
|
*/
|
||||||
|
private static boolean doesExtendFXApplication(Class<?> mainClass) {
|
||||||
|
for (Class<?> sc = mainClass.getSuperclass(); sc != null;
|
||||||
|
sc = sc.getSuperclass()) {
|
||||||
|
if (sc.getName().equals(JAVAFX_APPLICATION_CLASS_NAME)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// preloader ?
|
||||||
|
public static void main(String... args) throws Exception {
|
||||||
|
// launch appClass via fxLauncherMethod
|
||||||
|
fxLauncherMethod.invoke(null, new Object[] {appClass, args});
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -131,7 +131,10 @@ java.launcher.cls.error3=\
|
|||||||
\ public static void main(String[] args)
|
\ public static void main(String[] args)
|
||||||
java.launcher.cls.error4=\
|
java.launcher.cls.error4=\
|
||||||
Error: Main method not found in class {0}, please define the main method as:\n\
|
Error: Main method not found in class {0}, please define the main method as:\n\
|
||||||
\ public static void main(String[] args)
|
\ public static void main(String[] args)\n\
|
||||||
|
or a JavaFX application class must extend {1}
|
||||||
|
java.launcher.cls.error5=\
|
||||||
|
Error: JavaFX runtime components are missing, and are required to run this application
|
||||||
java.launcher.jar.error1=\
|
java.launcher.jar.error1=\
|
||||||
Error: An unexpected error occurred while trying to open file {0}
|
Error: An unexpected error occurred while trying to open file {0}
|
||||||
java.launcher.jar.error2=manifest not found in {0}
|
java.launcher.jar.error2=manifest not found in {0}
|
||||||
|
@ -559,6 +559,16 @@ public class TestHelper {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
boolean notContains(String str) {
|
||||||
|
for (String x : testOutput) {
|
||||||
|
if (x.contains(str)) {
|
||||||
|
appendError("string <" + str + "> found");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
boolean matches(String stringToMatch) {
|
boolean matches(String stringToMatch) {
|
||||||
for (String x : testOutput) {
|
for (String x : testOutput) {
|
||||||
if (x.matches(stringToMatch)) {
|
if (x.matches(stringToMatch)) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user