diff --git a/src/org/openstreetmap/josm/data/imagery/CachedAttributionBingAerialTileSource.java b/src/org/openstreetmap/josm/data/imagery/CachedAttributionBingAerialTileSource.java index 6b21c8bacb7..1dbeb3e66e3 100644 --- a/src/org/openstreetmap/josm/data/imagery/CachedAttributionBingAerialTileSource.java +++ b/src/org/openstreetmap/josm/data/imagery/CachedAttributionBingAerialTileSource.java @@ -9,10 +9,12 @@ import java.net.URL; import java.nio.charset.StandardCharsets; import java.util.List; +import java.util.Objects; import java.util.Timer; import java.util.TimerTask; import java.util.concurrent.Callable; -import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicReference; import org.openstreetmap.gui.jmapviewer.tilesources.BingAerialTileSource; @@ -88,19 +90,20 @@ protected boolean isOffline() { @Override protected Callable> getAttributionLoaderCallable() { final AtomicReference> attributions = new AtomicReference<>(); - final AtomicBoolean finished = new AtomicBoolean(); + final CountDownLatch finished = new CountDownLatch(1); return () -> { final PleaseWaitProgressMonitor monitor = new PleaseWaitProgressMonitor(); monitor.beginTask(tr("Attempting to fetch Bing attribution information"), ProgressMonitor.ALL_TICKS); final Timer timer = new Timer(Thread.currentThread().getName() + "-timer", true); timer.schedule(new AttributionTimerTask(monitor, timer, 1, attributions, finished), 0); - synchronized (finished) { - while (!finished.get() && !monitor.isCanceled()) { - finished.wait(1000); + try { + while (!monitor.isCanceled() && !finished.await(1, TimeUnit.SECONDS)) { + // Do nothing; we are waiting on the CountDownLatch to hit zero. } + } finally { + monitor.finishTask(); + monitor.close(); } - monitor.finishTask(); - monitor.close(); return attributions.get(); }; } @@ -113,7 +116,7 @@ private class AttributionTimerTask extends TimerTask { private final Timer timer; private final int waitTimeSec; private final AtomicReference> attributions; - private final AtomicBoolean finished; + private final CountDownLatch finished; /** * Create a new task for fetching Bing attribution data @@ -124,7 +127,7 @@ private class AttributionTimerTask extends TimerTask { * @param finished Set to {@code true} when we have successfully fetched attributions or fetching has been cancelled. */ AttributionTimerTask(ProgressMonitor monitor, Timer timer, int waitTimeSec, - AtomicReference> attributions, AtomicBoolean finished) { + AtomicReference> attributions, CountDownLatch finished) { this.monitor = monitor; this.timer = timer; this.waitTimeSec = waitTimeSec; @@ -137,6 +140,7 @@ public void run() { BingAttributionData attributionLoader = new BingAttributionData(); try { String xml = attributionLoader.updateIfRequiredString(); + Objects.requireNonNull(xml); List ret; try (StringReader sr = new StringReader(xml)) { ret = parseAttributionText(new InputSource(sr)); @@ -146,12 +150,12 @@ public void run() { attributionDownloadedTask = null; } this.attributions.set(ret); - this.finished.set(true); + this.finished.countDown(); } catch (IOException ex) { final String message = tr("Could not connect to Bing API. Will retry in {0} seconds.", waitTimeSec); Logging.log(Logging.LEVEL_WARN, message, ex); if (this.monitor.isCanceled()) { - this.finished.set(true); + this.finished.countDown(); return; } this.monitor.setCustomText(message); @@ -159,10 +163,6 @@ public void run() { final int newWaitTimeSec = 2 * this.waitTimeSec; this.timer.schedule(new AttributionTimerTask(this.monitor, this.timer, newWaitTimeSec, this.attributions, this.finished), newWaitTimeSec * 1000L); - } finally { - synchronized (this.finished) { - this.finished.notifyAll(); - } } } } diff --git a/src/org/openstreetmap/josm/data/osm/visitor/paint/StyledTiledMapRenderer.java b/src/org/openstreetmap/josm/data/osm/visitor/paint/StyledTiledMapRenderer.java index b230cfe7a4b..1508e021297 100644 --- a/src/org/openstreetmap/josm/data/osm/visitor/paint/StyledTiledMapRenderer.java +++ b/src/org/openstreetmap/josm/data/osm/visitor/paint/StyledTiledMapRenderer.java @@ -250,8 +250,8 @@ public int getHeight() { temporaryView.zoomTo(bounds.getCenter().getEastNorth(ProjectionRegistry.getProjection()), mapState.getScale()); BufferedImage bufferedImage = Optional.ofNullable(nc.getGraphicsConfiguration()) - .map(gc -> gc.createCompatibleImage(tileSize * xCount + xCount, tileSize * yCount + xCount, Transparency.TRANSLUCENT)) - .orElseGet(() -> new BufferedImage(tileSize * xCount + xCount, tileSize * yCount + xCount, BufferedImage.TYPE_INT_ARGB)); + .map(gc -> gc.createCompatibleImage(tileSize * xCount + xCount, tileSize * yCount + yCount, Transparency.TRANSLUCENT)) + .orElseGet(() -> new BufferedImage(tileSize * xCount + xCount, tileSize * yCount + yCount, BufferedImage.TYPE_INT_ARGB)); Graphics2D g2d = bufferedImage.createGraphics(); try { g2d.setRenderingHints(Map.of(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON)); @@ -334,7 +334,7 @@ public void run() { * Finish a tile generation job * @param tImage The tile image for this job */ - private synchronized void cacheTile(BufferedImage tImage) { + private void cacheTile(BufferedImage tImage) { cache.put(tile, new ImageCache(tImage, null, false)); done = true; notifier.accept(tile); diff --git a/src/org/openstreetmap/josm/gui/layer/OsmDataLayer.java b/src/org/openstreetmap/josm/gui/layer/OsmDataLayer.java index 56de4532133..0bcf27b6c62 100644 --- a/src/org/openstreetmap/josm/gui/layer/OsmDataLayer.java +++ b/src/org/openstreetmap/josm/gui/layer/OsmDataLayer.java @@ -1341,6 +1341,7 @@ private static int getZoom(NavigatableComponent navigatableComponent) { // We might have to fall back to the old method if user is reprojecting // 256 is the "target" size, (TODO check HiDPI!) final int targetSize = Config.getPref().getInt("mappaint.fast_render.tile_size", 256); + CheckParameterUtil.ensureThat(targetSize > 0, "mappaint.fast_render.tile_size should be > 0 (default 256)"); final double topResolution = 2 * Math.PI * OsmMercator.EARTH_RADIUS / targetSize; int zoom; for (zoom = 0; zoom < MAX_ZOOM; zoom++) { // Use something like imagery.{generic|tms}.max_zoom_lvl (20 is a bit too low for our needs)