Index: OsmApi.java
===================================================================
--- OsmApi.java	(revision 1580)
+++ OsmApi.java	(working copy)
@@ -22,6 +22,7 @@
 import java.util.Collection;
 import java.util.Properties;
 import java.util.StringTokenizer;
+import java.util.concurrent.FutureTask;
 
 import javax.xml.parsers.SAXParserFactory;
 
@@ -32,6 +33,7 @@
 import org.openstreetmap.josm.data.osm.Relation;
 import org.openstreetmap.josm.data.osm.Way;
 import org.openstreetmap.josm.data.osm.visitor.CreateOsmChangeVisitor;
+import org.openstreetmap.josm.gui.PleaseWaitRunnable;
 import org.xml.sax.Attributes;
 import org.xml.sax.InputSource;
 import org.xml.sax.SAXException;
@@ -285,41 +287,129 @@
     }
 
     /**
-     * Uploads a list of changes in "diff" form the the server. 
+     * Uploads a list of changes in "diff" form to he the server. 
+     *  
      * @param list the list of changed OSM Primitives
      * @return list of processed primitives
-     * @throws OsmTransferException if something is wrong.
+     * @throws OsmTransferException if something is wrong
+     * @throws OsmTransferCancelledException  if the upload was cancelled by the user 
      */
-    public Collection<OsmPrimitive> uploadDiff(Collection<OsmPrimitive> list) throws OsmTransferException {
+    public Collection<OsmPrimitive> uploadDiff(final Collection<OsmPrimitive> list) throws OsmTransferException {
     
         if (changeset == null) {
             throw new OsmTransferException(tr("No changeset present for diff upload"));
         }
         
-        CreateOsmChangeVisitor duv = new CreateOsmChangeVisitor(changeset, this);
         
-        ArrayList<OsmPrimitive> processed = new ArrayList<OsmPrimitive>();
-    
-        for (OsmPrimitive osm : list) {
-            int progress = Main.pleaseWaitDlg.progress.getValue();
-            Main.pleaseWaitDlg.currentAction.setText(tr("Preparing..."));
-            if (cancel) throw new OsmTransferCancelledException();
-            osm.visit(duv);
-            Main.pleaseWaitDlg.progress.setValue(progress+1);
+        final ArrayList<OsmPrimitive> processed = new ArrayList<OsmPrimitive>();
+        
+        // this is the asynchronous update task
+        //
+        class UploadDiffTask extends  PleaseWaitRunnable {
+            
+            private boolean uploadCancelled = false;
+            private boolean uploadFailed = false;
+            private Throwable lastThrowable = null;
+            
+            public UploadDiffTask(String title) {
+                super(title,false /* don't ignore exceptions */);
+            }
+            
+            @Override protected void realRun() throws SAXException, IOException {
+                CreateOsmChangeVisitor duv = new CreateOsmChangeVisitor(changeset, OsmApi.this);
+            
+                for (OsmPrimitive osm : list) {
+                    int progress = Main.pleaseWaitDlg.progress.getValue();
+                    Main.pleaseWaitDlg.currentAction.setText(tr("Preparing..."));
+                    osm.visit(duv);
+                    Main.pleaseWaitDlg.progress.setValue(progress+1);
+                }
+            
+                Main.pleaseWaitDlg.currentAction.setText(tr("Uploading..."));
+            
+                String diff = duv.getDocument();
+                try {
+                    String diffresult = sendRequest("POST", "changeset/" + changeset.id + "/upload", diff);  
+                    DiffResultReader.parseDiffResult(diffresult, list, processed, duv.getNewIdMap(), Main.pleaseWaitDlg);
+                } catch (Exception sxe) {
+                    if (isUploadCancelled()) {
+                        // ignore exceptions thrown because the connection is aborted,
+                        // i.e. IOExceptions or SocketExceptions
+                        //
+                        System.out.println("Ignoring exception caught because upload is cancelled. Exception is: " + sxe.toString());
+                        return;
+                    } 
+                    uploadFailed = true;
+                    // remember last exception and don't throw it. If it was thrown again it would
+                    // have to be encapsulated in a RuntimeException which would be nested in yet
+                    // another RuntimeException by parent classes.
+                    // Rather check isUploadFailed() and retrieve getLastThrowable() after the task 
+                    // is completed
+                    //
+                    lastThrowable = sxe;
+                }
+            }
+            
+            @Override protected void finish() {
+                // do nothing
+            }
+            
+            @Override protected void cancel() {
+                activeConnection.disconnect();
+                uploadCancelled = true; 
+            }
+            
+            public boolean isUploadCancelled() {
+                return uploadCancelled;
+            }
+            
+            public boolean isUploadFailed() {
+                return uploadFailed;
+            }
+            
+            public Throwable getLastThrowable() {
+                return lastThrowable;               
+            }
         }
-    
-        Main.pleaseWaitDlg.currentAction.setText(tr("Uploading..."));
-        if (cancel) throw new OsmTransferCancelledException();
-    
-        String diff = duv.getDocument();
-        String diffresult = sendRequest("POST", "changeset/" + changeset.id + "/upload", diff);  
-        try {
-            DiffResultReader.parseDiffResult(diffresult, list, processed, duv.getNewIdMap(), Main.pleaseWaitDlg);
-        } catch (Exception sxe) {
-            throw new OsmTransferException(tr("Error processing changeset upload response"), sxe);
+        
+        UploadDiffTask uploadTask = new UploadDiffTask(tr("Uploading data"));
+        
+        // run  data upload as asynchronous task 
+        //
+        try {            
+            Void result = null;
+            FutureTask<Void> task = new FutureTask<Void>(uploadTask, result);
+            task.run();
+            task.get(); // wait for the task to complete, no return value expected, though            
+        }  catch(Throwable e) {
+            if (uploadTask.isUploadCancelled()) {
+                throw new OsmTransferCancelledException();
+            }
+            throw new OsmTransferException(e);
+        } 
+        
+        // handle failed upload
+        //
+        if (uploadTask.isUploadFailed()) {
+            if (uploadTask.getLastThrowable() != null && uploadTask.getLastThrowable() instanceof OsmTransferException) {
+                OsmTransferException e = (OsmTransferException)uploadTask.getLastThrowable();
+                throw e;
+            } 
+            // shouldn't happen, but just in case
+            //
+            throw new OsmTransferException("Data upload failed for an unknown reason");
         }
+        
+        // handle cancelled upload 
+        //
+        if (uploadTask.isUploadCancelled()) {
+            throw new OsmTransferCancelledException();
+        }
+        
         return processed;
     }
+    
+    
 
     private void sleepAndListen() throws OsmTransferCancelledException {
         // System.out.print("backing off for 10 seconds...");
Index: OsmServerWriter.java
===================================================================
--- OsmServerWriter.java	(revision 1580)
+++ OsmServerWriter.java	(working copy)
@@ -137,6 +137,13 @@
     }
 
     private void dealWithTransferException (OsmTransferException e) {
+        if (e instanceof OsmTransferCancelledException) {
+            // ignore - don't bother the user with yet another message that he
+            // has successfully cancelled the data upload
+            //
+            return; 
+        }
+        
         JOptionPane.showMessageDialog(Main.parent, 
             /* tr("Error during upload: ") + */ e.getMessage());
     }
