From 0ff6d7605c8b964a2bbb9d051b9db65f666734b0 Mon Sep 17 00:00:00 2001 From: Bertrik Sikken Date: Sat, 7 Sep 2024 01:02:46 +0200 Subject: [PATCH] Replace spotbugs by errorprone --- build.gradle | 9 +++- .../bertrik/cayenne/CayenneMessage.java | 45 +++++++++---------- .../sikken/bertrik/cayenne/ECayenneItem.java | 11 +++-- .../cayenne/ECayennePayloadFormat.java | 2 +- .../cayenne/formatter/GpsFormatter.java | 10 +++-- .../bertrik/cayenne/formatter/IFormatter.java | 3 ++ .../bertrik/cayenne/CayenneMessageTest.java | 2 - gradle/libs.versions.toml | 27 ++++++----- sensor-data-bridge/build.gradle | 2 - .../bertriksikken/gls/GeoLocationRequest.java | 3 ++ .../bertriksikken/gls/GeoLocationService.java | 1 - .../helium/HeliumUplinkMessage.java | 3 -- .../loraforwarder/CommandHandler.java | 35 +++++++-------- .../loraforwarder/SensorDataBridge.java | 3 +- .../ttn/enddevice/UpdateEndDeviceRequest.java | 1 + .../ttn/dto/TtnV3UplinkMessageTest.java | 13 ++---- 16 files changed, 83 insertions(+), 87 deletions(-) diff --git a/build.gradle b/build.gradle index 87e0923..08a6dd1 100644 --- a/build.gradle +++ b/build.gradle @@ -1,5 +1,5 @@ plugins { - alias libs.plugins.spotbugs + alias libs.plugins.errorprone alias libs.plugins.versions alias libs.plugins.dependencycheck alias libs.plugins.git.version @@ -18,7 +18,7 @@ dependencyCheck { subprojects { apply plugin: "java" apply plugin: "eclipse" - apply plugin: "com.github.spotbugs" + apply plugin: 'net.ltgt.errorprone' apply plugin: 'com.github.ben-manes.versions' java { @@ -39,8 +39,13 @@ subprojects { // Standard libraries added to all projects dependencies { + errorprone("com.google.errorprone:error_prone_core:2.31.0") + + annotationProcessor libs.errorprone.annotationprocessor + implementation libs.errorprone.annotations implementation libs.slf4j.api + testAnnotationProcessor libs.errorprone.annotationprocessor testImplementation libs.junit testImplementation libs.mockito.core } diff --git a/cayenne/src/main/java/nl/sikken/bertrik/cayenne/CayenneMessage.java b/cayenne/src/main/java/nl/sikken/bertrik/cayenne/CayenneMessage.java index deb09b2..1a7e3d7 100644 --- a/cayenne/src/main/java/nl/sikken/bertrik/cayenne/CayenneMessage.java +++ b/cayenne/src/main/java/nl/sikken/bertrik/cayenne/CayenneMessage.java @@ -25,18 +25,18 @@ public CayenneMessage() { */ public CayenneMessage(ECayennePayloadFormat format) { switch (format) { - case DYNAMIC_SENSOR_PAYLOAD: - case PACKED_SENSOR_PAYLOAD: - break; - default: - throw new IllegalArgumentException("Payload format not supported: " + format); + case DYNAMIC_SENSOR_PAYLOAD: + case PACKED_SENSOR_PAYLOAD: + break; + default: + throw new IllegalArgumentException("Payload format not supported: " + format); } this.format = format; } /** * Parses the byte array into a cayenne message. - * + * * @param data the raw data * @throws CayenneException in case of a parsing problem */ @@ -46,15 +46,15 @@ public void parse(byte[] data) throws CayenneException { while (bb.hasRemaining()) { CayenneItem item; switch (format) { - case DYNAMIC_SENSOR_PAYLOAD: - item = CayenneItem.parse(bb); - break; - case PACKED_SENSOR_PAYLOAD: - item = CayenneItem.parsePacked(bb, channel); - channel++; - break; - default: - throw new IllegalStateException("Unsupported cayenne payload: " + format); + case DYNAMIC_SENSOR_PAYLOAD: + item = CayenneItem.parse(bb); + break; + case PACKED_SENSOR_PAYLOAD: + item = CayenneItem.parsePacked(bb, channel); + channel++; + break; + default: + throw new IllegalStateException("Unsupported cayenne payload: " + format); } add(item); } @@ -62,7 +62,7 @@ public void parse(byte[] data) throws CayenneException { /** * Adds a cayenne measurement item to the message. - * + * * @param item the item to add */ public void add(CayenneItem item) { @@ -71,7 +71,7 @@ public void add(CayenneItem item) { /** * Encodes the cayenne message into a byte array. - * + * * @param maxSize the maximum size of the cayenne message * @return the byte array. * @throws CayenneException in case something went wrong during encoding (e.g. @@ -86,8 +86,7 @@ public byte[] encode(int maxSize) throws CayenneException { } /** - * @return an immutable list of measurement items in the order it appears in the - * raw data + * Returns a list of measurement items in the order it appears in the raw data */ public List getItems() { return List.copyOf(items); @@ -95,8 +94,8 @@ public List getItems() { /** * Finds an item by type and channel. - * - * @param type the desired type + * + * @param type the desired type * @param channel the desired channel * @return the item, or null if it does not exist */ @@ -106,7 +105,7 @@ public CayenneItem find(ECayenneItem type, int channel) { /** * Finds an item by type. - * + * * @param type the desired type * @return the item, or null if it does not exist */ @@ -116,7 +115,7 @@ public CayenneItem ofType(ECayenneItem type) { /** * Finds an item by channel. - * + * * @param channel the desired channel * @return the item, or null if it does not exist */ diff --git a/cayenne/src/main/java/nl/sikken/bertrik/cayenne/ECayenneItem.java b/cayenne/src/main/java/nl/sikken/bertrik/cayenne/ECayenneItem.java index a0b5382..9319e8c 100644 --- a/cayenne/src/main/java/nl/sikken/bertrik/cayenne/ECayenneItem.java +++ b/cayenne/src/main/java/nl/sikken/bertrik/cayenne/ECayenneItem.java @@ -1,15 +1,15 @@ package nl.sikken.bertrik.cayenne; -import java.nio.ByteBuffer; -import java.util.HashMap; -import java.util.Map; -import java.util.stream.Stream; - import nl.sikken.bertrik.cayenne.formatter.FloatFormatter; import nl.sikken.bertrik.cayenne.formatter.GpsFormatter; import nl.sikken.bertrik.cayenne.formatter.IFormatter; import nl.sikken.bertrik.cayenne.formatter.IntegerFormatter; +import java.nio.ByteBuffer; +import java.util.HashMap; +import java.util.Map; +import java.util.stream.Stream; + /** * Enumeration of possible Cayenne item types. */ @@ -53,7 +53,6 @@ public enum ECayenneItem { * * @param type the type code * @return the enum, or null if not found - * @throws CayenneException */ public static ECayenneItem parse(int type) throws CayenneException { ECayenneItem item = LOOKUP.get(type); diff --git a/cayenne/src/main/java/nl/sikken/bertrik/cayenne/ECayennePayloadFormat.java b/cayenne/src/main/java/nl/sikken/bertrik/cayenne/ECayennePayloadFormat.java index 1679e76..04e7dbe 100644 --- a/cayenne/src/main/java/nl/sikken/bertrik/cayenne/ECayennePayloadFormat.java +++ b/cayenne/src/main/java/nl/sikken/bertrik/cayenne/ECayennePayloadFormat.java @@ -16,7 +16,7 @@ public enum ECayennePayloadFormat { SENSOR_PERIOD_CONFIGURATION(13), // SENSOR_ENABLE_CONFIGURATION(14); // - private int port; + private final int port; ECayennePayloadFormat(int port) { this.port = port; diff --git a/cayenne/src/main/java/nl/sikken/bertrik/cayenne/formatter/GpsFormatter.java b/cayenne/src/main/java/nl/sikken/bertrik/cayenne/formatter/GpsFormatter.java index 350e611..256f96f 100644 --- a/cayenne/src/main/java/nl/sikken/bertrik/cayenne/formatter/GpsFormatter.java +++ b/cayenne/src/main/java/nl/sikken/bertrik/cayenne/formatter/GpsFormatter.java @@ -2,6 +2,7 @@ import java.nio.ByteBuffer; import java.util.Locale; +import java.util.stream.Stream; /** * Formatter for cayenne items which represent a GPS position. @@ -16,13 +17,14 @@ public Double[] parse(ByteBuffer bb) { double lat = LAT_LON_SCALE * getValue(bb, 3, true); double lon = LAT_LON_SCALE * getValue(bb, 3, true); double alt = ALT_SCALE * getValue(bb, 3, true); - return new Double[] { lat, lon, alt }; + return new Double[]{lat, lon, alt}; } @Override - public String[] format(Number[] values) { - return new String[] { String.format(Locale.ROOT, "%.4f", values[0]), - String.format(Locale.ROOT, "%.4f", values[1]), String.format(Locale.ROOT, "%.2f", values[2]) }; + public String[] format(Number[] numbers) { + double[] values = Stream.of(numbers).mapToDouble(Number::doubleValue).toArray(); + return new String[]{String.format(Locale.ROOT, "%.4f", values[0]), + String.format(Locale.ROOT, "%.4f", values[1]), String.format(Locale.ROOT, "%.2f", values[2])}; } @Override diff --git a/cayenne/src/main/java/nl/sikken/bertrik/cayenne/formatter/IFormatter.java b/cayenne/src/main/java/nl/sikken/bertrik/cayenne/formatter/IFormatter.java index 3ae8971..3918c6e 100644 --- a/cayenne/src/main/java/nl/sikken/bertrik/cayenne/formatter/IFormatter.java +++ b/cayenne/src/main/java/nl/sikken/bertrik/cayenne/formatter/IFormatter.java @@ -1,11 +1,14 @@ package nl.sikken.bertrik.cayenne.formatter; +import com.google.errorprone.annotations.Immutable; + import java.nio.ByteBuffer; /** * Interface for cayenne data structures that can be formatted as an array of * strings. */ +@Immutable public interface IFormatter { /** diff --git a/cayenne/src/test/java/nl/sikken/bertrik/cayenne/CayenneMessageTest.java b/cayenne/src/test/java/nl/sikken/bertrik/cayenne/CayenneMessageTest.java index c63168c..65c9f50 100644 --- a/cayenne/src/test/java/nl/sikken/bertrik/cayenne/CayenneMessageTest.java +++ b/cayenne/src/test/java/nl/sikken/bertrik/cayenne/CayenneMessageTest.java @@ -225,8 +225,6 @@ public void testDigitalInput() throws CayenneException { /** * Verifies encoding/decoding of a presence value (e.g. number of satellites) - * - * @throws CayenneException */ @Test public void testPresence() throws CayenneException { diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 587c60f..7935465 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -3,17 +3,17 @@ jackson = "2.17.2" jersey = "3.1.8" retrofit = "2.11.0" slf4j = "2.0.16" -spotbugs = "4.8.6" +errorprone = "2.31.0" [libraries] -slf4j-api = { module = "org.slf4j:slf4j-api", version.ref="slf4j" } -slf4j-reload4j = { module = "org.slf4j:slf4j-reload4j", version.ref="slf4j" } +errorprone_annotationprocessor = { module = "com.google.errorprone:error_prone_core:2.30.0", version.ref = "errorprone" } +errorprone_annotations = { module = "com.google.errorprone:error_prone_annotations:2.30.0", version.ref = "errorprone" } -jackson-databind = {module = "com.fasterxml.jackson.core:jackson-databind", version.ref="jackson" } -jackson-dataformat-yaml = {module = "com.fasterxml.jackson.dataformat:jackson-dataformat-yaml", version.ref="jackson" } +slf4j-api = { module = "org.slf4j:slf4j-api", version.ref = "slf4j" } +slf4j-reload4j = { module = "org.slf4j:slf4j-reload4j", version.ref = "slf4j" } -spotbugs = { module = "com.github.spotbugs:spotbugs", version.ref = "spotbugs" } -spotbugs-annotations = { module = "com.github.spotbugs:spotbugs-annotations", version.ref = "spotbugs" } +jackson-databind = { module = "com.fasterxml.jackson.core:jackson-databind", version.ref = "jackson" } +jackson-dataformat-yaml = { module = "com.fasterxml.jackson.dataformat:jackson-dataformat-yaml", version.ref = "jackson" } retrofit = { module = "com.squareup.retrofit2:retrofit", version.ref = "retrofit" } retrofit-converter-jackson = { module = "com.squareup.retrofit2:converter-jackson", version.ref = "retrofit" } @@ -26,12 +26,12 @@ paho-client-mqttv3 = "org.eclipse.paho:org.eclipse.paho.client.mqttv3:1.2.5" jakarta-ws-rs-api = "jakarta.ws.rs:jakarta.ws.rs-api:4.0.0" -jersey-jetty = { module = "org.glassfish.jersey.containers:jersey-container-jetty-http", version.ref="jersey" } -jersey-server = { module = "org.glassfish.jersey.core:jersey-server", version.ref="jersey" } -jersey-inject = { module = "org.glassfish.jersey.inject:jersey-hk2", version.ref="jersey" } -jersey-jackson = { module = "org.glassfish.jersey.media:jersey-media-json-jackson", version.ref="jersey" } +jersey-jetty = { module = "org.glassfish.jersey.containers:jersey-container-jetty-http", version.ref = "jersey" } +jersey-server = { module = "org.glassfish.jersey.core:jersey-server", version.ref = "jersey" } +jersey-inject = { module = "org.glassfish.jersey.inject:jersey-hk2", version.ref = "jersey" } +jersey-jackson = { module = "org.glassfish.jersey.media:jersey-media-json-jackson", version.ref = "jersey" } -mockito-core = "org.mockito:mockito-core:5.12.0" +mockito-core = "org.mockito:mockito-core:5.13.0" [bundles] jackson = ["jackson-databind", "jackson-dataformat-yaml"] @@ -39,9 +39,8 @@ retrofit = ["retrofit", "retrofit-converter-jackson", "retrofit-converter-scalar jersey = ["jakarta-ws-rs-api", "jersey-jetty", "jersey-server", "jersey-inject", "jersey-jackson"] [plugins] +errorprone = "net.ltgt.errorprone:4.0.1" versions = "com.github.ben-manes.versions:0.51.0" -spotbugs = "com.github.spotbugs:5.0.14" dependencycheck = "org.owasp.dependencycheck:8.4.3" -version-catalog-update = "nl.littlerobots.version-catalog-update:0.8.0" git-version = "com.palantir.git-version:3.1.0" diff --git a/sensor-data-bridge/build.gradle b/sensor-data-bridge/build.gradle index 5dda81f..7920d47 100644 --- a/sensor-data-bridge/build.gradle +++ b/sensor-data-bridge/build.gradle @@ -25,8 +25,6 @@ dependencies { // REST client implementation libs.bundles.retrofit - compileOnly libs.spotbugs.annotations - testImplementation libs.retrofit.mock } diff --git a/sensor-data-bridge/src/main/java/nl/bertriksikken/gls/GeoLocationRequest.java b/sensor-data-bridge/src/main/java/nl/bertriksikken/gls/GeoLocationRequest.java index b764886..72dfdbd 100644 --- a/sensor-data-bridge/src/main/java/nl/bertriksikken/gls/GeoLocationRequest.java +++ b/sensor-data-bridge/src/main/java/nl/bertriksikken/gls/GeoLocationRequest.java @@ -6,6 +6,7 @@ import com.fasterxml.jackson.annotation.JsonProperty; +@SuppressWarnings("UnusedVariable") public final class GeoLocationRequest { @JsonProperty("considerIp") @@ -19,6 +20,8 @@ public GeoLocationRequest(boolean considerIp) { } /** + * Adds an SSID. + * * @param mac the 6-byte mac address of the access point * @param signalStrength signal strength in dBm * @param channel the WiFi channel diff --git a/sensor-data-bridge/src/main/java/nl/bertriksikken/gls/GeoLocationService.java b/sensor-data-bridge/src/main/java/nl/bertriksikken/gls/GeoLocationService.java index 900ee06..bf18cbf 100644 --- a/sensor-data-bridge/src/main/java/nl/bertriksikken/gls/GeoLocationService.java +++ b/sensor-data-bridge/src/main/java/nl/bertriksikken/gls/GeoLocationService.java @@ -49,7 +49,6 @@ public static GeoLocationService create(GeoLocationConfig config) { * * @param request containing the WiFi AP information * @return the response with the result - * @throws IOException */ public GeoLocationResponse geoLocate(GeoLocationRequest request) throws IOException { Response response = restClient.geoLocate(key, request).execute(); diff --git a/sensor-data-bridge/src/main/java/nl/bertriksikken/helium/HeliumUplinkMessage.java b/sensor-data-bridge/src/main/java/nl/bertriksikken/helium/HeliumUplinkMessage.java index 52f96c6..a8b92dd 100644 --- a/sensor-data-bridge/src/main/java/nl/bertriksikken/helium/HeliumUplinkMessage.java +++ b/sensor-data-bridge/src/main/java/nl/bertriksikken/helium/HeliumUplinkMessage.java @@ -6,9 +6,6 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; -import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; - -@SuppressFBWarnings("URF_UNREAD_FIELD") @JsonIgnoreProperties(ignoreUnknown = true) public final class HeliumUplinkMessage { diff --git a/sensor-data-bridge/src/main/java/nl/bertriksikken/loraforwarder/CommandHandler.java b/sensor-data-bridge/src/main/java/nl/bertriksikken/loraforwarder/CommandHandler.java index 9f4dc31..8aed03d 100644 --- a/sensor-data-bridge/src/main/java/nl/bertriksikken/loraforwarder/CommandHandler.java +++ b/sensor-data-bridge/src/main/java/nl/bertriksikken/loraforwarder/CommandHandler.java @@ -1,15 +1,5 @@ package nl.bertriksikken.loraforwarder; -import java.io.IOException; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.util.Arrays; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import nl.bertriksikken.gls.GeoLocationRequest; import nl.bertriksikken.gls.GeoLocationResponse; import nl.bertriksikken.gls.GeoLocationService; @@ -18,6 +8,15 @@ import nl.bertriksikken.ttn.enddevice.EndDevice; import nl.bertriksikken.ttn.enddevice.EndDeviceRegistry; import nl.bertriksikken.ttn.enddevice.Location; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.util.List; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; /** * Handles commands and response from LoRaWAN devices. @@ -47,20 +46,18 @@ public void stop() { /** * Test message on port 100: 00 9C 1C 12 F6 EB C0 D3 01 9C 1C 12 F6 F5 42 C9 01 - * - * @param uplink */ void processResponse(TtnUplinkMessage uplink) { ByteBuffer bb = ByteBuffer.wrap(uplink.getRawPayload()).order(ByteOrder.BIG_ENDIAN); int cmd = bb.get() & 0xFF; switch (cmd) { - case 0: - executor.execute(new CatchingRunnable(LOG, () -> handleWifiLocalisation(bb, uplink.getDevId()))); - break; - default: - LOG.warn("Unhandled command {}", cmd); - break; + case 0: + executor.execute(new CatchingRunnable(LOG, () -> handleWifiLocalisation(bb, uplink.getDevId()))); + break; + default: + LOG.warn("Unhandled command {}", cmd); + break; } } @@ -80,7 +77,7 @@ void handleWifiLocalisation(ByteBuffer bb, String devId) { EndDevice endDevice = endDeviceRegistry.buildEndDevice(devId); Location location = new Location(response.getLatitude(), response.getLongitude()); endDevice.setLocation(EndDevice.LOCATION_USER, location); - endDeviceRegistry.updateEndDevice(endDevice, Arrays.asList("locations")); + endDeviceRegistry.updateEndDevice(endDevice, List.of("locations")); } } catch (IOException e) { LOG.warn("Caught IOException", e); diff --git a/sensor-data-bridge/src/main/java/nl/bertriksikken/loraforwarder/SensorDataBridge.java b/sensor-data-bridge/src/main/java/nl/bertriksikken/loraforwarder/SensorDataBridge.java index 647ad17..762fc95 100644 --- a/sensor-data-bridge/src/main/java/nl/bertriksikken/loraforwarder/SensorDataBridge.java +++ b/sensor-data-bridge/src/main/java/nl/bertriksikken/loraforwarder/SensorDataBridge.java @@ -207,6 +207,7 @@ SensorData decodeTtnMessage(DecoderConfig config, TtnUplinkMessage uplink) throw * * @throws MqttException in case of a problem starting MQTT client */ + @SuppressWarnings("FutureReturnValueIgnored") private void start() throws MqttException { LOG.info("Starting sensor-data-bridge application"); @@ -235,7 +236,7 @@ private void updateAttributes() { try { for (EndDevice device : registry.listEndDevices(IEndDeviceRegistryRestApi.FIELD_IDS, IEndDeviceRegistryRestApi.FIELD_ATTRIBUTES)) { - map.put(device.getDeviceId(), new AttributeMap((device.getAttributes()))); + map.put(device.getDeviceId(), new AttributeMap(device.getAttributes())); } } catch (IOException e) { LOG.warn("Error getting attributes for {}", applicationId, e); diff --git a/sensor-data-bridge/src/main/java/nl/bertriksikken/ttn/enddevice/UpdateEndDeviceRequest.java b/sensor-data-bridge/src/main/java/nl/bertriksikken/ttn/enddevice/UpdateEndDeviceRequest.java index aa86cb6..1470cac 100644 --- a/sensor-data-bridge/src/main/java/nl/bertriksikken/ttn/enddevice/UpdateEndDeviceRequest.java +++ b/sensor-data-bridge/src/main/java/nl/bertriksikken/ttn/enddevice/UpdateEndDeviceRequest.java @@ -5,6 +5,7 @@ /** * https://www.thethingsindustries.com/docs/reference/api/end_device/#message:UpdateEndDeviceRequest */ +@SuppressWarnings("UnusedVariable") public final class UpdateEndDeviceRequest { @JsonProperty("end_device") diff --git a/sensor-data-bridge/src/test/java/nl/bertriksikken/ttn/dto/TtnV3UplinkMessageTest.java b/sensor-data-bridge/src/test/java/nl/bertriksikken/ttn/dto/TtnV3UplinkMessageTest.java index 8d7b052..77ff9ae 100644 --- a/sensor-data-bridge/src/test/java/nl/bertriksikken/ttn/dto/TtnV3UplinkMessageTest.java +++ b/sensor-data-bridge/src/test/java/nl/bertriksikken/ttn/dto/TtnV3UplinkMessageTest.java @@ -1,15 +1,12 @@ package nl.bertriksikken.ttn.dto; -import java.io.IOException; -import java.io.InputStream; - -import nl.bertriksikken.ttn.dto.Ttnv3UplinkMessage; +import com.fasterxml.jackson.databind.ObjectMapper; +import nl.bertriksikken.ttn.TtnUplinkMessage; import org.junit.Assert; import org.junit.Test; -import com.fasterxml.jackson.databind.ObjectMapper; - -import nl.bertriksikken.ttn.TtnUplinkMessage; +import java.io.IOException; +import java.io.InputStream; /** * Unit tests related to TTN messages. @@ -18,8 +15,6 @@ public final class TtnV3UplinkMessageTest { /** * Reads an example message and verifies parsing. - * - * @throws IOException */ @Test public void testDecode() throws IOException {