Changeset 1663 in josm for trunk/src/org/openstreetmap/josm/io
- Timestamp:
- 2009-06-10T23:15:32+02:00 (15 years ago)
- Location:
- trunk/src/org/openstreetmap/josm/io
- Files:
-
- 2 added
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/org/openstreetmap/josm/io/OsmApi.java
r1608 r1663 23 23 import java.util.Properties; 24 24 import java.util.StringTokenizer; 25 import java.util.concurrent.FutureTask;26 25 27 26 import javax.xml.parsers.SAXParserFactory; … … 34 33 import org.openstreetmap.josm.data.osm.Way; 35 34 import org.openstreetmap.josm.data.osm.visitor.CreateOsmChangeVisitor; 36 import org.openstreetmap.josm.gui.PleaseWaitRunnable;37 35 import org.xml.sax.Attributes; 38 36 import org.xml.sax.InputSource; … … 50 48 */ 51 49 public 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; 52 52 53 53 /** … … 93 93 minVersion = atts.getValue("minimum"); 94 94 maxVersion = atts.getValue("maximum"); 95 } else if (qName.equals("area")) 95 } else if (qName.equals("area")) { 96 96 maxArea = atts.getValue("maximum"); 97 } 97 98 } 98 99 } … … 132 133 * @exception UnknownHostException thrown, if the API host is unknown 133 134 * @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 136 137 */ 137 138 public void initialize() throws UnknownHostException,SocketTimeoutException, ConnectException,Exception { … … 149 150 System.err.println(tr("This version of JOSM is incompatible with the configured server.")); 150 151 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)); 152 153 initialized = false; 153 154 } 154 155 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)); 157 158 osmWriter.setVersion(version); 158 159 } catch (Exception ex) { … … 302 303 public Collection<OsmPrimitive> uploadDiff(final Collection<OsmPrimitive> list) throws OsmTransferException { 303 304 304 if (changeset == null) {305 if (changeset == null) 305 306 throw new OsmTransferException(tr("No changeset present for diff upload")); 306 }307 308 307 309 308 final ArrayList<OsmPrimitive> processed = new ArrayList<OsmPrimitive>(); 310 309 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); 384 324 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) { 393 327 throw new OsmTransferException(e); 394 }395 396 // handle failed upload397 //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 case404 //405 throw new OsmTransferException(tr("Data upload failed for unknown reason"));406 }407 408 // handle cancelled upload409 //410 if (uploadTask.isUploadCancelled()) {411 throw new OsmTransferCancelledException();412 328 } 413 329 … … 420 336 // System.out.print("backing off for 10 seconds..."); 421 337 for(int i=0; i < 10; i++) { 422 if (cancel || isAuthCancelled()) {338 if (cancel || isAuthCancelled()) 423 339 throw new OsmTransferCancelledException(); 424 }425 340 try { 426 341 Thread.sleep(1000); … … 450 365 451 366 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 455 371 456 372 while(true) { // the retry loop … … 511 427 responseBody.append("\n"); 512 428 } 513 514 statusMessage.setLength(0); 429 String errorHeader = null; 515 430 // Look for a detailed error message from the server 516 431 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); 520 434 } else if (retCode != 200 && responseBody.length()>0) { 521 435 System.err.println("Error body: " + responseBody); 522 statusMessage.append(tr(responseBody.toString()));523 } else {524 statusMessage.append(activeConnection.getResponseMessage());525 436 } 526 437 activeConnection.disconnect(); 527 438 528 if (retCode != 200) {529 throw new Osm TransferException(statusMessage.toString());530 } 439 if (retCode != 200) 440 throw new OsmApiException(retCode,errorHeader,responseBody.toString()); 441 531 442 return responseBody.toString(); 532 443 } catch (UnknownHostException e) { 533 throw new OsmTransferException( tr("Unknown host")+": "+e.getMessage(),e);444 throw new OsmTransferException(e); 534 445 } catch (SocketTimeoutException e) { 535 if (retries-- > 0) 446 if (retries-- > 0) { 536 447 continue; 537 throw new OsmTransferException(e.getMessage()+ " " + e.getClass().getCanonicalName(), e); 448 } 449 throw new OsmTransferException(e); 538 450 } catch (ConnectException e) { 539 if (retries-- > 0) 451 if (retries-- > 0) { 540 452 continue; 541 throw new OsmTransferException(e.getMessage()+ " " + e.getClass().getCanonicalName(), e); 453 } 454 throw new OsmTransferException(e); 542 455 } catch (Exception e) { 543 456 if (e instanceof OsmTransferException) throw (OsmTransferException) e; -
trunk/src/org/openstreetmap/josm/io/OsmServerWriter.java
r1630 r1663 7 7 import java.util.LinkedList; 8 8 import java.util.List; 9 10 import javax.swing.JOptionPane; 9 import java.util.logging.Logger; 11 10 12 11 import org.openstreetmap.josm.Main; … … 14 13 import org.openstreetmap.josm.data.osm.OsmPrimitive; 15 14 import org.openstreetmap.josm.data.osm.visitor.NameVisitor; 16 import org.openstreetmap.josm.gui.historycombobox.JHistoryComboBox;17 15 18 16 /** … … 24 22 */ 25 23 public class OsmServerWriter { 24 static private final Logger logger = Logger.getLogger(OsmServerWriter.class.getName()); 26 25 27 26 /** … … 45 44 long now = System.currentTimeMillis(); 46 45 long elapsed = now - uploadStartTime; 47 if (elapsed == 0) 46 if (elapsed == 0) { 48 47 elapsed = 1; 48 } 49 49 float uploads_per_ms = (float)progress / elapsed; 50 50 float uploads_left = list_size - progress; … … 53 53 int seconds_left = (ms_left / MSECS_PER_SECOND) % SECONDS_PER_MINUTE ; 54 54 String time_left_str = Integer.toString(minutes_left) + ":"; 55 if (seconds_left < 10) 55 if (seconds_left < 10) { 56 56 time_left_str += "0"; 57 } 57 58 time_left_str += Integer.toString(seconds_left); 58 59 return time_left_str; … … 60 61 61 62 /** 63 * retrieves the most recent changeset comment from the preferences 64 * 65 * @return the most recent changeset comment 66 */ 67 protected String getChangesetComment() { 68 String cmt = ""; 69 List<String> history = new LinkedList<String>( 70 Main.pref.getCollection(UploadAction.HISTORY_KEY, new LinkedList<String>())); 71 if(history.size() > 0) { 72 cmt = history.get(0); 73 } 74 return cmt; 75 } 76 77 /** 62 78 * Send the dataset to the server. 63 * @param the_version version of the data set 64 * @param list list of objects to send 79 * 80 * @param apiVersion version of the data set 81 * @param primitives list of objects to send 65 82 */ 66 public void uploadOsm(String the_version, Collection<OsmPrimitive> list){83 public void uploadOsm(String apiVersion, Collection<OsmPrimitive> primitives) throws OsmTransferException { 67 84 processed = new LinkedList<OsmPrimitive>(); 68 85 … … 73 90 api.initialize(); 74 91 } catch(Exception e) { 75 JOptionPane.showMessageDialog( 76 null, 77 tr( "Failed to initialize communication with the OSM server {0}.\n" 78 + "Check the server URL in your preferences and your internet connection.", 79 Main.pref.get("osm-server.url") 80 ), 81 tr("Error"), 82 JOptionPane.ERROR_MESSAGE 83 ); 84 e.printStackTrace(); 85 return; 92 throw new OsmApiInitializationException(e); 86 93 } 87 94 88 Main.pleaseWaitDlg.progress.setMaximum( list.size());95 Main.pleaseWaitDlg.progress.setMaximum(primitives.size()); 89 96 Main.pleaseWaitDlg.progress.setValue(0); 90 97 91 boolean useChangesets = api.hasChangesetSupport(); 92 93 // controls whether or not we try and upload the whole bunch in one go 94 boolean useDiffUploads = Main.pref.getBoolean("osm-server.atomic-upload", 95 "0.6".equals(api.getVersion())); 96 97 // create changeset if required 98 try { 99 if (useChangesets) { 100 // add the last entered comment to the changeset 101 String cmt = ""; 102 List<String> history = new LinkedList<String>( 103 Main.pref.getCollection(UploadAction.HISTORY_KEY, new LinkedList<String>())); 104 if(history.size() > 0) { 105 cmt = history.get(0); 106 } 107 api.createChangeset(cmt); 108 } 109 } catch (OsmTransferException ex) { 110 dealWithTransferException(ex); 111 return; 98 // check whether we can use changeset 99 // 100 boolean canUseChangeset = api.hasChangesetSupport(); 101 boolean useChangeset = Main.pref.getBoolean("osm-server.atomic-upload", apiVersion.compareTo("0.6")>=0); 102 if (useChangeset && ! canUseChangeset) { 103 System.out.println(tr("WARNING: preference '{0}' or api version {1} of dataset requires to use changesets, but API is not handle them. Ignoring changesets.", "osm-server.atomic-upload", apiVersion)); 104 useChangeset = false; 112 105 } 113 106 114 try { 115 if (useDiffUploads) { 116 // all in one go 117 processed.addAll(api.uploadDiff(list)); 118 } else { 119 // upload changes individually (90% of code is for the status display...) 120 NameVisitor v = new NameVisitor(); 121 uploadStartTime = System.currentTimeMillis(); 122 for (OsmPrimitive osm : list) { 123 osm.visit(v); 124 int progress = Main.pleaseWaitDlg.progress.getValue(); 125 String time_left_str = timeLeft(progress, list.size()); 126 Main.pleaseWaitDlg.currentAction.setText( 127 tr("{0}% ({1}/{2}), {3} left. Uploading {4}: {5} (id: {6})", 128 Math.round(100.0*progress/list.size()), progress, 129 list.size(), time_left_str, tr(v.className), v.name, osm.id)); 130 makeApiRequest(osm); 131 processed.add(osm); 132 Main.pleaseWaitDlg.progress.setValue(progress+1); 107 if (useChangeset) { 108 // upload everything in one changeset 109 // 110 try { 111 api.createChangeset(getChangesetComment()); 112 processed.addAll(api.uploadDiff(primitives)); 113 } catch(OsmTransferException e) { 114 throw e; 115 } finally { 116 try { 117 if (canUseChangeset) { 118 api.stopChangeset(); 119 } 120 } catch (Exception ee) { 121 // ignore nested exception 133 122 } 134 123 } 135 if (useChangesets) api.stopChangeset(); 136 } catch (OsmTransferException e) { 137 try { 138 if (useChangesets) api.stopChangeset(); 139 } catch (Exception ee) { 140 // ignore nested exception 124 } else { 125 // upload changes individually (90% of code is for the status display...) 126 // 127 NameVisitor v = new NameVisitor(); 128 uploadStartTime = System.currentTimeMillis(); 129 for (OsmPrimitive osm : primitives) { 130 osm.visit(v); 131 int progress = Main.pleaseWaitDlg.progress.getValue(); 132 String time_left_str = timeLeft(progress, primitives.size()); 133 Main.pleaseWaitDlg.currentAction.setText( 134 tr("{0}% ({1}/{2}), {3} left. Uploading {4}: {5} (id: {6})", 135 Math.round(100.0*progress/primitives.size()), progress, 136 primitives.size(), time_left_str, tr(v.className), v.name, osm.id)); 137 makeApiRequest(osm); 138 processed.add(osm); 139 Main.pleaseWaitDlg.progress.setValue(progress+1); 141 140 } 142 dealWithTransferException(e);143 141 } 144 142 } … … 154 152 } 155 153 156 private void dealWithTransferException (OsmTransferException e) { 157 if (e instanceof OsmTransferCancelledException) { 158 // ignore - don't bother the user with yet another message that he 159 // has successfully cancelled the data upload 160 // 161 return; 154 public void disconnectActiveConnection() { 155 if (api != null && api.activeConnection != null) { 156 api.activeConnection.disconnect(); 162 157 } 163 164 JOptionPane.showMessageDialog(Main.parent,165 /* tr("Error during upload: ") + */ e.getMessage());166 158 } 167 159 }
Note:
See TracChangeset
for help on using the changeset viewer.