diff --git a/src/main/java/org/openstreetmap/josm/plugins/mapwithai/backend/MapWithAILayer.java b/src/main/java/org/openstreetmap/josm/plugins/mapwithai/backend/MapWithAILayer.java
index ff6891d..9c380fd 100644
--- a/src/main/java/org/openstreetmap/josm/plugins/mapwithai/backend/MapWithAILayer.java
+++ b/src/main/java/org/openstreetmap/josm/plugins/mapwithai/backend/MapWithAILayer.java
@@ -26,6 +26,7 @@ import javax.swing.Action;
import javax.swing.Icon;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JLabel;
+import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.SwingConstants;
@@ -38,6 +39,7 @@ import org.openstreetmap.josm.data.osm.OsmPrimitive;
import org.openstreetmap.josm.data.osm.UploadPolicy;
import org.openstreetmap.josm.data.osm.Way;
import org.openstreetmap.josm.gui.MainApplication;
+import org.openstreetmap.josm.gui.Notification;
import org.openstreetmap.josm.gui.layer.Layer;
import org.openstreetmap.josm.gui.layer.MainLayerManager.ActiveLayerChangeEvent;
import org.openstreetmap.josm.gui.layer.MainLayerManager.ActiveLayerChangeListener;
@@ -45,8 +47,10 @@ import org.openstreetmap.josm.gui.layer.OsmDataLayer;
import org.openstreetmap.josm.gui.mappaint.MapPaintStyles;
import org.openstreetmap.josm.gui.mappaint.StyleSource;
import org.openstreetmap.josm.gui.util.GuiHelper;
+import org.openstreetmap.josm.gui.widgets.HtmlPanel;
import org.openstreetmap.josm.plugins.mapwithai.MapWithAIPlugin;
import org.openstreetmap.josm.plugins.mapwithai.data.mapwithai.MapWithAIInfo;
+import org.openstreetmap.josm.plugins.mapwithai.tools.BlacklistUtils;
import org.openstreetmap.josm.plugins.mapwithai.tools.MapPaintUtils;
import org.openstreetmap.josm.spi.preferences.Config;
import org.openstreetmap.josm.tools.GBC;
@@ -227,6 +231,13 @@ public class MapWithAILayer extends OsmDataLayer implements ActiveLayerChangeLis
@Override
public void selectionChanged(SelectionChangeEvent event) {
+ if (BlacklistUtils.isBlacklisted()) {
+ if (!event.getSelection().isEmpty()) {
+ GuiHelper.runInEDT(() -> getDataSet().setSelected(Collections.emptySet()));
+ createBadDataNotification();
+ }
+ return;
+ }
super.selectionChanged(event);
final int maximumAdditionSelection = MapWithAIPreferenceHelper.getMaximumAddition();
if ((event.getSelection().size() - event.getOldSelection().size() > 1
@@ -248,6 +259,29 @@ public class MapWithAILayer extends OsmDataLayer implements ActiveLayerChangeLis
}
}
+ /**
+ * Create a notification for plugin versions that create bad data.
+ */
+ public static void createBadDataNotification() {
+ Notification badData = new Notification();
+ badData.setIcon(JOptionPane.ERROR_MESSAGE);
+ badData.setDuration(Notification.TIME_LONG);
+ HtmlPanel panel = new HtmlPanel();
+ StringBuilder message = new StringBuilder()
+ .append(tr("This version of the MapWithAI plugin is known to create bad data.")).append("
")
+ .append(tr("Please update plugins and/or JOSM."));
+ if (BlacklistUtils.isOffline()) {
+ message.append("
").append(tr("This message may occur when JOSM is offline."));
+ }
+ panel.setText(message.toString());
+ badData.setContent(panel);
+ MapWithAILayer layer = MapWithAIDataUtils.getLayer(false);
+ if (layer != null) {
+ layer.setMaximumAddition(0);
+ }
+ GuiHelper.runInEDT(badData::show);
+ }
+
private static class OsmComparator implements Comparator, Serializable {
final Collection previousSelection;
diff --git a/src/main/java/org/openstreetmap/josm/plugins/mapwithai/backend/MapWithAIMoveAction.java b/src/main/java/org/openstreetmap/josm/plugins/mapwithai/backend/MapWithAIMoveAction.java
index 0b7c7cb..8bc8afd 100644
--- a/src/main/java/org/openstreetmap/josm/plugins/mapwithai/backend/MapWithAIMoveAction.java
+++ b/src/main/java/org/openstreetmap/josm/plugins/mapwithai/backend/MapWithAIMoveAction.java
@@ -27,6 +27,7 @@ import org.openstreetmap.josm.gui.layer.OsmDataLayer;
import org.openstreetmap.josm.gui.util.GuiHelper;
import org.openstreetmap.josm.plugins.mapwithai.MapWithAIPlugin;
import org.openstreetmap.josm.plugins.mapwithai.commands.MapWithAIAddCommand;
+import org.openstreetmap.josm.plugins.mapwithai.tools.BlacklistUtils;
import org.openstreetmap.josm.tools.Shortcut;
public class MapWithAIMoveAction extends JosmAction {
@@ -63,6 +64,10 @@ public class MapWithAIMoveAction extends JosmAction {
@Override
public void actionPerformed(ActionEvent event) {
+ if (BlacklistUtils.isBlacklisted()) {
+ MapWithAILayer.createBadDataNotification();
+ return;
+ }
for (final MapWithAILayer mapWithAI : MainApplication.getLayerManager().getLayersOfType(MapWithAILayer.class)) {
final DataSet ds = mapWithAI.getDataSet();
final int maxAddition = MapWithAIPreferenceHelper.getMaximumAddition();
diff --git a/src/main/java/org/openstreetmap/josm/plugins/mapwithai/tools/BlacklistUtils.java b/src/main/java/org/openstreetmap/josm/plugins/mapwithai/tools/BlacklistUtils.java
index 4e6bef6..a632637 100644
--- a/src/main/java/org/openstreetmap/josm/plugins/mapwithai/tools/BlacklistUtils.java
+++ b/src/main/java/org/openstreetmap/josm/plugins/mapwithai/tools/BlacklistUtils.java
@@ -14,6 +14,7 @@ import javax.json.JsonStructure;
import javax.json.JsonValue;
import org.openstreetmap.josm.io.CachedFile;
+import org.openstreetmap.josm.io.NetworkManager;
import org.openstreetmap.josm.plugins.mapwithai.MapWithAIPlugin;
import org.openstreetmap.josm.tools.Logging;
@@ -39,8 +40,8 @@ public class BlacklistUtils {
*/
public static boolean isBlacklisted() {
String version = MapWithAIPlugin.getVersionInfo();
- try (CachedFile blacklist = new CachedFile(blacklistUrl);
- BufferedReader bufferedReader = blacklist.getContentReader();
+ CachedFile blacklist = new CachedFile(blacklistUrl);
+ try (BufferedReader bufferedReader = blacklist.getContentReader();
JsonReader reader = Json.createReader(bufferedReader)) {
JsonStructure structure = reader.read();
if (structure.getValueType() == JsonValue.ValueType.ARRAY) {
@@ -52,7 +53,14 @@ public class BlacklistUtils {
return object.keySet().contains(version);
}
} catch (IOException | JsonException e) {
+ try {
+ blacklist.clear();
+ } catch (IOException e1) {
+ Logging.error(e1);
+ }
Logging.error(e);
+ } finally {
+ blacklist.close();
}
return true;
}
@@ -65,4 +73,13 @@ public class BlacklistUtils {
static void setBlacklistUrl(String url) {
blacklistUrl = url;
}
+
+ /**
+ * Check if we can reach the URL for the known-bad version list.
+ *
+ * @return {@code true} if the configured url is offline
+ */
+ public static boolean isOffline() {
+ return NetworkManager.isOffline(blacklistUrl);
+ }
}
diff --git a/test/unit/org/openstreetmap/josm/plugins/mapwithai/backend/MapWithAILayerTest.java b/test/unit/org/openstreetmap/josm/plugins/mapwithai/backend/MapWithAILayerTest.java
index cebd79f..fa937aa 100644
--- a/test/unit/org/openstreetmap/josm/plugins/mapwithai/backend/MapWithAILayerTest.java
+++ b/test/unit/org/openstreetmap/josm/plugins/mapwithai/backend/MapWithAILayerTest.java
@@ -22,6 +22,7 @@ import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import org.awaitility.Durations;
+import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;
@@ -42,6 +43,7 @@ import org.openstreetmap.josm.plugins.mapwithai.MapWithAIPlugin;
import org.openstreetmap.josm.plugins.mapwithai.backend.MapWithAILayer.ContinuousDownloadAction;
import org.openstreetmap.josm.plugins.mapwithai.commands.MapWithAIAddCommand;
import org.openstreetmap.josm.plugins.mapwithai.data.mapwithai.MapWithAIInfo;
+import org.openstreetmap.josm.plugins.mapwithai.testutils.MapWithAIPluginMock;
import org.openstreetmap.josm.plugins.mapwithai.testutils.MapWithAITestRules;
import org.openstreetmap.josm.plugins.mapwithai.tools.MapPaintUtils;
import org.openstreetmap.josm.spi.preferences.Config;
@@ -57,17 +59,23 @@ import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
class MapWithAILayerTest {
@RegisterExtension
@SuppressFBWarnings("URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD")
- JOSMTestRules test = new MapWithAITestRules().sources().wiremock().preferences().main().projection().fakeAPI()
- .territories();
+ static JOSMTestRules test = new MapWithAITestRules().sources().wiremock().preferences().main().projection()
+ .fakeAPI().territories();
MapWithAILayer layer;
- @BeforeEach
- void setUp() {
- layer = new MapWithAILayer(new DataSet(), "test", null);
+ @BeforeAll
+ static void beforeAll() {
+ TestUtils.assumeWorkingJMockit();
+ new MapWithAIPluginMock();
Territories.initialize(); // Required to avoid an NPE (see JOSM-19132)
}
+ @BeforeEach
+ void beforeEach() {
+ layer = new MapWithAILayer(new DataSet(), "test", null);
+ }
+
@Test
void testGetSource() {
assertNull(layer.getChangesetSourceTag(), "The source tag should be null");
diff --git a/test/unit/org/openstreetmap/josm/plugins/mapwithai/backend/MapWithAIMoveActionTest.java b/test/unit/org/openstreetmap/josm/plugins/mapwithai/backend/MapWithAIMoveActionTest.java
index f41f25c..f165cd7 100644
--- a/test/unit/org/openstreetmap/josm/plugins/mapwithai/backend/MapWithAIMoveActionTest.java
+++ b/test/unit/org/openstreetmap/josm/plugins/mapwithai/backend/MapWithAIMoveActionTest.java
@@ -13,6 +13,7 @@ import java.util.concurrent.Future;
import org.awaitility.Awaitility;
import org.awaitility.Durations;
+import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;
@@ -28,6 +29,7 @@ import org.openstreetmap.josm.gui.layer.OsmDataLayer;
import org.openstreetmap.josm.gui.util.GuiHelper;
import org.openstreetmap.josm.plugins.mapwithai.commands.ConnectedCommand;
import org.openstreetmap.josm.plugins.mapwithai.commands.DuplicateCommand;
+import org.openstreetmap.josm.plugins.mapwithai.testutils.MapWithAIPluginMock;
import org.openstreetmap.josm.plugins.mapwithai.testutils.MapWithAITestRules;
import org.openstreetmap.josm.plugins.mapwithai.testutils.MissingConnectionTagsMocker;
import org.openstreetmap.josm.spi.preferences.Config;
@@ -49,9 +51,14 @@ class MapWithAIMoveActionTest {
@RegisterExtension
@SuppressFBWarnings("URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD")
- JOSMTestRules test = new MapWithAITestRules().wiremock().preferences().main().projection().territories()
+ static JOSMTestRules test = new MapWithAITestRules().wiremock().preferences().main().projection().territories()
.assertionsInEDT();
+ @BeforeAll
+ static void beforeAll() {
+ new MapWithAIPluginMock();
+ }
+
@BeforeEach
void setUp() {
moveAction = new MapWithAIMoveAction();
diff --git a/test/unit/org/openstreetmap/josm/plugins/mapwithai/backend/MapWithAIUploadHookTest.java b/test/unit/org/openstreetmap/josm/plugins/mapwithai/backend/MapWithAIUploadHookTest.java
index 57b8791..eec5c44 100644
--- a/test/unit/org/openstreetmap/josm/plugins/mapwithai/backend/MapWithAIUploadHookTest.java
+++ b/test/unit/org/openstreetmap/josm/plugins/mapwithai/backend/MapWithAIUploadHookTest.java
@@ -14,6 +14,7 @@ import java.util.Map;
import java.util.TreeMap;
import java.util.stream.Collectors;
+import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;
@@ -30,6 +31,7 @@ import org.openstreetmap.josm.plugins.PluginException;
import org.openstreetmap.josm.plugins.PluginInformation;
import org.openstreetmap.josm.plugins.mapwithai.data.mapwithai.MapWithAIInfo;
import org.openstreetmap.josm.plugins.mapwithai.data.mapwithai.MapWithAILayerInfo;
+import org.openstreetmap.josm.plugins.mapwithai.testutils.MapWithAIPluginMock;
import org.openstreetmap.josm.plugins.mapwithai.testutils.MapWithAITestRules;
import org.openstreetmap.josm.testutils.JOSMTestRules;
@@ -42,7 +44,8 @@ import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
class MapWithAIUploadHookTest {
@RegisterExtension
@SuppressFBWarnings("URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD")
- JOSMTestRules test = new MapWithAITestRules().sources().wiremock().main().projection().preferences().territories();
+ static JOSMTestRules test = new MapWithAITestRules().sources().wiremock().main().projection().preferences()
+ .territories();
private PluginInformation info;
private OsmDataLayer osmLayer;
private MapWithAILayer aiLayer;
@@ -51,6 +54,11 @@ class MapWithAIUploadHookTest {
private MapWithAIMoveAction action;
private MapWithAIUploadHook hook;
+ @BeforeAll
+ static void beforeAll() {
+ new MapWithAIPluginMock();
+ }
+
@BeforeEach
void setUp() throws PluginException, IOException {
try (InputStream in = new ByteArrayInputStream("".getBytes(StandardCharsets.UTF_8))) {
diff --git a/test/unit/org/openstreetmap/josm/plugins/mapwithai/testutils/MapWithAIPluginMock.java b/test/unit/org/openstreetmap/josm/plugins/mapwithai/testutils/MapWithAIPluginMock.java
new file mode 100644
index 0000000..fc97c7e
--- /dev/null
+++ b/test/unit/org/openstreetmap/josm/plugins/mapwithai/testutils/MapWithAIPluginMock.java
@@ -0,0 +1,14 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.plugins.mapwithai.testutils;
+
+import org.openstreetmap.josm.plugins.mapwithai.MapWithAIPlugin;
+
+import mockit.Mock;
+import mockit.MockUp;
+
+public class MapWithAIPluginMock extends MockUp {
+ @Mock
+ public static String getVersionInfo() {
+ return "1.0";
+ }
+}
diff --git a/test/unit/org/openstreetmap/josm/plugins/mapwithai/tools/BlacklistUtilsTest.java b/test/unit/org/openstreetmap/josm/plugins/mapwithai/tools/BlacklistUtilsTest.java
index 9aa28c2..2f2aff5 100644
--- a/test/unit/org/openstreetmap/josm/plugins/mapwithai/tools/BlacklistUtilsTest.java
+++ b/test/unit/org/openstreetmap/josm/plugins/mapwithai/tools/BlacklistUtilsTest.java
@@ -15,14 +15,13 @@ import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;
+import org.openstreetmap.josm.TestUtils;
import org.openstreetmap.josm.plugins.mapwithai.MapWithAIPlugin;
+import org.openstreetmap.josm.plugins.mapwithai.testutils.MapWithAIPluginMock;
import org.openstreetmap.josm.testutils.JOSMTestRules;
import com.github.tomakehurst.wiremock.WireMockServer;
-import mockit.Mock;
-import mockit.MockUp;
-
/**
* Tests for {@link BlacklistUtils}
*
@@ -31,13 +30,6 @@ import mockit.MockUp;
*/
class BlacklistUtilsTest {
- private static class MapWithAIPluginMock extends MockUp {
- @Mock
- public static String getVersionInfo() {
- return "1.0";
- }
- }
-
@RegisterExtension
static JOSMTestRules rules = new JOSMTestRules();
@@ -45,6 +37,7 @@ class BlacklistUtilsTest {
@BeforeAll
static void setup() {
+ TestUtils.assumeWorkingJMockit();
wireMock = new WireMockServer(options().dynamicPort());
wireMock.start();
BlacklistUtils.setBlacklistUrl(wireMock.baseUrl() + "/JOSM_MapWithAI/json/blacklisted_versions.json");