diff -r e19639f572c4 netx/net/sourceforge/jnlp/controlpanel/CommandLine.java --- a/netx/net/sourceforge/jnlp/controlpanel/CommandLine.java Fri Oct 12 15:37:59 2018 +0200 +++ b/netx/net/sourceforge/jnlp/controlpanel/CommandLine.java Tue Oct 16 21:53:55 2018 +0200 @@ -37,6 +37,7 @@ import net.sourceforge.jnlp.util.docprovider.formatters.formatters.PlainTextFormatter; import net.sourceforge.jnlp.util.logging.OutputController; import net.sourceforge.jnlp.util.optionparser.OptionParser; +import net.sourceforge.swing.SwingUtils; /** * Encapsulates a command line interface to the deployment configuration. @@ -495,6 +496,9 @@ * @throws java.lang.Exception when it goes wrong */ public static void main(String[] args) throws Exception { + // setup Swing EDT tracing: + SwingUtils.setup(); + try { OptionParser optionParser = new OptionParser(args, OptionsDefinitions.getItwsettingsCommands()); if (optionParser.hasOption(OptionsDefinitions.OPTIONS.DETAILS) || optionParser.hasOption(OptionsDefinitions.OPTIONS.VERBOSE)){ diff -r e19639f572c4 netx/net/sourceforge/jnlp/runtime/Boot.java --- a/netx/net/sourceforge/jnlp/runtime/Boot.java Fri Oct 12 15:37:59 2018 +0200 +++ b/netx/net/sourceforge/jnlp/runtime/Boot.java Tue Oct 16 21:53:55 2018 +0200 @@ -96,6 +96,9 @@ * @param argsIn launching arguments */ public static void main(String[] argsIn) throws UnevenParameterException { + // setup Swing EDT tracing: + SwingUtils.setup(); + optionParser = new OptionParser(argsIn, OptionsDefinitions.getJavaWsOptions()); if (optionParser.hasOption(OptionsDefinitions.OPTIONS.VERBOSE)) { @@ -117,7 +120,7 @@ } catch (Exception e) { OutputController.getLogger().log(OutputController.Level.ERROR_ALL, e); } finally { - //no metter what happens, terminate + //no matter what happens, terminate return; } } diff -r e19639f572c4 netx/net/sourceforge/jnlp/security/policyeditor/PolicyEditor.java --- a/netx/net/sourceforge/jnlp/security/policyeditor/PolicyEditor.java Fri Oct 12 15:37:59 2018 +0200 +++ b/netx/net/sourceforge/jnlp/security/policyeditor/PolicyEditor.java Tue Oct 16 21:53:55 2018 +0200 @@ -120,6 +120,7 @@ import net.sourceforge.jnlp.util.docprovider.formatters.formatters.PlainTextFormatter; import net.sourceforge.jnlp.util.logging.OutputController; import net.sourceforge.jnlp.util.optionparser.OptionParser; +import net.sourceforge.swing.SwingUtils; import sun.security.provider.PolicyParser; /** @@ -1734,6 +1735,9 @@ * -help will print a help message and immediately return (no editor instance opens) */ public static void main(final String[] args) { + // setup Swing EDT tracing: + SwingUtils.setup(); + final OptionParser optionParser = new OptionParser(args, OptionsDefinitions.getPolicyEditorOptions()); if (optionParser.hasOption(OptionsDefinitions.OPTIONS.VERBOSE)) { diff -r e19639f572c4 netx/net/sourceforge/jnlp/util/ImageResources.java --- a/netx/net/sourceforge/jnlp/util/ImageResources.java Fri Oct 12 15:37:59 2018 +0200 +++ b/netx/net/sourceforge/jnlp/util/ImageResources.java Tue Oct 16 21:53:55 2018 +0200 @@ -77,14 +77,16 @@ } InputStream in = cl.getResourceAsStream(APPLICATION_ICON_PATH); - try { - Image image = ImageIO.read(in); - cache.put(APPLICATION_ICON_PATH, image); - return image; - } catch (IOException ioe) { - OutputController.getLogger().log(OutputController.Level.ERROR_ALL, ioe); - return null; + if (in != null) { + try { + Image image = ImageIO.read(in); + cache.put(APPLICATION_ICON_PATH, image); + return image; + } catch (IOException ioe) { + OutputController.getLogger().log(OutputController.Level.ERROR_ALL, ioe); + } } + return null; } /** diff -r e19639f572c4 netx/net/sourceforge/swing/SwingUtils.java --- a/netx/net/sourceforge/swing/SwingUtils.java Fri Oct 12 15:37:59 2018 +0200 +++ b/netx/net/sourceforge/swing/SwingUtils.java Tue Oct 16 21:53:55 2018 +0200 @@ -38,16 +38,8 @@ import java.awt.Window; import java.lang.reflect.InvocationTargetException; -import java.util.concurrent.Callable; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Future; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.ThreadFactory; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicInteger; import javax.swing.JWindow; +import javax.swing.RepaintManager; import javax.swing.SwingUtilities; import net.sourceforge.jnlp.runtime.Translator; import net.sourceforge.jnlp.util.logging.OutputController; @@ -57,18 +49,37 @@ */ public final class SwingUtils { + private static final boolean DEBUG_EDT = System.getProperty("icedtea-web.edt.debug", "false").equalsIgnoreCase("true"); + // debugging flags: private static final boolean INFO_DIALOG = false; private static final boolean TRACE_INVOKE_EDT = false; private static final boolean TRACE_TG = false; + // internals: + private static boolean DO_SETUP = true; + /** main thread group (initialized at startup) */ - static final ThreadGroup MAIN_GROUP = Thread.currentThread().getThreadGroup(); + private static final ThreadGroup MAIN_GROUP = Thread.currentThread().getThreadGroup(); + + /* shared Window owner */ + private static Window window = null; private SwingUtils() { // forbidden } + public static void setup() { + if (DO_SETUP) { + DO_SETUP = false; // avoid reentrance + + if (DEBUG_EDT) { + trace("Using ThreadCheckingRepaintManager"); + RepaintManager.setCurrentManager(new ThreadCheckingRepaintManager()); + } + } + } + static void trace(final String msg) { // Use System.err directly for debuging EDT without any conflict with console / logging system System.err.println(msg); @@ -93,72 +104,6 @@ } } - // --- SwingUtilities wrapper --- - public static boolean isEventDispatchThread() { - return SwingUtilities.isEventDispatchThread(); - } - - public static void invokeLater(final Runnable doRun) { - if (isMainThreadGroup()) { - if (isEventDispatchThread()) { - if (TRACE_INVOKE_EDT) { - traceWithStack("invokeLater() from EDT: MAY be fixed ?"); - } - } - SwingUtilities.invokeLater(doRun); - } else { - EDT_DAEMON_THREAD_POOL.submit(new Runnable() { - @Override - public void run() { - SwingUtilities.invokeLater(doRun); - } - }); - } - } - - public static void callOnAppContext(final Runnable doRun) throws InterruptedException, InvocationTargetException { - SwingUtilities.invokeAndWait(doRun); - } - - public static void invokeAndWait(final Runnable doRun) { - if (isMainThreadGroup()) { - if (isEventDispatchThread()) { - if (TRACE_INVOKE_EDT) { - traceWithStack("invokeAndWait() from EDT: MAY be fixed ?"); - } - doRun.run(); - } else { - try { - callOnAppContext(doRun); - } catch (InterruptedException ie) { - OutputController.getLogger().log(OutputController.Level.ERROR_ALL, ie); - } catch (InvocationTargetException ite) { - OutputController.getLogger().log(OutputController.Level.ERROR_ALL, ite); - } - } - } else { - final Future future = EDT_DAEMON_THREAD_POOL.submit(new Callable() { - @Override - public Void call() throws Exception { - callOnAppContext(doRun); - return null; - } - }); - try { - // Wait on Future: - future.get(); - } catch (InterruptedException ie) { - OutputController.getLogger().log(OutputController.Level.ERROR_ALL, ie); - } catch (ExecutionException ee) { - if (ee.getCause() != null) { - OutputController.getLogger().log(OutputController.Level.ERROR_ALL, ee.getCause()); - } else { - OutputController.getLogger().log(OutputController.Level.ERROR_ALL, ee); - } - } - } - } - private static boolean isMainThreadGroup() { final Thread t = Thread.currentThread(); final ThreadGroup g = t.getThreadGroup(); @@ -172,36 +117,42 @@ return true; } - private static final class MainAppContextDaemonThreadFactory implements ThreadFactory { + // --- SwingUtilities wrapper --- + public static boolean isEventDispatchThread() { + return SwingUtilities.isEventDispatchThread(); + } - private final AtomicInteger threadNumber = new AtomicInteger(1); - private final String namePrefix = "itw-edt-thread-"; + public static void invokeLater(final Runnable doRun) { + if (isMainThreadGroup()) { + if (TRACE_INVOKE_EDT && isEventDispatchThread()) { + traceWithStack("invokeLater() from EDT: MAY be fixed (useless) ?"); + } + } + SwingUtilities.invokeLater(doRun); + } - @Override - public Thread newThread(Runnable r) { - final Thread t = new Thread(MAIN_GROUP, r, - namePrefix + threadNumber.getAndIncrement() - ); - if (!t.isDaemon()) { - t.setDaemon(true); + public static void callOnAppContext(final Runnable doRun) throws InterruptedException, InvocationTargetException { + SwingUtilities.invokeAndWait(doRun); + } + + public static void invokeAndWait(final Runnable doRun) { + if (isEventDispatchThread()) { + if (TRACE_INVOKE_EDT) { + traceWithStack("invokeAndWait() from EDT: to be fixed (illegal) ?"); } - if (t.getPriority() != Thread.NORM_PRIORITY) { - t.setPriority(Thread.NORM_PRIORITY); + // Direct invocation: + doRun.run(); + } else { + try { + callOnAppContext(doRun); + } catch (InterruptedException ie) { + OutputController.getLogger().log(OutputController.Level.ERROR_ALL, ie); + } catch (InvocationTargetException ite) { + OutputController.getLogger().log(OutputController.Level.ERROR_ALL, ite); } - return t; } } - /** single thread pool with max 1 live daemon thread */ - private static final ExecutorService EDT_DAEMON_THREAD_POOL = new ThreadPoolExecutor(0, 1, - 60L, TimeUnit.SECONDS, - new LinkedBlockingQueue(), - new MainAppContextDaemonThreadFactory() - ); - - /* shared Window owner */ - private static Window window = null; - public static synchronized Window getOrCreateWindowOwner() { if (window == null) { invokeAndWait(new Runnable() {