diff -r 8ab8c2b2eee6 -r 364408faddeb jdk/src/share/classes/sun/launcher/LauncherHelper.java --- a/jdk/src/share/classes/sun/launcher/LauncherHelper.java Sat Jan 05 17:06:54 2013 +0000 +++ b/jdk/src/share/classes/sun/launcher/LauncherHelper.java Mon Jan 07 09:58:48 2013 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -409,6 +409,15 @@ if (mainValue == null) { abort(null, "java.launcher.jar.error3", jarname); } + /* + * Hand off to FXHelper if it detects a JavaFX application + * This must be done after ensuring a Main-Class entry + * exists to enforce compliance with the jar specification + */ + if (mainAttrs.containsKey( + new Attributes.Name(FXHelper.JAVAFX_APPLICATION_MARKER))) { + return FXHelper.class.getName(); + } return mainValue.trim(); } catch (IOException ioe) { abort(ioe, "java.launcher.jar.error1", jarname); @@ -483,26 +492,23 @@ } catch (NoClassDefFoundError | ClassNotFoundException cnfe) { abort(cnfe, "java.launcher.cls.error1", cn); } - // set to mainClass, FXHelper may return something else + // set to mainClass 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. In an FX app, + * the main class may or may not have a main method, so do this before + * validating the main class. + */ + if (mainClass.equals(FXHelper.class) || + FXHelper.doesExtendFXApplication(mainClass)) { + // Will abort() if there are problems with the FX runtime + FXHelper.setFXLaunchParameters(what, mode); + return FXHelper.class; } - // 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... + validateMainClass(mainClass); + return mainClass; } /* @@ -515,16 +521,18 @@ return appClass; } - // Check for main method or return null if not found - static Method getMainMethod(Class clazz) { + // Check the existence and signature of main and abort if incorrect + static void validateMainClass(Class mainClass) { + Method mainMethod; try { - return clazz.getMethod("main", String[].class); - } catch (NoSuchMethodException nsme) {} - return null; - } + mainMethod = mainClass.getMethod("main", String[].class); + } catch (NoSuchMethodException nsme) { + // invalid main or not FX application, abort with an error + abort(null, "java.launcher.cls.error4", mainClass.getName(), + FXHelper.JAVAFX_APPLICATION_CLASS_NAME); + return; // Avoid compiler issues + } - // Check the signature of main and abort if it's incorrect - static void validateMainMethod(Method mainMethod) { /* * getMethod (above) will choose the correct method, based * on its name and parameter type, however, we still have to @@ -644,41 +652,78 @@ } static final class FXHelper { + // Marker entry in jar manifest that designates a JavaFX application jar + private static final String JAVAFX_APPLICATION_MARKER = + "JavaFX-Application-Class"; private static final String JAVAFX_APPLICATION_CLASS_NAME = "javafx.application.Application"; private static final String JAVAFX_LAUNCHER_CLASS_NAME = "com.sun.javafx.application.LauncherImpl"; /* + * The launch method used to invoke the JavaFX launcher. These must + * match the strings used in the launchApplication method. + * + * Command line JavaFX-App-Class Launch mode FX Launch mode + * java -cp fxapp.jar FXClass N/A LM_CLASS "LM_CLASS" + * java -cp somedir FXClass N/A LM_CLASS "LM_CLASS" + * java -jar fxapp.jar Present LM_JAR "LM_JAR" + * java -jar fxapp.jar Not Present LM_JAR "LM_JAR" + */ + private static final String JAVAFX_LAUNCH_MODE_CLASS = "LM_CLASS"; + private static final String JAVAFX_LAUNCH_MODE_JAR = "LM_JAR"; + + /* * FX application launcher and launch method, so we can launch * applications with no main method. */ + private static String fxLaunchName = null; + private static String fxLaunchMode = null; + 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. + * Set the launch params according to what was passed to LauncherHelper + * so we can use the same launch mode for FX. Abort if there is any + * issue with loading the FX runtime or with the launcher method. */ - private static Class getFXMainClass(Class mainClass) { - // Check if mainClass extends Application - if (!doesExtendFXApplication(mainClass)) { - return null; - } - + private static void setFXLaunchParameters(String what, int mode) { // Check for the FX launcher classes try { fxLauncherClass = scloader.loadClass(JAVAFX_LAUNCHER_CLASS_NAME); + /* + * signature must be: + * public static void launchApplication(String launchName, + * String launchMode, String[] args); + */ fxLauncherMethod = fxLauncherClass.getMethod("launchApplication", - Class.class, String[].class); + String.class, String.class, String[].class); + + // verify launcher signature as we do when validating the main method + int mod = fxLauncherMethod.getModifiers(); + if (!Modifier.isStatic(mod)) { + abort(null, "java.launcher.javafx.error1"); + } + if (fxLauncherMethod.getReturnType() != java.lang.Void.TYPE) { + abort(null, "java.launcher.javafx.error1"); + } } 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; + fxLaunchName = what; + switch (mode) { + case LM_CLASS: + fxLaunchMode = JAVAFX_LAUNCH_MODE_CLASS; + break; + case LM_JAR: + fxLaunchMode = JAVAFX_LAUNCH_MODE_JAR; + break; + default: + // should not have gotten this far... + throw new InternalError(mode + ": Unknown launch mode"); + } } /* @@ -696,11 +741,15 @@ return false; } - // preloader ? public static void main(String... args) throws Exception { + if (fxLauncherMethod == null + || fxLaunchMode == null + || fxLaunchName == null) { + throw new RuntimeException("Invalid JavaFX launch parameters"); + } // launch appClass via fxLauncherMethod - fxLauncherMethod.invoke(null, new Object[] {appClass, args}); + fxLauncherMethod.invoke(null, + new Object[] {fxLaunchName, fxLaunchMode, args}); } } } -