- Timestamp:
- 2023-06-13T21:32:22+02:00 (14 months ago)
- Location:
- trunk/src/org/openstreetmap/josm
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/org/openstreetmap/josm/actions/UploadAction.java
r18467 r18752 12 12 import java.util.Map; 13 13 import java.util.Optional; 14 import java.util.concurrent.CompletableFuture; 15 import java.util.concurrent.ExecutionException; 16 import java.util.concurrent.Future; 17 import java.util.function.Consumer; 14 18 15 19 import javax.swing.JOptionPane; … … 37 41 import org.openstreetmap.josm.spi.preferences.Config; 38 42 import org.openstreetmap.josm.tools.ImageProvider; 43 import org.openstreetmap.josm.tools.JosmRuntimeException; 39 44 import org.openstreetmap.josm.tools.Logging; 40 45 import org.openstreetmap.josm.tools.Shortcut; … … 43 48 /** 44 49 * Action that opens a connection to the osm server and uploads all changes. 45 * 50 * <p> 46 51 * A dialog is displayed asking the user to specify a rectangle to grab. 47 52 * The url and account settings from the preferences are used. 48 * 49 * If the upload fails this action offers various options to resolve conflicts.53 * <p> 54 * If the upload fails, this action offers various options to resolve conflicts. 50 55 * 51 56 * @author imi … … 56 61 * when the user wants to upload data. Plugins can insert their own hooks here 57 62 * if they want to be able to veto an upload. 58 * 63 * <p> 59 64 * Be default, the standard upload dialog is the only element in the list. 60 65 * Plugins should normally insert their code before that, so that the upload … … 195 200 196 201 /** 197 * Check whether the preconditions are met to upload data in <code>apiData</code>.198 * Makes sure upload is allowed, primitives in <code>apiData</code>don't participate in conflicts and202 * Check whether the preconditions are met to upload data in {@code apiData}. 203 * Makes sure upload is allowed, primitives in {@code apiData} don't participate in conflicts and 199 204 * runs the installed {@link UploadHook}s. 200 205 * … … 204 209 */ 205 210 public static boolean checkPreUploadConditions(AbstractModifiableLayer layer, APIDataSet apiData) { 211 try { 212 return checkPreUploadConditionsAsync(layer, apiData, null).get(); 213 } catch (InterruptedException e) { 214 Thread.currentThread().interrupt(); 215 throw new JosmRuntimeException(e); 216 } catch (ExecutionException e) { 217 throw new JosmRuntimeException(e); 218 } 219 } 220 221 /** 222 * Check whether the preconditions are met to upload data in {@code apiData}. 223 * Makes sure upload is allowed, primitives in {@code apiData} don't participate in conflicts and 224 * runs the installed {@link UploadHook}s. 225 * 226 * @param layer the source layer of the data to be uploaded 227 * @param apiData the data to be uploaded 228 * @param onFinish {@code true} if the preconditions are met; {@code false}, otherwise 229 * @return A future that completes when the checks are finished 230 * @since 18752 231 */ 232 private static Future<Boolean> checkPreUploadConditionsAsync(AbstractModifiableLayer layer, APIDataSet apiData, Consumer<Boolean> onFinish) { 233 final CompletableFuture<Boolean> future = new CompletableFuture<>(); 234 if (onFinish != null) { 235 future.thenAccept(onFinish); 236 } 206 237 if (layer.isUploadDiscouraged() && warnUploadDiscouraged(layer)) { 207 return false; 208 } 209 if (layer instanceof OsmDataLayer) { 238 future.complete(false); 239 } else if (layer instanceof OsmDataLayer) { 210 240 OsmDataLayer osmLayer = (OsmDataLayer) layer; 211 241 ConflictCollection conflicts = osmLayer.getConflicts(); 212 242 if (apiData.participatesInConflict(conflicts)) { 213 243 alertUnresolvedConflicts(osmLayer); 214 return false;244 future.complete(false); 215 245 } 216 246 } 217 247 // Call all upload hooks in sequence. 218 // FIXME: this should become an asynchronous task 219 // 220 if (apiData != null) { 221 return UPLOAD_HOOKS.stream().allMatch(hook -> hook.checkUpload(apiData)); 222 } 223 224 return true; 248 if (!future.isDone()) { 249 MainApplication.worker.execute(() -> { 250 boolean hooks = true; 251 if (apiData != null) { 252 hooks = UPLOAD_HOOKS.stream().allMatch(hook -> hook.checkUpload(apiData)); 253 } 254 future.complete(hooks); 255 }); 256 } 257 return future; 225 258 } 226 259 … … 236 269 return; 237 270 } 238 if (!checkPreUploadConditions(layer, apiData)) 239 return; 271 checkPreUploadConditionsAsync(layer, apiData, passed -> GuiHelper.runInEDT(() -> { 272 if (Boolean.TRUE.equals(passed)) { 273 realUploadData(layer, apiData); 274 } else { 275 new Notification(tr("One of the upload verification processes failed")).show(); 276 } 277 })); 278 } 279 280 /** 281 * Uploads data to the OSM API. 282 * 283 * @param layer the source layer for the data to upload 284 * @param apiData the primitives to be added, updated, or deleted 285 */ 286 private static void realUploadData(final OsmDataLayer layer, final APIDataSet apiData) { 240 287 241 288 ChangesetUpdater.check(); … … 284 331 uploadStrategySpecification, layer, apiData, cs); 285 332 286 if (asyncUploadTask.isPresent()) { 287 MainApplication.worker.execute(asyncUploadTask.get()); 288 } 333 asyncUploadTask.ifPresent(MainApplication.worker::execute); 289 334 } else { 290 335 MainApplication.worker.execute(new UploadPrimitivesTask(uploadStrategySpecification, layer, apiData, cs)); -
trunk/src/org/openstreetmap/josm/actions/upload/ValidateUploadHook.java
r18318 r18752 6 6 import java.awt.Dimension; 7 7 import java.awt.GridBagLayout; 8 import java.util.ArrayList;9 8 import java.util.Collection; 10 9 import java.util.List; 10 import java.util.concurrent.atomic.AtomicBoolean; 11 11 12 12 import javax.swing.JPanel; … … 15 15 import org.openstreetmap.josm.data.APIDataSet; 16 16 import org.openstreetmap.josm.data.osm.OsmPrimitive; 17 import org.openstreetmap.josm.data.preferences.sources.ValidatorPrefHelper;18 17 import org.openstreetmap.josm.data.validation.OsmValidator; 19 import org.openstreetmap.josm.data.validation.Severity;20 import org.openstreetmap.josm.data.validation.Test;21 18 import org.openstreetmap.josm.data.validation.TestError; 19 import org.openstreetmap.josm.data.validation.ValidationTask; 22 20 import org.openstreetmap.josm.data.validation.util.AggregatePrimitivesVisitor; 23 21 import org.openstreetmap.josm.gui.ExtendedDialog; 24 22 import org.openstreetmap.josm.gui.MainApplication; 25 import org.openstreetmap.josm.gui.MapFrame;26 23 import org.openstreetmap.josm.gui.dialogs.validator.ValidatorTreePanel; 27 import org.openstreetmap.josm.gui.layer.OsmDataLayer;28 24 import org.openstreetmap.josm.gui.layer.ValidatorLayer; 29 25 import org.openstreetmap.josm.gui.util.GuiHelper; … … 34 30 * The action that does the validate thing. 35 31 * <p> 36 * This action iterates through all active tests and give them the data, so that32 * This action iterates through all active tests and gives them the data, so that 37 33 * each one can test it. 38 34 * … … 45 41 * Validate the modified data before uploading 46 42 * @param apiDataSet contains primitives to be uploaded 47 * @return trueif upload should continue, else false43 * @return {@code true} if upload should continue, else false 48 44 */ 49 45 @Override 50 46 public boolean checkUpload(APIDataSet apiDataSet) { 51 52 OsmValidator.initializeTests(); 53 Collection<Test> tests = OsmValidator.getEnabledTests(true); 54 if (tests.isEmpty()) 55 return true; 56 47 AtomicBoolean returnCode = new AtomicBoolean(); 57 48 AggregatePrimitivesVisitor v = new AggregatePrimitivesVisitor(); 58 49 v.visit(apiDataSet.getPrimitivesToAdd()); 59 Collection<OsmPrimitive> selection = v.visit(apiDataSet.getPrimitivesToUpdate()); 50 Collection<OsmPrimitive> visited = v.visit(apiDataSet.getPrimitivesToUpdate()); 51 OsmValidator.initializeTests(); 52 new ValidationTask(errors -> { 53 if (errors.stream().allMatch(TestError::isIgnored)) { 54 returnCode.set(true); 55 } else { 56 // Unfortunately, the progress monitor is not "finished" until after `finish` is called, so we will 57 // have a ProgressMonitor open behind the error screen. Fortunately, the error screen appears in front 58 // of the progress monitor. 59 GuiHelper.runInEDTAndWait(() -> returnCode.set(displayErrorScreen(errors))); 60 } 61 }, null, OsmValidator.getEnabledTests(true), visited, null, true).run(); 60 62 61 List<TestError> errors = new ArrayList<>(30); 62 for (Test test : tests) { 63 test.setBeforeUpload(true); 64 test.setPartialSelection(true); 65 test.startTest(null); 66 test.visit(selection); 67 test.endTest(); 68 if (ValidatorPrefHelper.PREF_OTHER.get() && ValidatorPrefHelper.PREF_OTHER_UPLOAD.get()) { 69 errors.addAll(test.getErrors()); 70 } else { 71 for (TestError e : test.getErrors()) { 72 if (e.getSeverity() != Severity.OTHER) { 73 errors.add(e); 74 } 75 } 76 } 77 test.clear(); 78 test.setBeforeUpload(false); 79 } 80 81 if (Boolean.TRUE.equals(ValidatorPrefHelper.PREF_USE_IGNORE.get())) { 82 errors.forEach(TestError::updateIgnored); 83 } 84 85 OsmDataLayer editLayer = MainApplication.getLayerManager().getEditLayer(); 86 if (editLayer != null) { 87 editLayer.validationErrors.clear(); 88 editLayer.validationErrors.addAll(errors); 89 } 90 MapFrame map = MainApplication.getMap(); 91 if (map != null) { 92 map.validatorDialog.tree.setErrors(errors); 93 } 94 if (errors.stream().allMatch(TestError::isIgnored)) 95 return true; 96 97 return displayErrorScreen(errors); 63 return returnCode.get(); 98 64 } 99 65 … … 102 68 * give the user the possibility to cancel the upload. 103 69 * @param errors The errors displayed in the screen 104 * @return <code>true</code>, if the upload should continue. <code>false</code>105 * if the user requested cancel.70 * @return {@code true}, if the upload should continue.<br> 71 * {@code false}, if the user requested cancel. 106 72 */ 107 73 private static boolean displayErrorScreen(List<TestError> errors) { -
trunk/src/org/openstreetmap/josm/data/validation/ValidationTask.java
r18208 r18752 4 4 import static org.openstreetmap.josm.tools.I18n.tr; 5 5 6 import java.awt.GraphicsEnvironment; 6 7 import java.util.ArrayList; 7 8 import java.util.Collection; 8 9 import java.util.List; 10 import java.util.function.BiConsumer; 11 import java.util.function.Consumer; 9 12 10 13 import javax.swing.JOptionPane; … … 26 29 */ 27 30 public class ValidationTask extends PleaseWaitRunnable { 31 private final Consumer<List<TestError>> onFinish; 28 32 private Collection<Test> tests; 29 33 private final Collection<OsmPrimitive> validatedPrimitives; 30 34 private final Collection<OsmPrimitive> formerValidatedPrimitives; 35 private final boolean beforeUpload; 31 36 private boolean canceled; 32 37 private List<TestError> errors; 38 private BiConsumer<ValidationTask, Test> testConsumer; 33 39 34 40 /** … … 45 51 } 46 52 47 protected ValidationTask(ProgressMonitor progressMonitor, 48 Collection<Test> tests, 49 Collection<OsmPrimitive> validatedPrimitives, 50 Collection<OsmPrimitive> formerValidatedPrimitives) { 51 super(tr("Validating"), progressMonitor, false /*don't ignore exceptions */); 53 /** 54 * Constructs a new {@code ValidationTask} 55 * 56 * @param onFinish called when the tests are finished 57 * @param progressMonitor the progress monitor to update with test progress 58 * @param tests the tests to run 59 * @param validatedPrimitives the collection of primitives to validate. 60 * @param formerValidatedPrimitives the last collection of primitives being validates. May be null. 61 * @param beforeUpload {@code true} if this is being run prior to upload 62 * @since 18752 63 */ 64 public ValidationTask(Consumer<List<TestError>> onFinish, 65 ProgressMonitor progressMonitor, 66 Collection<Test> tests, 67 Collection<OsmPrimitive> validatedPrimitives, 68 Collection<OsmPrimitive> formerValidatedPrimitives, 69 boolean beforeUpload) { 70 super(tr("Validating"), 71 progressMonitor != null ? progressMonitor : new PleaseWaitProgressMonitor(tr("Validating")), 72 false /*don't ignore exceptions */); 73 this.onFinish = onFinish; 52 74 this.validatedPrimitives = validatedPrimitives; 53 75 this.formerValidatedPrimitives = formerValidatedPrimitives; 54 76 this.tests = tests; 77 this.beforeUpload = beforeUpload; 78 } 79 80 protected ValidationTask(ProgressMonitor progressMonitor, 81 Collection<Test> tests, 82 Collection<OsmPrimitive> validatedPrimitives, 83 Collection<OsmPrimitive> formerValidatedPrimitives) { 84 this(null, progressMonitor, tests, validatedPrimitives, formerValidatedPrimitives, false); 55 85 } 56 86 … … 64 94 if (canceled) return; 65 95 66 // update GUI on Swing EDT 67 GuiHelper.runInEDT(() -> { 68 MapFrame map = MainApplication.getMap(); 69 map.validatorDialog.unfurlDialog(); 70 map.validatorDialog.tree.setErrors(errors); 71 //FIXME: nicer way to find / invalidate the corresponding error layer 72 MainApplication.getLayerManager().getLayersOfType(ValidatorLayer.class).forEach(ValidatorLayer::invalidate); 73 if (!errors.isEmpty()) { 74 OsmValidator.initializeErrorLayer(); 75 } 76 }); 96 if (!GraphicsEnvironment.isHeadless() && MainApplication.getMap() != null) { 97 // update GUI on Swing EDT 98 GuiHelper.runInEDT(() -> { 99 MapFrame map = MainApplication.getMap(); 100 map.validatorDialog.unfurlDialog(); 101 map.validatorDialog.tree.setErrors(errors); 102 //FIXME: nicer way to find / invalidate the corresponding error layer 103 MainApplication.getLayerManager().getLayersOfType(ValidatorLayer.class).forEach(ValidatorLayer::invalidate); 104 if (!errors.isEmpty()) { 105 OsmValidator.initializeErrorLayer(); 106 } 107 }); 108 } 109 if (this.onFinish != null) { 110 this.onFinish.accept(this.errors); 111 } 77 112 } 78 113 … … 89 124 testCounter++; 90 125 getProgressMonitor().setCustomText(tr("Test {0}/{1}: Starting {2}", testCounter, tests.size(), test.getName())); 91 test.setBeforeUpload( false);126 test.setBeforeUpload(this.beforeUpload); 92 127 test.setPartialSelection(formerValidatedPrimitives != null); 93 128 test.startTest(getProgressMonitor().createSubTaskMonitor(validatedPrimitives.size(), false)); … … 95 130 test.endTest(); 96 131 errors.addAll(test.getErrors()); 132 if (this.testConsumer != null) { 133 this.testConsumer.accept(this, test); 134 } 97 135 test.clear(); 136 test.setBeforeUpload(false); 98 137 } 99 138 tests = null; … … 125 164 return errors; 126 165 } 166 167 /** 168 * A test consumer to avoid filling up memory. A test consumer <i>may</i> remove tests it has consumed. 169 * @param testConsumer The consumer which takes a {@link ValidationTask} ({@code this}) and the test that finished. 170 * @since 18752 171 */ 172 public void setTestConsumer(BiConsumer<ValidationTask, Test> testConsumer) { 173 this.testConsumer = testConsumer; 174 } 127 175 } -
trunk/src/org/openstreetmap/josm/data/validation/ValidatorCLI.java
r18718 r18752 11 11 import java.nio.charset.StandardCharsets; 12 12 import java.nio.file.Files; 13 import java.nio.file.Path; 13 14 import java.nio.file.Paths; 14 15 import java.util.ArrayList; … … 26 27 import java.util.stream.Collectors; 27 28 29 import jakarta.json.JsonObject; 28 30 import org.apache.commons.compress.utils.FileNameUtils; 29 31 import org.openstreetmap.josm.actions.ExtensionFileFilter; … … 177 179 for (String inputFile : this.input) { 178 180 if (inputFile.endsWith(".validator.mapcss")) { 179 this.processValidatorFile(inputFile);181 processValidatorFile(inputFile); 180 182 } else if (inputFile.endsWith(".mapcss")) { 181 this.processMapcssFile(inputFile);183 processMapcssFile(inputFile); 182 184 } else { 183 185 this.processFile(inputFile); … … 198 200 * @throws ParseException if the file does not match the mapcss syntax 199 201 */ 200 private void processMapcssFile(final String inputFile) throws ParseException {202 private static void processMapcssFile(final String inputFile) throws ParseException { 201 203 final MapCSSStyleSource styleSource = new MapCSSStyleSource(new File(inputFile).toURI().getPath(), inputFile, inputFile); 202 204 styleSource.loadStyleSource(); … … 215 217 * @throws ParseException if the file does not match the validator mapcss syntax 216 218 */ 217 private void processValidatorFile(final String inputFile) throws ParseException, IOException {219 private static void processValidatorFile(final String inputFile) throws ParseException, IOException { 218 220 // Check asserts 219 221 Config.getPref().putBoolean("validator.check_assert_local_rules", true); … … 257 259 try { 258 260 Logging.info(task); 259 OsmValidator.initializeTests();260 261 dataLayer = MainApplication.getLayerManager().getLayersOfType(OsmDataLayer.class) 261 262 .stream().filter(layer -> inputFileFile.equals(layer.getAssociatedFile())) … … 270 271 } 271 272 } 272 Collection<Test> tests = OsmValidator.getEnabledTests(false);273 if ( Files.isRegularFile(Paths.get(outputFile)) && !Files.deleteIfExists(Paths.get(outputFile))) {273 Path path = Paths.get(outputFile); 274 if (path.toFile().isFile() && !Files.deleteIfExists(path)) { 274 275 Logging.error("Could not delete {0}, attempting to append", outputFile); 275 276 } 276 277 GeoJSONMapRouletteWriter geoJSONMapRouletteWriter = new GeoJSONMapRouletteWriter(dataSet); 277 try (OutputStream fileOutputStream = Files.newOutputStream(Paths.get(outputFile))) { 278 tests.parallelStream().forEach(test -> runTest(test, geoJSONMapRouletteWriter, fileOutputStream, dataSet)); 278 OsmValidator.initializeTests(); 279 280 try (OutputStream fileOutputStream = Files.newOutputStream(path)) { 281 // The first writeErrors catches anything that was written, for whatever reason. This is probably never 282 // going to be called. 283 ValidationTask validationTask = new ValidationTask(errors -> writeErrors(geoJSONMapRouletteWriter, fileOutputStream, errors), 284 progressMonitorFactory.get(), OsmValidator.getEnabledTests(false), 285 dataSet.allPrimitives(), Collections.emptyList(), false); 286 // This avoids keeping errors in memory 287 validationTask.setTestConsumer((t, test) -> { 288 writeErrors(geoJSONMapRouletteWriter, fileOutputStream, test.getErrors()); 289 t.getErrors().removeIf(test.getErrors()::contains); 290 }); 291 validationTask.run(); 279 292 } 280 293 } finally { … … 283 296 } 284 297 Logging.info(stopwatch.toString(task)); 298 } 299 } 300 301 private void writeErrors(GeoJSONMapRouletteWriter geoJSONMapRouletteWriter, OutputStream fileOutputStream, 302 Collection<TestError> errors) { 303 for (TestError error : errors) { 304 Optional<JsonObject> object = geoJSONMapRouletteWriter.write(error); 305 if (object.isPresent()) { 306 try { 307 writeToFile(fileOutputStream, object.get().toString().getBytes(StandardCharsets.UTF_8)); 308 } catch (IOException e) { 309 throw new JosmRuntimeException(e); 310 } 311 } 285 312 } 286 313 } … … 300 327 } 301 328 return FileNameUtils.getBaseName(FileNameUtils.getBaseName(inputString)) + ".geojson"; 302 }303 304 /**305 * Run a test306 * @param test The test to run307 * @param geoJSONMapRouletteWriter The object to use to create challenges308 * @param fileOutputStream The location to write data to309 * @param dataSet The dataset to check310 */311 private void runTest(final Test test, final GeoJSONMapRouletteWriter geoJSONMapRouletteWriter,312 final OutputStream fileOutputStream, DataSet dataSet) {313 test.startTest(progressMonitorFactory.get());314 test.visit(dataSet.allPrimitives());315 test.endTest();316 test.getErrors().stream().map(geoJSONMapRouletteWriter::write)317 .filter(Optional::isPresent).map(Optional::get)318 .map(jsonObject -> jsonObject.toString().getBytes(StandardCharsets.UTF_8)).forEach(bytes -> {319 try {320 writeToFile(fileOutputStream, bytes);321 } catch (IOException e) {322 throw new JosmRuntimeException(e);323 }324 });325 test.clear();326 329 } 327 330 -
trunk/src/org/openstreetmap/josm/gui/io/SaveLayersDialog.java
r18706 r18752 64 64 /** 65 65 * Dialog that pops up when the user closes a layer with modified data. 66 * 67 * It asks for confirmation that all modification should be discarded and offers66 * <p> 67 * It asks for confirmation that all modifications should be discarded and offer 68 68 * to save the layers to file or upload to server, depending on the type of layer. 69 69 */ … … 450 450 closeDialog(); 451 451 } 452 } catch (UserCancelException ignore) {453 Logging.trace( ignore);452 } catch (UserCancelException userCancelException) { 453 Logging.trace(userCancelException); 454 454 } 455 455 } … … 557 557 AbstractModifiableLayer layer = layerInfo.getLayer(); 558 558 if (canceled) { 559 GuiHelper.runInEDTAndWait(() -> model.setUploadState(layer, UploadOrSaveState.CANCELED)); 560 continue; 561 } 562 GuiHelper.runInEDTAndWait(() -> monitor.subTask(tr("Preparing layer ''{0}'' for upload ...", layerInfo.getName()))); 563 564 // checkPreUploadConditions must not be run in the EDT to avoid deadlocks 565 if (!UploadAction.checkPreUploadConditions(layer)) { 566 GuiHelper.runInEDTAndWait(() -> model.setUploadState(layer, UploadOrSaveState.FAILED)); 567 continue; 568 } 569 570 GuiHelper.runInEDTAndWait(() -> uploadLayersUploadModelStateOnFinish(layer)); 571 currentTask = null; 572 } 573 } 574 575 /** 576 * Update the {@link #model} state on upload finish 577 * @param layer The layer that has been saved 578 */ 579 private void uploadLayersUploadModelStateOnFinish(AbstractModifiableLayer layer) { 580 AbstractUploadDialog dialog = layer.getUploadDialog(); 581 if (dialog != null) { 582 dialog.setVisible(true); 583 if (dialog.isCanceled()) { 559 584 model.setUploadState(layer, UploadOrSaveState.CANCELED); 560 continue; 561 } 562 monitor.subTask(tr("Preparing layer ''{0}'' for upload ...", layerInfo.getName())); 563 564 if (!UploadAction.checkPreUploadConditions(layer)) { 565 model.setUploadState(layer, UploadOrSaveState.FAILED); 566 continue; 567 } 568 569 AbstractUploadDialog dialog = layer.getUploadDialog(); 570 if (dialog != null) { 571 dialog.setVisible(true); 572 if (dialog.isCanceled()) { 573 model.setUploadState(layer, UploadOrSaveState.CANCELED); 574 continue; 575 } 576 dialog.rememberUserInput(); 577 } 578 579 currentTask = layer.createUploadTask(monitor); 580 if (currentTask == null) { 581 model.setUploadState(layer, UploadOrSaveState.FAILED); 582 continue; 583 } 584 Future<?> currentFuture = worker.submit(currentTask); 585 try { 586 // wait for the asynchronous task to complete 587 currentFuture.get(); 588 } catch (CancellationException e) { 589 Logging.trace(e); 590 model.setUploadState(layer, UploadOrSaveState.CANCELED); 591 } catch (InterruptedException | ExecutionException e) { 592 Logging.error(e); 593 model.setUploadState(layer, UploadOrSaveState.FAILED); 594 ExceptionDialogUtil.explainException(e); 595 } 596 if (currentTask.isCanceled()) { 597 model.setUploadState(layer, UploadOrSaveState.CANCELED); 598 } else if (currentTask.isFailed()) { 599 Logging.error(currentTask.getLastException()); 600 ExceptionDialogUtil.explainException(currentTask.getLastException()); 601 model.setUploadState(layer, UploadOrSaveState.FAILED); 602 } else { 603 model.setUploadState(layer, UploadOrSaveState.OK); 604 } 605 currentTask = null; 585 return; 586 } 587 dialog.rememberUserInput(); 588 } 589 590 currentTask = layer.createUploadTask(monitor); 591 if (currentTask == null) { 592 model.setUploadState(layer, UploadOrSaveState.FAILED); 593 return; 594 } 595 Future<?> currentFuture = worker.submit(currentTask); 596 try { 597 // wait for the asynchronous task to complete 598 currentFuture.get(); 599 } catch (CancellationException e) { 600 Logging.trace(e); 601 model.setUploadState(layer, UploadOrSaveState.CANCELED); 602 } catch (InterruptedException e) { 603 Thread.currentThread().interrupt(); 604 Logging.error(e); 605 model.setUploadState(layer, UploadOrSaveState.FAILED); 606 ExceptionDialogUtil.explainException(e); 607 } catch (ExecutionException e) { 608 Logging.error(e); 609 model.setUploadState(layer, UploadOrSaveState.FAILED); 610 ExceptionDialogUtil.explainException(e); 611 } 612 if (currentTask.isCanceled()) { 613 model.setUploadState(layer, UploadOrSaveState.CANCELED); 614 } else if (currentTask.isFailed()) { 615 Logging.error(currentTask.getLastException()); 616 ExceptionDialogUtil.explainException(currentTask.getLastException()); 617 model.setUploadState(layer, UploadOrSaveState.FAILED); 618 } else { 619 model.setUploadState(layer, UploadOrSaveState.OK); 606 620 } 607 621 } … … 673 687 @Override 674 688 public void run() { 689 GuiHelper.runInEDTAndWait(() -> model.setMode(SaveLayersModel.Mode.UPLOADING_AND_SAVING)); 690 // We very specifically do not want to block the EDT or the worker thread when validating 691 List<SaveLayerInfo> toUpload = model.getLayersToUpload(); 692 if (!toUpload.isEmpty()) { 693 uploadLayers(toUpload); 694 } 675 695 GuiHelper.runInEDTAndWait(() -> { 676 model.setMode(SaveLayersModel.Mode.UPLOADING_AND_SAVING);677 List<SaveLayerInfo> toUpload = model.getLayersToUpload();678 if (!toUpload.isEmpty()) {679 uploadLayers(toUpload);680 }681 696 List<SaveLayerInfo> toSave = model.getLayersToSave(); 682 697 if (!toSave.isEmpty()) {
Note:
See TracChangeset
for help on using the changeset viewer.