001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.gui.progress.swing;
003
004import java.util.concurrent.CancellationException;
005import java.util.concurrent.ExecutionException;
006import java.util.concurrent.Future;
007import java.util.concurrent.LinkedBlockingQueue;
008import java.util.concurrent.ThreadPoolExecutor;
009import java.util.concurrent.TimeUnit;
010
011import org.openstreetmap.josm.tools.Logging;
012import org.openstreetmap.josm.tools.Utils;
013
014/**
015 * Executor that displays the progress monitor to the user.
016 *
017 * Similar to Executors.newSingleThreadExecutor(), but displays the
018 * progress monitor whenever a new task is executed.
019 * @since 12675 (moved from {@code gui.progress} package}
020 */
021public class ProgressMonitorExecutor extends ThreadPoolExecutor {
022
023    /**
024     * Creates a new {@code ProgressMonitorExecutor}
025     * @param nameFormat see {@link Utils#newThreadFactory(String, int)}
026     * @param threadPriority see {@link Utils#newThreadFactory(String, int)}
027     */
028    public ProgressMonitorExecutor(final String nameFormat, final int threadPriority) {
029        super(1, 1, 0L, TimeUnit.MILLISECONDS,
030                new LinkedBlockingQueue<Runnable>(),
031                Utils.newThreadFactory(nameFormat, threadPriority));
032    }
033
034    @Override
035    public void execute(Runnable command) {
036        if (PleaseWaitProgressMonitor.currentProgressMonitor != null) {
037            //TODO show only if this can't be in background or better if always in background is not checked
038            PleaseWaitProgressMonitor.currentProgressMonitor.showForegroundDialog();
039        }
040        super.execute(command);
041    }
042
043    @Override
044    public void afterExecute(final Runnable r, Throwable t) {
045        // largely as proposed by JDK8 docs
046        super.afterExecute(r, t);
047        if (t == null && r instanceof Future<?>) {
048            try {
049                ((Future<?>) r).get();
050            } catch (CancellationException cancellationException) {
051                t = cancellationException;
052            } catch (ExecutionException executionException) {
053                Logging.trace(executionException);
054                t = executionException.getCause();
055            } catch (InterruptedException interruptedException) {
056                Thread.currentThread().interrupt(); // ignore/reset
057            }
058        }
059        if (t != null) {
060            Logging.error("Thread {0} raised {1}", Thread.currentThread().getName(), t);
061        }
062    }
063}