Ignore:
Timestamp:
2009-06-10T23:15:32+02:00 (17 years ago)
Author:
Gubaer
Message:

#2437: cleaned up code for uploading and improved user feedback in case of 409 conflicts

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/io/OsmApi.java

    r1608 r1663  
    2323import java.util.Properties;
    2424import java.util.StringTokenizer;
    25 import java.util.concurrent.FutureTask;
    2625
    2726import javax.xml.parsers.SAXParserFactory;
     
    3433import org.openstreetmap.josm.data.osm.Way;
    3534import org.openstreetmap.josm.data.osm.visitor.CreateOsmChangeVisitor;
    36 import org.openstreetmap.josm.gui.PleaseWaitRunnable;
    3735import org.xml.sax.Attributes;
    3836import org.xml.sax.InputSource;
     
    5048 */
    5149public class OsmApi extends OsmConnection {
     50    /** max number of retries to send a request in case of HTTP 500 errors or timeouts */
     51    static public final int DEFAULT_MAX_NUM_RETRIES = 5;
    5252
    5353    /**
     
    9393                minVersion = atts.getValue("minimum");
    9494                maxVersion = atts.getValue("maximum");
    95             } else if (qName.equals("area"))
     95            } else if (qName.equals("area")) {
    9696                maxArea = atts.getValue("maximum");
     97            }
    9798        }
    9899    }
     
    132133     * @exception UnknownHostException thrown, if the API host is unknown
    133134     * @exception SocketTimeoutException thrown, if the connection to the API host  times out
    134      * @exception ConnectException throw, if the connection to the API host fails 
    135      * @exception Exception any other exception 
     135     * @exception ConnectException throw, if the connection to the API host fails
     136     * @exception Exception any other exception
    136137     */
    137138    public void initialize() throws UnknownHostException,SocketTimeoutException, ConnectException,Exception {
     
    149150                System.err.println(tr("This version of JOSM is incompatible with the configured server."));
    150151                System.err.println(tr("It supports protocol versions 0.5 and 0.6, while the server says it supports {0} to {1}.",
    151                     minVersion, maxVersion));
     152                        minVersion, maxVersion));
    152153                initialized = false;
    153154            }
    154155            System.out.println(tr("Communications with {0} established using protocol version {1}",
    155                 Main.pref.get("osm-server.url"),
    156                 version));
     156                    Main.pref.get("osm-server.url"),
     157                    version));
    157158            osmWriter.setVersion(version);
    158159        } catch (Exception ex) {
     
    302303    public Collection<OsmPrimitive> uploadDiff(final Collection<OsmPrimitive> list) throws OsmTransferException {
    303304
    304         if (changeset == null) {
     305        if (changeset == null)
    305306            throw new OsmTransferException(tr("No changeset present for diff upload"));
    306         }
    307 
    308307
    309308        final ArrayList<OsmPrimitive> processed = new ArrayList<OsmPrimitive>();
    310309
    311         // this is the asynchronous update task
    312         //
    313         class UploadDiffTask extends  PleaseWaitRunnable {
    314 
    315             private boolean uploadCancelled = false;
    316             private boolean uploadFailed = false;
    317             private Throwable lastThrowable = null;
    318 
    319             public UploadDiffTask(String title) {
    320                 super(title,false /* don't ignore exceptions */);
    321             }
    322 
    323             @Override protected void realRun() throws SAXException, IOException {
    324                 CreateOsmChangeVisitor duv = new CreateOsmChangeVisitor(changeset, OsmApi.this);
    325 
    326                 for (OsmPrimitive osm : list) {
    327                     int progress = Main.pleaseWaitDlg.progress.getValue();
    328                     Main.pleaseWaitDlg.currentAction.setText(tr("Preparing..."));
    329                     osm.visit(duv);
    330                     Main.pleaseWaitDlg.progress.setValue(progress+1);
    331                 }
    332 
    333                 Main.pleaseWaitDlg.currentAction.setText(tr("Uploading..."));
    334 
    335                 String diff = duv.getDocument();
    336                 try {
    337                     String diffresult = sendRequest("POST", "changeset/" + changeset.id + "/upload", diff);
    338                     DiffResultReader.parseDiffResult(diffresult, list, processed, duv.getNewIdMap(), Main.pleaseWaitDlg);
    339                 } catch (Exception sxe) {
    340                     if (isUploadCancelled()) {
    341                         // ignore exceptions thrown because the connection is aborted,
    342                         // i.e. IOExceptions or SocketExceptions
    343                         //
    344                         System.out.println("Ignoring exception caught because upload is cancelled. Exception is: " + sxe.toString());
    345                         return;
    346                     }
    347                     uploadFailed = true;
    348                     // remember last exception and don't throw it. If it was thrown again it would
    349                     // have to be encapsulated in a RuntimeException which would be nested in yet
    350                     // another RuntimeException by parent classes.
    351                     // Rather check isUploadFailed() and retrieve getLastThrowable() after the task
    352                     // is completed
    353                     //
    354                     lastThrowable = sxe;
    355                 }
    356             }
    357 
    358             @Override protected void finish() {
    359                 // do nothing
    360             }
    361 
    362             @Override protected void cancel() {
    363                 activeConnection.disconnect();
    364                 uploadCancelled = true;
    365             }
    366 
    367             public boolean isUploadCancelled() {
    368                 return uploadCancelled;
    369             }
    370 
    371             public boolean isUploadFailed() {
    372                 return uploadFailed;
    373             }
    374 
    375             public Throwable getLastThrowable() {
    376                 return lastThrowable;
    377             }
    378         }
    379 
    380         UploadDiffTask uploadTask = new UploadDiffTask(tr("Uploading data"));
    381 
    382         // run  data upload as asynchronous task
    383         //
     310
     311        CreateOsmChangeVisitor duv = new CreateOsmChangeVisitor(changeset, OsmApi.this);
     312
     313        for (OsmPrimitive osm : list) {
     314            int progress = Main.pleaseWaitDlg.progress.getValue();
     315            Main.pleaseWaitDlg.currentAction.setText(tr("Preparing..."));
     316            osm.visit(duv);
     317            Main.pleaseWaitDlg.progress.setValue(progress+1);
     318        }
     319
     320        Main.pleaseWaitDlg.currentAction.setText(tr("Uploading..."));
     321
     322        String diff = duv.getDocument();
     323        String diffresult = sendRequest("POST", "changeset/" + changeset.id + "/upload", diff);
    384324        try {
    385             Void result = null;
    386             FutureTask<Void> task = new FutureTask<Void>(uploadTask, result);
    387             task.run();
    388             task.get(); // wait for the task to complete, no return value expected, though
    389         }  catch(Throwable e) {
    390             if (uploadTask.isUploadCancelled()) {
    391                 throw new OsmTransferCancelledException();
    392             }
     325            DiffResultReader.parseDiffResult(diffresult, list, processed, duv.getNewIdMap(), Main.pleaseWaitDlg);
     326        } catch(Exception e) {
    393327            throw new OsmTransferException(e);
    394         }
    395 
    396         // handle failed upload
    397         //
    398         if (uploadTask.isUploadFailed()) {
    399             if (uploadTask.getLastThrowable() != null && uploadTask.getLastThrowable() instanceof OsmTransferException) {
    400                 OsmTransferException e = (OsmTransferException)uploadTask.getLastThrowable();
    401                 throw e;
    402             }
    403             // shouldn't happen, but just in case
    404             //
    405             throw new OsmTransferException(tr("Data upload failed for unknown reason"));
    406         }
    407 
    408         // handle cancelled upload
    409         //
    410         if (uploadTask.isUploadCancelled()) {
    411             throw new OsmTransferCancelledException();
    412328        }
    413329
     
    420336        // System.out.print("backing off for 10 seconds...");
    421337        for(int i=0; i < 10; i++) {
    422             if (cancel || isAuthCancelled()) {
     338            if (cancel || isAuthCancelled())
    423339                throw new OsmTransferCancelledException();
    424             }
    425340            try {
    426341                Thread.sleep(1000);
     
    450365
    451366        StringBuffer responseBody = new StringBuffer();
    452         StringBuffer statusMessage = new StringBuffer();
    453 
    454         int retries = 5; // configurable?
     367
     368        int retries = Main.pref.getInteger("osm-server.max-num-retries", DEFAULT_MAX_NUM_RETRIES);
     369        retries = Math.max(0,retries);
     370
    455371
    456372        while(true) { // the retry loop
     
    511427                    responseBody.append("\n");
    512428                }
    513 
    514                 statusMessage.setLength(0);
     429                String errorHeader = null;
    515430                // Look for a detailed error message from the server
    516431                if (activeConnection.getHeaderField("Error") != null) {
    517                     String er = activeConnection.getHeaderField("Error");
    518                     System.err.println("Error header: " + er);
    519                     statusMessage.append(tr(er));
     432                    errorHeader = activeConnection.getHeaderField("Error");
     433                    System.err.println("Error header: " + errorHeader);
    520434                } else if (retCode != 200 && responseBody.length()>0) {
    521435                    System.err.println("Error body: " + responseBody);
    522                     statusMessage.append(tr(responseBody.toString()));
    523                 } else {
    524                     statusMessage.append(activeConnection.getResponseMessage());
    525436                }
    526437                activeConnection.disconnect();
    527438
    528                 if (retCode != 200) {
    529                     throw new OsmTransferException(statusMessage.toString());
    530                 }
     439                if (retCode != 200)
     440                    throw new OsmApiException(retCode,errorHeader,responseBody.toString());
     441
    531442                return responseBody.toString();
    532443            } catch (UnknownHostException e) {
    533                 throw new OsmTransferException(tr("Unknown host")+": "+e.getMessage(), e);
     444                throw new OsmTransferException(e);
    534445            } catch (SocketTimeoutException e) {
    535                 if (retries-- > 0)
     446                if (retries-- > 0) {
    536447                    continue;
    537                 throw new OsmTransferException(e.getMessage()+ " " + e.getClass().getCanonicalName(), e);
     448                }
     449                throw new OsmTransferException(e);
    538450            } catch (ConnectException e) {
    539                 if (retries-- > 0)
     451                if (retries-- > 0) {
    540452                    continue;
    541                 throw new OsmTransferException(e.getMessage()+ " " + e.getClass().getCanonicalName(), e);
     453                }
     454                throw new OsmTransferException(e);
    542455            } catch (Exception e) {
    543456                if (e instanceof OsmTransferException) throw (OsmTransferException) e;
Note: See TracChangeset for help on using the changeset viewer.