36 import java.lang.reflect.Constructor;
37 import java.lang.reflect.InvocationTargetException;
38 import java.lang.reflect.Method;
39 import java.net.MalformedURLException;
40 import java.net.URL;
41 import java.net.URLClassLoader;
42 import java.security.AccessController;
43 import java.security.PrivilegedAction;
44 import java.util.ArrayList;
45 import java.util.LinkedList;
46 import java.util.List;
47 import java.util.concurrent.CountDownLatch;
48 import java.util.concurrent.atomic.AtomicBoolean;
49 import java.util.concurrent.atomic.AtomicReference;
50 import java.util.jar.Attributes;
51 import java.util.jar.JarFile;
52 import java.util.jar.Manifest;
53 import java.util.Base64;
54 import com.sun.javafx.jmx.MXExtension;
55 import com.sun.javafx.runtime.SystemProperties;
56 import com.sun.javafx.util.ModuleHelper;
57
58 public class LauncherImpl {
59
60 /**
61 * Ensures that the module of the given class is readable to this
62 * module.
63 */
64 private static void ensureReadable(Class<?> targetClass) {
65 if (verbose) {
66 System.err.println("ensureReadable: " + targetClass);
67 }
68 Object thisModule = ModuleHelper.getModule(LauncherImpl.class);
69 Object targetModule = ModuleHelper.getModule(targetClass);
70 ModuleHelper.addReads(thisModule, targetModule);
71 }
72
73 /*
74 private void addExports(ClassLoader targetLoader) {
75 try {
76 Method getModuleMethod = Class.class.getMethod("getModule");
77 Object thisModule = getModuleMethod.invoke(this.getClass());
78 Method getUnnamedModuleMethod = ClassLoader.class.getMethod("getUnnamedModule");
79 Object targetModule = getUnnamedModuleMethod.invoke(targetLoader);
80
81 Class<?> moduleClass = getModuleMethod.getReturnType();
82 Method addExportsMethod = moduleClass.getMethod("addExports", String.class, moduleClass);
83 addExportsMethod.invoke(thisModule, "com.sun.tools.doclets.internal.toolkit.taglets", targetModule);
84 } catch (NoSuchMethodException e) {
85 // ignore
86 } catch (Exception e) {
87 throw new InternalError(e);
88 }
89 }
90 */
91
92 /**
93 * When passed as launchMode to launchApplication, tells the method that
94 * launchName is the name of the JavaFX application class to launch.
95 */
96 public static final String LAUNCH_MODE_CLASS = "LM_CLASS";
97
98 /**
99 * When passed as launchMode to launchApplication, tells the method that
100 * launchName is a path to a JavaFX application jar file to be launched.
101 */
102 public static final String LAUNCH_MODE_JAR = "LM_JAR";
103
104 // set to true to debug launch issues from Java launcher
105 private static final boolean trace = false;
106
107 // set system property javafx.verbose to true to make the launcher noisy
108 private static final boolean verbose;
109
110 private static final String MF_MAIN_CLASS = "Main-Class";
111 private static final String MF_JAVAFX_MAIN = "JavaFX-Application-Class";
112 private static final String MF_JAVAFX_PRELOADER = "JavaFX-Preloader-Class";
397 } catch (ClassNotFoundException cnfe) {
398 abort(cnfe, "Missing JavaFX preloader class %1$s", preloaderClassName);
399 }
400
401 if (!Preloader.class.isAssignableFrom(clz)) {
402 abort(null, "JavaFX preloader class %1$s does not extend javafx.application.Preloader", clz.getName());
403 }
404 preClassRef.set(clz.asSubclass(Preloader.class));
405 }
406 });
407 preClass = preClassRef.get();
408 tempAppClass = tmpClassRef.get();
409
410 // Save the preloader class in a static field for later use when
411 // main calls back into launchApplication.
412 savedPreloaderClass = preClass;
413
414 // If there is a public static void main(String[]) method then call it
415 // otherwise just hand off to the other launchApplication method
416
417 ensureReadable(tempAppClass);
418 Exception theEx = null;
419 try {
420 Method mainMethod = tempAppClass.getMethod("main",
421 new Class[] { (new String[0]).getClass() });
422 if (verbose) {
423 System.err.println("Calling main(String[]) method");
424 }
425 savedMainCcl = Thread.currentThread().getContextClassLoader();
426 mainMethod.invoke(null, new Object[] { args });
427 return;
428 } catch (NoSuchMethodException | IllegalAccessException ex) {
429 theEx = ex;
430 savedPreloaderClass = null;
431 if (verbose) {
432 System.err.println("WARNING: Cannot access application main method: " + ex);
433 }
434 } catch (InvocationTargetException ex) {
435 ex.printStackTrace();
436 abort(null, "Exception running application %1$s", tempAppClass.getName());
437 return;
548 || System.getProperty("ftp.proxyHost") != null
549 || System.getProperty("socksProxyHost") != null) {
550 if (verbose) {
551 System.out.println("Explicit proxy settings detected. Skip autoconfig.");
552 System.out.println(" http.proxyHost=" + System.getProperty("http.proxyHost"));
553 System.out.println(" https.proxyHost=" + System.getProperty("https.proxyHost"));
554 System.out.println(" ftp.proxyHost=" + System.getProperty("ftp.proxyHost"));
555 System.out.println(" socksProxyHost=" + System.getProperty("socksProxyHost"));
556 }
557 return;
558 }
559 if (System.getProperty("javafx.autoproxy.disable") != null) {
560 if (verbose) {
561 System.out.println("Disable autoproxy on request.");
562 }
563 return;
564 }
565
566 try {
567 Class sm = Class.forName("com.sun.deploy.services.ServiceManager");
568 ensureReadable(sm);
569 Class params[] = {Integer.TYPE};
570 Method setservice = sm.getDeclaredMethod("setService", params);
571 String osname = System.getProperty("os.name");
572
573 String servicename;
574 if (osname.startsWith("Win")) {
575 servicename = "STANDALONE_TIGER_WIN32";
576 } else if (osname.contains("Mac")) {
577 servicename = "STANDALONE_TIGER_MACOSX";
578 } else {
579 servicename = "STANDALONE_TIGER_UNIX";
580 }
581 Object values[] = new Object[1];
582 Class pt = Class.forName("com.sun.deploy.services.PlatformType");
583 values[0] = pt.getField(servicename).get(null);
584 setservice.invoke(null, values);
585
586 Class dps = Class.forName(
587 "com.sun.deploy.net.proxy.DeployProxySelector");
588 Method m = dps.getDeclaredMethod("reset", new Class[0]);
706 final Class<? extends Preloader> preloaderClass,
707 final String[] args) throws Exception {
708
709 startToolkit();
710
711 if (savedMainCcl != null) {
712 /*
713 * The toolkit was already started by the java launcher, and the
714 * main method of the application class was called. Check to see
715 * whether the CCL has been changed. If so, then we need
716 * to pass the context class loader to the FX app thread so that it
717 * correctly picks up the current setting.
718 */
719 final ClassLoader ccl = Thread.currentThread().getContextClassLoader();
720 if (ccl != null && ccl != savedMainCcl) {
721 PlatformImpl.runLater(() -> {
722 Thread.currentThread().setContextClassLoader(ccl);
723 });
724 }
725 }
726
727 if (preloaderClass != null) {
728 ensureReadable(preloaderClass);
729 }
730 ensureReadable(appClass);
731
732 final AtomicBoolean pStartCalled = new AtomicBoolean(false);
733 final AtomicBoolean startCalled = new AtomicBoolean(false);
734 final AtomicBoolean exitCalled = new AtomicBoolean(false);
735 final AtomicBoolean pExitCalled = new AtomicBoolean(false);
736 final CountDownLatch shutdownLatch = new CountDownLatch(1);
737 final CountDownLatch pShutdownLatch = new CountDownLatch(1);
738
739 final PlatformImpl.FinishListener listener = new PlatformImpl.FinishListener() {
740 @Override public void idle(boolean implicitExit) {
741 if (!implicitExit) {
742 return;
743 }
744
745 // System.err.println("JavaFX Launcher: system is idle");
746 if (startCalled.get()) {
747 shutdownLatch.countDown();
748 } else if (pStartCalled.get()) {
749 pShutdownLatch.countDown();
750 }
|
36 import java.lang.reflect.Constructor;
37 import java.lang.reflect.InvocationTargetException;
38 import java.lang.reflect.Method;
39 import java.net.MalformedURLException;
40 import java.net.URL;
41 import java.net.URLClassLoader;
42 import java.security.AccessController;
43 import java.security.PrivilegedAction;
44 import java.util.ArrayList;
45 import java.util.LinkedList;
46 import java.util.List;
47 import java.util.concurrent.CountDownLatch;
48 import java.util.concurrent.atomic.AtomicBoolean;
49 import java.util.concurrent.atomic.AtomicReference;
50 import java.util.jar.Attributes;
51 import java.util.jar.JarFile;
52 import java.util.jar.Manifest;
53 import java.util.Base64;
54 import com.sun.javafx.jmx.MXExtension;
55 import com.sun.javafx.runtime.SystemProperties;
56
57 public class LauncherImpl {
58
59 /**
60 * When passed as launchMode to launchApplication, tells the method that
61 * launchName is the name of the JavaFX application class to launch.
62 */
63 public static final String LAUNCH_MODE_CLASS = "LM_CLASS";
64
65 /**
66 * When passed as launchMode to launchApplication, tells the method that
67 * launchName is a path to a JavaFX application jar file to be launched.
68 */
69 public static final String LAUNCH_MODE_JAR = "LM_JAR";
70
71 // set to true to debug launch issues from Java launcher
72 private static final boolean trace = false;
73
74 // set system property javafx.verbose to true to make the launcher noisy
75 private static final boolean verbose;
76
77 private static final String MF_MAIN_CLASS = "Main-Class";
78 private static final String MF_JAVAFX_MAIN = "JavaFX-Application-Class";
79 private static final String MF_JAVAFX_PRELOADER = "JavaFX-Preloader-Class";
364 } catch (ClassNotFoundException cnfe) {
365 abort(cnfe, "Missing JavaFX preloader class %1$s", preloaderClassName);
366 }
367
368 if (!Preloader.class.isAssignableFrom(clz)) {
369 abort(null, "JavaFX preloader class %1$s does not extend javafx.application.Preloader", clz.getName());
370 }
371 preClassRef.set(clz.asSubclass(Preloader.class));
372 }
373 });
374 preClass = preClassRef.get();
375 tempAppClass = tmpClassRef.get();
376
377 // Save the preloader class in a static field for later use when
378 // main calls back into launchApplication.
379 savedPreloaderClass = preClass;
380
381 // If there is a public static void main(String[]) method then call it
382 // otherwise just hand off to the other launchApplication method
383
384 Exception theEx = null;
385 try {
386 Method mainMethod = tempAppClass.getMethod("main",
387 new Class[] { (new String[0]).getClass() });
388 if (verbose) {
389 System.err.println("Calling main(String[]) method");
390 }
391 savedMainCcl = Thread.currentThread().getContextClassLoader();
392 mainMethod.invoke(null, new Object[] { args });
393 return;
394 } catch (NoSuchMethodException | IllegalAccessException ex) {
395 theEx = ex;
396 savedPreloaderClass = null;
397 if (verbose) {
398 System.err.println("WARNING: Cannot access application main method: " + ex);
399 }
400 } catch (InvocationTargetException ex) {
401 ex.printStackTrace();
402 abort(null, "Exception running application %1$s", tempAppClass.getName());
403 return;
514 || System.getProperty("ftp.proxyHost") != null
515 || System.getProperty("socksProxyHost") != null) {
516 if (verbose) {
517 System.out.println("Explicit proxy settings detected. Skip autoconfig.");
518 System.out.println(" http.proxyHost=" + System.getProperty("http.proxyHost"));
519 System.out.println(" https.proxyHost=" + System.getProperty("https.proxyHost"));
520 System.out.println(" ftp.proxyHost=" + System.getProperty("ftp.proxyHost"));
521 System.out.println(" socksProxyHost=" + System.getProperty("socksProxyHost"));
522 }
523 return;
524 }
525 if (System.getProperty("javafx.autoproxy.disable") != null) {
526 if (verbose) {
527 System.out.println("Disable autoproxy on request.");
528 }
529 return;
530 }
531
532 try {
533 Class sm = Class.forName("com.sun.deploy.services.ServiceManager");
534 Class params[] = {Integer.TYPE};
535 Method setservice = sm.getDeclaredMethod("setService", params);
536 String osname = System.getProperty("os.name");
537
538 String servicename;
539 if (osname.startsWith("Win")) {
540 servicename = "STANDALONE_TIGER_WIN32";
541 } else if (osname.contains("Mac")) {
542 servicename = "STANDALONE_TIGER_MACOSX";
543 } else {
544 servicename = "STANDALONE_TIGER_UNIX";
545 }
546 Object values[] = new Object[1];
547 Class pt = Class.forName("com.sun.deploy.services.PlatformType");
548 values[0] = pt.getField(servicename).get(null);
549 setservice.invoke(null, values);
550
551 Class dps = Class.forName(
552 "com.sun.deploy.net.proxy.DeployProxySelector");
553 Method m = dps.getDeclaredMethod("reset", new Class[0]);
671 final Class<? extends Preloader> preloaderClass,
672 final String[] args) throws Exception {
673
674 startToolkit();
675
676 if (savedMainCcl != null) {
677 /*
678 * The toolkit was already started by the java launcher, and the
679 * main method of the application class was called. Check to see
680 * whether the CCL has been changed. If so, then we need
681 * to pass the context class loader to the FX app thread so that it
682 * correctly picks up the current setting.
683 */
684 final ClassLoader ccl = Thread.currentThread().getContextClassLoader();
685 if (ccl != null && ccl != savedMainCcl) {
686 PlatformImpl.runLater(() -> {
687 Thread.currentThread().setContextClassLoader(ccl);
688 });
689 }
690 }
691
692 final AtomicBoolean pStartCalled = new AtomicBoolean(false);
693 final AtomicBoolean startCalled = new AtomicBoolean(false);
694 final AtomicBoolean exitCalled = new AtomicBoolean(false);
695 final AtomicBoolean pExitCalled = new AtomicBoolean(false);
696 final CountDownLatch shutdownLatch = new CountDownLatch(1);
697 final CountDownLatch pShutdownLatch = new CountDownLatch(1);
698
699 final PlatformImpl.FinishListener listener = new PlatformImpl.FinishListener() {
700 @Override public void idle(boolean implicitExit) {
701 if (!implicitExit) {
702 return;
703 }
704
705 // System.err.println("JavaFX Launcher: system is idle");
706 if (startCalled.get()) {
707 shutdownLatch.countDown();
708 } else if (pStartCalled.get()) {
709 pShutdownLatch.countDown();
710 }
|