Index: /trunk/src/org/openstreetmap/josm/actions/downloadtasks/PostDownloadHandler.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/actions/downloadtasks/PostDownloadHandler.java	(revision 9904)
+++ /trunk/src/org/openstreetmap/josm/actions/downloadtasks/PostDownloadHandler.java	(revision 9905)
@@ -4,8 +4,8 @@
 import static org.openstreetmap.josm.tools.I18n.tr;
 
+import java.awt.GraphicsEnvironment;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.LinkedHashSet;
-import java.util.List;
 import java.util.Set;
 import java.util.concurrent.Future;
@@ -22,5 +22,5 @@
 public class PostDownloadHandler implements Runnable {
     private final DownloadTask task;
-    private final List<Future<?>> futures;
+    private final Future<?> future;
 
     /**
@@ -31,53 +31,21 @@
     public PostDownloadHandler(DownloadTask task, Future<?> future) {
         this.task = task;
-        this.futures = new ArrayList<>();
-        if (future != null) {
-            this.futures.add(future);
-        }
-    }
-
-    /**
-     * constructor
-     * @param task the asynchronous download task
-     * @param futures the futures on which the completion of the download task can be synchronized
-     */
-    public PostDownloadHandler(DownloadTask task, Future<?> ... futures) {
-        this.task = task;
-        this.futures = new ArrayList<>();
-        if (futures == null) return;
-        for (Future<?> future: futures) {
-            this.futures.add(future);
-        }
-    }
-
-    /**
-     * constructor
-     * @param task the asynchronous download task
-     * @param futures the futures on which the completion of the download task can be synchronized
-     */
-    public PostDownloadHandler(DownloadTask task, List<Future<?>> futures) {
-        this.task = task;
-        this.futures = new ArrayList<>();
-        if (futures == null) return;
-        this.futures.addAll(futures);
+        this.future = future;
     }
 
     @Override
     public void run() {
-        // wait for all downloads task to finish (by waiting for the futures to return a value)
+        // wait for downloads task to finish (by waiting for the future to return a value)
         //
-        for (Future<?> future: futures) {
-            try {
-                future.get();
-            } catch (Exception e) {
-                Main.error(e);
-                return;
-            }
+        try {
+            future.get();
+        } catch (Exception e) {
+            Main.error(e);
+            return;
         }
 
         // make sure errors are reported only once
         //
-        Set<Object> errors = new LinkedHashSet<>();
-        errors.addAll(task.getErrorObjects());
+        Set<Object> errors = new LinkedHashSet<>(task.getErrorObjects());
         if (errors.isEmpty())
             return;
@@ -87,20 +55,22 @@
         if (errors.size() == 1) {
             final Object error = errors.iterator().next();
-            SwingUtilities.invokeLater(new Runnable() {
-                @Override
-                public void run() {
-                    if (error instanceof Exception) {
-                        ExceptionDialogUtil.explainException((Exception) error);
-                    } else if (tr("No data found in this area.").equals(error)) {
-                        new Notification(error.toString()).setIcon(JOptionPane.WARNING_MESSAGE).show();
-                    } else {
-                        JOptionPane.showMessageDialog(
-                                Main.parent,
-                                error.toString(),
-                                tr("Error during download"),
-                                JOptionPane.ERROR_MESSAGE);
+            if (!GraphicsEnvironment.isHeadless()) {
+                SwingUtilities.invokeLater(new Runnable() {
+                    @Override
+                    public void run() {
+                        if (error instanceof Exception) {
+                            ExceptionDialogUtil.explainException((Exception) error);
+                        } else if (tr("No data found in this area.").equals(error)) {
+                            new Notification(error.toString()).setIcon(JOptionPane.WARNING_MESSAGE).show();
+                        } else {
+                            JOptionPane.showMessageDialog(
+                                    Main.parent,
+                                    error.toString(),
+                                    tr("Error during download"),
+                                    JOptionPane.ERROR_MESSAGE);
+                        }
                     }
-                }
-            });
+                });
+            }
             return;
         }
@@ -110,5 +80,5 @@
         if (!errors.isEmpty()) {
             final Collection<String> items = new ArrayList<>();
-            for (Object error:errors) {
+            for (Object error : errors) {
                 if (error instanceof String) {
                     items.add((String) error);
@@ -118,14 +88,16 @@
             }
 
-            SwingUtilities.invokeLater(new Runnable() {
-                @Override
-                public void run() {
-                    JOptionPane.showMessageDialog(
-                            Main.parent,
-                            "<html>"+Utils.joinAsHtmlUnorderedList(items)+"</html>",
-                            tr("Errors during download"),
-                            JOptionPane.ERROR_MESSAGE);
-                }
-            });
+            if (!GraphicsEnvironment.isHeadless()) {
+                SwingUtilities.invokeLater(new Runnable() {
+                    @Override
+                    public void run() {
+                        JOptionPane.showMessageDialog(
+                                Main.parent,
+                                "<html>"+Utils.joinAsHtmlUnorderedList(items)+"</html>",
+                                tr("Errors during download"),
+                                JOptionPane.ERROR_MESSAGE);
+                    }
+                });
+            }
             return;
         }
Index: /trunk/test/unit/org/openstreetmap/josm/actions/downloadtasks/DownloadNotesTaskTest.java
===================================================================
--- /trunk/test/unit/org/openstreetmap/josm/actions/downloadtasks/DownloadNotesTaskTest.java	(revision 9904)
+++ /trunk/test/unit/org/openstreetmap/josm/actions/downloadtasks/DownloadNotesTaskTest.java	(revision 9905)
@@ -25,5 +25,5 @@
     @BeforeClass
     public static void setUp() {
-        JOSMFixture.createUnitTestFixture().init();
+        JOSMFixture.createUnitTestFixture().init(true);
     }
 
Index: /trunk/test/unit/org/openstreetmap/josm/actions/downloadtasks/PostDownloadHandlerTest.java
===================================================================
--- /trunk/test/unit/org/openstreetmap/josm/actions/downloadtasks/PostDownloadHandlerTest.java	(revision 9905)
+++ /trunk/test/unit/org/openstreetmap/josm/actions/downloadtasks/PostDownloadHandlerTest.java	(revision 9905)
@@ -0,0 +1,157 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.actions.downloadtasks;
+
+import static org.junit.Assert.assertTrue;
+
+import java.net.URL;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.openstreetmap.josm.JOSMFixture;
+import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.data.Bounds;
+import org.openstreetmap.josm.gui.progress.ProgressMonitor;
+
+/**
+ * Unit tests for class {@link PostDownloadHandler}.
+ */
+public class PostDownloadHandlerTest {
+
+    /**
+     * Setup test.
+     */
+    @BeforeClass
+    public static void setUp() {
+        JOSMFixture.createUnitTestFixture().init();
+    }
+
+    private static DownloadTask newTask(final List<Object> errorObjects) {
+        return new DownloadTask() {
+            @Override
+            public Future<?> loadUrl(boolean newLayer, String url, ProgressMonitor progressMonitor) {
+                return null;
+            }
+
+            @Override
+            public String getTitle() {
+                return null;
+            }
+
+            @Override
+            public String[] getPatterns() {
+                return null;
+            }
+
+            @Override
+            public List<Object> getErrorObjects() {
+                return errorObjects;
+            }
+
+            @Override
+            public String getConfirmationMessage(URL url) {
+                return null;
+            }
+
+            @Override
+            public Future<?> download(boolean newLayer, Bounds downloadArea, ProgressMonitor progressMonitor) {
+                return null;
+            }
+
+            @Override
+            public void cancel() {
+            }
+
+            @Override
+            public boolean acceptsUrl(String url, boolean isRemotecontrol) {
+                return false;
+            }
+
+            @Override
+            public String acceptsDocumentationSummary() {
+                return null;
+            }
+        };
+    }
+
+    private static Future<Object> newFuture(final String exceptionName) {
+        return new Future<Object>() {
+            @Override
+            public boolean cancel(boolean mayInterruptIfRunning) {
+                return false;
+            }
+
+            @Override
+            public boolean isCancelled() {
+                return false;
+            }
+
+            @Override
+            public boolean isDone() {
+                return false;
+            }
+
+            @Override
+            public Object get() throws InterruptedException, ExecutionException {
+                if (exceptionName != null) {
+                    throw new ExecutionException(exceptionName, null);
+                }
+                return null;
+            }
+
+            @Override
+            public Object get(long timeout, TimeUnit unit)
+                    throws InterruptedException, ExecutionException, TimeoutException {
+                return null;
+            }
+        };
+    }
+
+    /**
+     * Unit test of {@code PostDownloadHandler#run} - error case: future throws exception.
+     */
+    @Test
+    public void testRunExceptionFuture() {
+        Main.clearLastErrorAndWarnings();
+        new PostDownloadHandler(null, newFuture("testRunExceptionFuture")).run();
+        assertTrue(Main.getLastErrorAndWarnings().toString(),
+                Main.getLastErrorAndWarnings().contains("E: java.util.concurrent.ExecutionException: testRunExceptionFuture"));
+    }
+
+    /**
+     * Unit test of {@code PostDownloadHandler#run} - nominal case: no errors.
+     */
+    @Test
+    public void testRunNoError() {
+        Main.clearLastErrorAndWarnings();
+        new PostDownloadHandler(newTask(Collections.emptyList()), newFuture(null)).run();
+        assertTrue(Main.getLastErrorAndWarnings().toString(), Main.getLastErrorAndWarnings().isEmpty());
+    }
+
+    /**
+     * Unit test of {@code PostDownloadHandler#run} - nominal case: only one error.
+     */
+    @Test
+    public void testRunOneError() {
+        Main.clearLastErrorAndWarnings();
+        new PostDownloadHandler(newTask(Collections.singletonList(new Object())), newFuture(null)).run();
+        assertTrue(Main.getLastErrorAndWarnings().toString(), Main.getLastErrorAndWarnings().isEmpty());
+    }
+
+    /**
+     * Unit test of {@code PostDownloadHandler#run} - nominal case: multiple errors.
+     */
+    @Test
+    public void testRunMultipleErrors() {
+        Main.clearLastErrorAndWarnings();
+        new PostDownloadHandler(newTask(Arrays.asList("foo", new Exception("bar"), new Object())), newFuture(null)).run();
+        assertTrue(Main.getLastErrorAndWarnings().toString(),
+                Main.getLastErrorAndWarnings().contains("E: java.lang.Exception: bar"));
+    }
+}
