From f6bd3a65abec38402bbb742377c22e17fa077527 Mon Sep 17 00:00:00 2001 From: J-N-K Date: Thu, 25 Mar 2021 17:26:45 +0100 Subject: [PATCH] [infrastructure] improve null-analysis (#46) * improve null-analysis - upgrade EEA - make null-analysis more strict - fix null errors Signed-off-by: Jan N. Klug --- .../internal/Connection.java | 7 ++- .../internal/AndroidDebugBridgeDevice.java | 7 ++- .../internal/netutils/AsyncHttpClient.java | 5 +- .../dmx/internal/DmxBridgeHandler.java | 3 +- .../binding/dmx/internal/ValueSet.java | 4 +- .../dmx/internal/action/FadeAction.java | 3 +- .../dmx/internal/dmxoverethernet/IpNode.java | 3 +- .../internal/handler/Lib485BridgeHandler.java | 2 +- .../internal/multiverse/BaseDmxChannel.java | 16 +++--- .../dmx/test/AbstractDmxThingTestParent.java | 2 + .../http/internal/HttpThingHandler.java | 5 +- .../internal/http/HttpResponseListener.java | 2 +- .../internal/handler/RoombaHandlerTest.java | 15 ++--- .../internal/client/AbstractKNXClient.java | 5 +- .../knx/internal/client/DeviceInspector.java | 20 +++++-- .../knx/internal/client/ReadDatapoint.java | 4 +- .../handler/AbstractKNXThingHandler.java | 3 +- .../internal/handler/DeviceThingHandler.java | 4 +- .../knx/internal/handler/Firmware.java | 12 ++-- .../handler/SerialBridgeThingHandler.java | 6 +- .../internal/channel/KNXChannelTypeTest.java | 32 +++++++++++ .../mail/internal/POP3IMAPHandler.java | 7 +-- .../binding/mail/internal/SMTPHandler.java | 8 ++- .../binding/onewire/internal/Util.java | 7 ++- .../AdvancedMultisensorThingHandler.java | 14 ++--- .../internal/handler/OwBaseThingHandler.java | 4 +- .../internal/owserver/OwserverConnection.java | 2 +- .../snmp/internal/SnmpTargetHandlerTest.java | 29 ++++++++-- .../snmp/internal/StringChannelTest.java | 22 ++++++-- .../snmp/internal/SwitchChannelTest.java | 14 ++++- .../internal/Tr064CommunicationException.java | 7 ++- .../tr064/internal/Tr064RootHandler.java | 33 ++++++----- .../tr064/internal/Tr064SubHandler.java | 3 +- .../internal/phonebook/PhonebookActions.java | 8 +-- .../internal/phonebook/PhonebookProfile.java | 3 +- .../influxdb/internal/InfluxPoint.java | 3 +- .../influx2/InfluxDB2RepositoryImpl.java | 12 ++-- .../internal/ItemToStorePointCreatorTest.java | 55 ++++++++++++++++++- pom.xml | 7 +-- tools/org.eclipse.jdt.core.prefs | 25 +++++++++ 40 files changed, 306 insertions(+), 117 deletions(-) create mode 100644 tools/org.eclipse.jdt.core.prefs diff --git a/bundles/org.smarthomej.binding.amazonechocontrol/src/main/java/org/smarthomej/binding/amazonechocontrol/internal/Connection.java b/bundles/org.smarthomej.binding.amazonechocontrol/src/main/java/org/smarthomej/binding/amazonechocontrol/internal/Connection.java index 940cd402ec..67e294edf3 100644 --- a/bundles/org.smarthomej.binding.amazonechocontrol/src/main/java/org/smarthomej/binding/amazonechocontrol/internal/Connection.java +++ b/bundles/org.smarthomej.binding.amazonechocontrol/src/main/java/org/smarthomej/binding/amazonechocontrol/internal/Connection.java @@ -1592,7 +1592,6 @@ private void executeSequenceNode(List devices, JsonObject nodeToExecute) logger.debug("added {} device {}", queueObject.hashCode(), serialNumbers); } - @SuppressWarnings("null") // peek can return null private void handleExecuteSequenceNode() { Lock lock = Objects.requireNonNull(locks.computeIfAbsent(TimerType.DEVICES, k -> new ReentrantLock())); if (lock.tryLock()) { @@ -1612,12 +1611,16 @@ private void handleExecuteSequenceNode() { .get(tmpDevice.serialNumber); if (tmpQueueObjects != null) { QueueObject tmpQueueObject = tmpQueueObjects.peek(); - Future tmpFuture = tmpQueueObject.future; + Future tmpFuture = null; + if (tmpQueueObject != null) { + tmpFuture = tmpQueueObject.future; + } if (!queueObject.equals(tmpQueueObject) || (tmpFuture != null && !tmpFuture.isDone())) { execute = false; break; } + serial = serial + tmpDevice.serialNumber + " "; } } diff --git a/bundles/org.smarthomej.binding.androiddebugbridge/src/main/java/org/smarthomej/binding/androiddebugbridge/internal/AndroidDebugBridgeDevice.java b/bundles/org.smarthomej.binding.androiddebugbridge/src/main/java/org/smarthomej/binding/androiddebugbridge/internal/AndroidDebugBridgeDevice.java index c4b2c5c63e..e97f9a01bb 100644 --- a/bundles/org.smarthomej.binding.androiddebugbridge/src/main/java/org/smarthomej/binding/androiddebugbridge/internal/AndroidDebugBridgeDevice.java +++ b/bundles/org.smarthomej.binding.androiddebugbridge/src/main/java/org/smarthomej/binding/androiddebugbridge/internal/AndroidDebugBridgeDevice.java @@ -31,6 +31,7 @@ import java.security.spec.InvalidKeySpecException; import java.util.Arrays; import java.util.Base64; +import java.util.Objects; import java.util.Optional; import java.util.concurrent.*; import java.util.concurrent.locks.Lock; @@ -135,7 +136,7 @@ public void openURL(String url) public String getCurrentPackage() throws AndroidDebugBridgeDeviceException, InterruptedException, AndroidDebugBridgeDeviceReadException, TimeoutException, ExecutionException { String result = runAdbShell("dumpsys", "window", "windows", "|", "grep", "mFocusedApp"); - String targetLine = Arrays.stream(result.split("\n")).findFirst().orElse(""); + String targetLine = Objects.requireNonNull(Arrays.stream(result.split("\n")).findFirst().orElse("")); String[] lineParts = targetLine.split(" "); if (lineParts.length >= 2) { String packageActivityName = lineParts[lineParts.length - 2]; @@ -333,7 +334,8 @@ private String runAdbShell(String... args) } lock.lock(); try { - commandFuture = scheduler.submit(() -> { + stopCommandFuture(); // make sure there is not future + Future commandFuture = scheduler.submit(() -> { ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); String cmd = String.join(" ", args); logger.debug("{} - shell:{}", ip, cmd); @@ -350,6 +352,7 @@ private String runAdbShell(String... args) } return byteArrayOutputStream.toString(StandardCharsets.US_ASCII); }); + this.commandFuture = commandFuture; return commandFuture.get(timeoutSec, TimeUnit.SECONDS).trim(); } finally { stopCommandFuture(); diff --git a/bundles/org.smarthomej.binding.deconz/src/main/java/org/smarthomej/binding/deconz/internal/netutils/AsyncHttpClient.java b/bundles/org.smarthomej.binding.deconz/src/main/java/org/smarthomej/binding/deconz/internal/netutils/AsyncHttpClient.java index 44df9b1670..286a5c8b36 100644 --- a/bundles/org.smarthomej.binding.deconz/src/main/java/org/smarthomej/binding/deconz/internal/netutils/AsyncHttpClient.java +++ b/bundles/org.smarthomej.binding.deconz/src/main/java/org/smarthomej/binding/deconz/internal/netutils/AsyncHttpClient.java @@ -102,7 +102,7 @@ private CompletableFuture doNetwork(HttpMethod method, String address, @ } request.method(method).timeout(timeout, TimeUnit.MILLISECONDS).send(new BufferingResponseListener() { - @NonNullByDefault({}) + @Override public void onComplete(org.eclipse.jetty.client.api.Result result) { final HttpResponse response = (HttpResponse) result.getResponse(); @@ -110,7 +110,8 @@ public void onComplete(org.eclipse.jetty.client.api.Result result) { f.completeExceptionally(result.getFailure()); return; } - f.complete(new Result(getContentAsString(), response.getStatus())); + String content = getContentAsString(); + f.complete(new Result(content != null ? content : "", response.getStatus())); } }); return f; diff --git a/bundles/org.smarthomej.binding.dmx/src/main/java/org/smarthomej/binding/dmx/internal/DmxBridgeHandler.java b/bundles/org.smarthomej.binding.dmx/src/main/java/org/smarthomej/binding/dmx/internal/DmxBridgeHandler.java index b1cd8b3be2..221f1917ae 100644 --- a/bundles/org.smarthomej.binding.dmx/src/main/java/org/smarthomej/binding/dmx/internal/DmxBridgeHandler.java +++ b/bundles/org.smarthomej.binding.dmx/src/main/java/org/smarthomej/binding/dmx/internal/DmxBridgeHandler.java @@ -22,6 +22,7 @@ import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; +import org.eclipse.jdt.annotation.NonNull; import org.openhab.core.library.types.OnOffType; import org.openhab.core.thing.Bridge; import org.openhab.core.thing.ChannelUID; @@ -284,7 +285,7 @@ public void immediateFade(String channelString, String fadeString, Boolean resum } @Override - public Collection> getServices() { + public @NonNull Collection<@NonNull Class> getServices() { return Collections.singletonList(DmxActions.class); } } diff --git a/bundles/org.smarthomej.binding.dmx/src/main/java/org/smarthomej/binding/dmx/internal/ValueSet.java b/bundles/org.smarthomej.binding.dmx/src/main/java/org/smarthomej/binding/dmx/internal/ValueSet.java index f9b15a7b06..efa3746bec 100644 --- a/bundles/org.smarthomej.binding.dmx/src/main/java/org/smarthomej/binding/dmx/internal/ValueSet.java +++ b/bundles/org.smarthomej.binding.dmx/src/main/java/org/smarthomej/binding/dmx/internal/ValueSet.java @@ -18,6 +18,7 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; +import org.eclipse.jdt.annotation.NonNull; import org.openhab.core.library.types.PercentType; /** @@ -25,7 +26,6 @@ * * @author Jan N. Klug - Initial contribution */ - public class ValueSet { protected static final Pattern VALUESET_PATTERN = Pattern.compile("^(\\d*):([\\d,]*):([\\d-]*)$"); @@ -189,7 +189,7 @@ public static List parseChaseConfig(String chaseConfigString) { } @Override - public String toString() { + public @NonNull String toString() { String str = "fade/hold:" + String.valueOf(fadeTime) + "/" + String.valueOf(holdTime) + ": "; for (Integer value : values) { str += String.valueOf(value) + " "; diff --git a/bundles/org.smarthomej.binding.dmx/src/main/java/org/smarthomej/binding/dmx/internal/action/FadeAction.java b/bundles/org.smarthomej.binding.dmx/src/main/java/org/smarthomej/binding/dmx/internal/action/FadeAction.java index 343fa505de..b1f7eb1f19 100644 --- a/bundles/org.smarthomej.binding.dmx/src/main/java/org/smarthomej/binding/dmx/internal/action/FadeAction.java +++ b/bundles/org.smarthomej.binding.dmx/src/main/java/org/smarthomej/binding/dmx/internal/action/FadeAction.java @@ -13,6 +13,7 @@ */ package org.smarthomej.binding.dmx.internal.action; +import org.eclipse.jdt.annotation.NonNull; import org.openhab.core.library.types.PercentType; import org.smarthomej.binding.dmx.internal.Util; import org.smarthomej.binding.dmx.internal.multiverse.DmxChannel; @@ -139,7 +140,7 @@ public int getNewValue(DmxChannel channel, long currentTime) { } @Override - public String toString() { + public @NonNull String toString() { return "FadeAction: " + String.valueOf(targetValue) + ", fade time " + String.valueOf(fadeTime) + "ms, hold time " + String.valueOf(holdTime) + "ms"; } diff --git a/bundles/org.smarthomej.binding.dmx/src/main/java/org/smarthomej/binding/dmx/internal/dmxoverethernet/IpNode.java b/bundles/org.smarthomej.binding.dmx/src/main/java/org/smarthomej/binding/dmx/internal/dmxoverethernet/IpNode.java index ed11fd6a58..adf44e5c80 100644 --- a/bundles/org.smarthomej.binding.dmx/src/main/java/org/smarthomej/binding/dmx/internal/dmxoverethernet/IpNode.java +++ b/bundles/org.smarthomej.binding.dmx/src/main/java/org/smarthomej/binding/dmx/internal/dmxoverethernet/IpNode.java @@ -20,6 +20,7 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; +import org.eclipse.jdt.annotation.NonNull; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -132,7 +133,7 @@ public String getAddressString() { * @return string representation of this node (address:port) */ @Override - public String toString() { + public @NonNull String toString() { if (this.address == null) { return "(null):" + String.valueOf(this.port); } diff --git a/bundles/org.smarthomej.binding.dmx/src/main/java/org/smarthomej/binding/dmx/internal/handler/Lib485BridgeHandler.java b/bundles/org.smarthomej.binding.dmx/src/main/java/org/smarthomej/binding/dmx/internal/handler/Lib485BridgeHandler.java index a4f5bb24f6..95d659c29c 100644 --- a/bundles/org.smarthomej.binding.dmx/src/main/java/org/smarthomej/binding/dmx/internal/handler/Lib485BridgeHandler.java +++ b/bundles/org.smarthomej.binding.dmx/src/main/java/org/smarthomej/binding/dmx/internal/handler/Lib485BridgeHandler.java @@ -105,7 +105,7 @@ protected void sendDmxData() { universe.calculateBuffer(now); for (IpNode receiverNode : receiverNodes.keySet()) { Socket socket = receiverNodes.get(receiverNode); - if (socket.isConnected()) { + if (socket != null && socket.isConnected()) { try { socket.getOutputStream().write(universe.getBuffer()); } catch (IOException e) { diff --git a/bundles/org.smarthomej.binding.dmx/src/main/java/org/smarthomej/binding/dmx/internal/multiverse/BaseDmxChannel.java b/bundles/org.smarthomej.binding.dmx/src/main/java/org/smarthomej/binding/dmx/internal/multiverse/BaseDmxChannel.java index ba4cdd377e..c6630f173f 100644 --- a/bundles/org.smarthomej.binding.dmx/src/main/java/org/smarthomej/binding/dmx/internal/multiverse/BaseDmxChannel.java +++ b/bundles/org.smarthomej.binding.dmx/src/main/java/org/smarthomej/binding/dmx/internal/multiverse/BaseDmxChannel.java @@ -20,6 +20,8 @@ import java.util.stream.IntStream; import java.util.stream.Stream; +import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.Nullable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.smarthomej.binding.dmx.internal.Util; @@ -92,20 +94,20 @@ public void setUniverseId(int universeId) { } @Override - public int compareTo(BaseDmxChannel otherDmxChannel) { + public int compareTo(@Nullable BaseDmxChannel otherDmxChannel) { if (otherDmxChannel == null) { return -1; } - int universeCompare = new Integer(getUniverseId()).compareTo(new Integer(otherDmxChannel.getUniverseId())); + int universeCompare = Integer.valueOf(getUniverseId()).compareTo(otherDmxChannel.getUniverseId()); if (universeCompare == 0) { - return new Integer(getChannelId()).compareTo(new Integer(otherDmxChannel.getChannelId())); + return Integer.valueOf(getChannelId()).compareTo(otherDmxChannel.getChannelId()); } else { return universeCompare; } } @Override - public String toString() { + public @NonNull String toString() { return universeId + ":" + dmxChannelId; } @@ -125,9 +127,9 @@ public static List fromString(String dmxChannelString, int defau Matcher channelMatch = CHANNEL_PATTERN.matcher(singleDmxChannelString); if (channelMatch.matches()) { final int universeId = (channelMatch.group(1) == null) ? defaultUniverseId - : Integer.valueOf(channelMatch.group(1)); - dmxChannelWidth = channelMatch.group(3).equals("") ? 1 : Integer.valueOf(channelMatch.group(3)); - dmxChannelId = Integer.valueOf(channelMatch.group(2)); + : Integer.parseInt(channelMatch.group(1)); + dmxChannelWidth = channelMatch.group(3).equals("") ? 1 : Integer.parseInt(channelMatch.group(3)); + dmxChannelId = Integer.parseInt(channelMatch.group(2)); LOGGER.trace("parsed channel string {} to universe {}, id {}, width {}", singleDmxChannelString, universeId, dmxChannelId, dmxChannelWidth); IntStream.range(dmxChannelId, dmxChannelId + dmxChannelWidth) diff --git a/bundles/org.smarthomej.binding.dmx/src/test/java/org/smarthomej/binding/dmx/test/AbstractDmxThingTestParent.java b/bundles/org.smarthomej.binding.dmx/src/test/java/org/smarthomej/binding/dmx/test/AbstractDmxThingTestParent.java index 01d710f511..3d368c4855 100644 --- a/bundles/org.smarthomej.binding.dmx/src/test/java/org/smarthomej/binding/dmx/test/AbstractDmxThingTestParent.java +++ b/bundles/org.smarthomej.binding.dmx/src/test/java/org/smarthomej/binding/dmx/test/AbstractDmxThingTestParent.java @@ -23,6 +23,7 @@ import java.util.HashMap; import java.util.Map; +import java.util.Objects; import java.util.function.Consumer; import org.mockito.ArgumentCaptor; @@ -93,6 +94,7 @@ protected void assertThingStatus(Thing thing) { // check that thing properly follows bridge status ThingHandler handler = thing.getHandler(); assertNotNull(handler); + Objects.requireNonNull(handler); handler.bridgeStatusChanged(ThingStatusInfoBuilder.create(ThingStatus.OFFLINE).build()); waitForAssert(() -> assertEquals(ThingStatus.OFFLINE, thing.getStatusInfo().getStatus())); handler.bridgeStatusChanged(ThingStatusInfoBuilder.create(ThingStatus.ONLINE).build()); diff --git a/bundles/org.smarthomej.binding.http/src/main/java/org/smarthomej/binding/http/internal/HttpThingHandler.java b/bundles/org.smarthomej.binding.http/src/main/java/org/smarthomej/binding/http/internal/HttpThingHandler.java index b36b58a093..c8f99e672d 100644 --- a/bundles/org.smarthomej.binding.http/src/main/java/org/smarthomej/binding/http/internal/HttpThingHandler.java +++ b/bundles/org.smarthomej.binding.http/src/main/java/org/smarthomej/binding/http/internal/HttpThingHandler.java @@ -287,8 +287,9 @@ private void createChannel(Channel channel) { // we need a key consisting of stateContent and URL, only if both are equal, we can use the same cache String key = channelConfig.stateContent + "$" + stateUrl; channelUrls.put(channelUID, key); - urlHandlers.computeIfAbsent(key, k -> new RefreshingUrlCache(scheduler, rateLimitedHttpClient, stateUrl, - config, channelConfig.stateContent)).addConsumer(itemValueConverter::process); + Objects.requireNonNull(urlHandlers.computeIfAbsent(key, k -> new RefreshingUrlCache(scheduler, + rateLimitedHttpClient, stateUrl, config, channelConfig.stateContent))) + .addConsumer(itemValueConverter::process); } StateDescription stateDescription = StateDescriptionFragmentBuilder.create() diff --git a/bundles/org.smarthomej.binding.http/src/main/java/org/smarthomej/binding/http/internal/http/HttpResponseListener.java b/bundles/org.smarthomej.binding.http/src/main/java/org/smarthomej/binding/http/internal/http/HttpResponseListener.java index b52fa143c4..dbe7e4a31c 100644 --- a/bundles/org.smarthomej.binding.http/src/main/java/org/smarthomej/binding/http/internal/http/HttpResponseListener.java +++ b/bundles/org.smarthomej.binding.http/src/main/java/org/smarthomej/binding/http/internal/http/HttpResponseListener.java @@ -55,7 +55,7 @@ public HttpResponseListener(CompletableFuture<@Nullable ContentWrapper> future, } @Override - public void onComplete(@NonNullByDefault({}) Result result) { + public void onComplete(Result result) { Response response = result.getResponse(); if (logger.isTraceEnabled()) { logger.trace("Received from '{}': {}", result.getRequest().getURI(), responseToLogString(response)); diff --git a/bundles/org.smarthomej.binding.irobot/src/test/java/org/smarthomej/binding/irobot/internal/handler/RoombaHandlerTest.java b/bundles/org.smarthomej.binding.irobot/src/test/java/org/smarthomej/binding/irobot/internal/handler/RoombaHandlerTest.java index d5d319edb4..daa8c7c520 100644 --- a/bundles/org.smarthomej.binding.irobot/src/test/java/org/smarthomej/binding/irobot/internal/handler/RoombaHandlerTest.java +++ b/bundles/org.smarthomej.binding.irobot/src/test/java/org/smarthomej/binding/irobot/internal/handler/RoombaHandlerTest.java @@ -15,6 +15,7 @@ import java.io.IOException; import java.lang.reflect.Field; +import java.util.Objects; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.TestInstance; @@ -76,7 +77,7 @@ void testInit() throws InterruptedException, IOException { handler.initialize(); Mockito.verify(myThing, Mockito.times(1)).getConfiguration(); - System.in.read(); + Objects.requireNonNull(System.in).read(); handler.dispose(); } @@ -84,12 +85,12 @@ void testInit() throws InterruptedException, IOException { void testCleanRegion() throws IOException, InterruptedException { handler.initialize(); - System.in.read(); + Objects.requireNonNull(System.in).read(); ChannelUID cmd = new ChannelUID("my:thi:blabla:command"); handler.handleCommand(cmd, new StringType("cleanRegions:AABBCCDDEEFFGGHH;2,3")); - System.in.read(); + Objects.requireNonNull(System.in).read(); handler.dispose(); } @@ -97,12 +98,12 @@ void testCleanRegion() throws IOException, InterruptedException { void testDock() throws IOException, InterruptedException { handler.initialize(); - System.in.read(); + Objects.requireNonNull(System.in).read(); ChannelUID cmd = new ChannelUID("my:thi:blabla:command"); handler.handleCommand(cmd, new StringType("dock")); - System.in.read(); + Objects.requireNonNull(System.in).read(); handler.dispose(); } @@ -110,12 +111,12 @@ void testDock() throws IOException, InterruptedException { void testStop() throws IOException, InterruptedException { handler.initialize(); - System.in.read(); + Objects.requireNonNull(System.in).read(); ChannelUID cmd = new ChannelUID("my:thi:blabla:command"); handler.handleCommand(cmd, new StringType("stop")); - System.in.read(); + Objects.requireNonNull(System.in).read(); handler.dispose(); } } diff --git a/bundles/org.smarthomej.binding.knx/src/main/java/org/smarthomej/binding/knx/internal/client/AbstractKNXClient.java b/bundles/org.smarthomej.binding.knx/src/main/java/org/smarthomej/binding/knx/internal/client/AbstractKNXClient.java index 75fbc7cede..ebc6ae84bd 100644 --- a/bundles/org.smarthomej.binding.knx/src/main/java/org/smarthomej/binding/knx/internal/client/AbstractKNXClient.java +++ b/bundles/org.smarthomej.binding.knx/src/main/java/org/smarthomej/binding/knx/internal/client/AbstractKNXClient.java @@ -21,6 +21,7 @@ import java.util.concurrent.TimeUnit; import java.util.function.Consumer; +import org.eclipse.jdt.annotation.NonNull; import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; import org.openhab.core.thing.ThingStatus; @@ -222,7 +223,6 @@ private void disconnect(@Nullable Exception e) { } } - @SuppressWarnings("null") private void releaseConnection() { logger.debug("Bridge {} is disconnecting from the KNX bus", thingUID); readDatapoints.clear(); @@ -241,7 +241,7 @@ private void releaseConnection() { }); } - private <@Nullable T> T nullify(T target, @Nullable Consumer lastWill) { + private @Nullable T nullify(@Nullable T target, @Nullable Consumer<@NonNull T> lastWill) { if (target != null && lastWill != null) { lastWill.accept(target); } @@ -272,7 +272,6 @@ private String toDPTValue(Type type, String dpt) { return typeHelper.toDPTValue(type, dpt); } - @SuppressWarnings("null") private void readNextQueuedDatapoint() { if (!connectIfNotAutomatic()) { return; diff --git a/bundles/org.smarthomej.binding.knx/src/main/java/org/smarthomej/binding/knx/internal/client/DeviceInspector.java b/bundles/org.smarthomej.binding.knx/src/main/java/org/smarthomej/binding/knx/internal/client/DeviceInspector.java index c3ca103065..67c02a6201 100644 --- a/bundles/org.smarthomej.binding.knx/src/main/java/org/smarthomej/binding/knx/internal/client/DeviceInspector.java +++ b/bundles/org.smarthomej.binding.knx/src/main/java/org/smarthomej/binding/knx/internal/client/DeviceInspector.java @@ -143,12 +143,20 @@ private Map readDeviceDescription(IndividualAddress address) { if (data != null) { final DD0 dd = DeviceDescriptor.DD0.from(data); - ret.put(FIRMWARE_TYPE, Firmware.getName(dd.firmwareType())); - ret.put(FIRMWARE_VERSION, Firmware.getName(dd.firmwareVersion())); - ret.put(FIRMWARE_SUBVERSION, Firmware.getName(dd.firmwareSubcode())); - logger.debug("The device with address {} is of type {}, version {}, subversion {}", address, - Firmware.getName(dd.firmwareType()), Firmware.getName(dd.firmwareVersion()), - Firmware.getName(dd.firmwareSubcode())); + String type = Firmware.getName(dd.firmwareType()); + if (type != null) { + ret.put(FIRMWARE_TYPE, type); + } + String version = Firmware.getName(dd.firmwareVersion()); + if (version != null) { + ret.put(FIRMWARE_VERSION, version); + } + String subVersion = Firmware.getName(dd.firmwareSubcode()); + if (subVersion != null) { + ret.put(FIRMWARE_SUBVERSION, subVersion); + } + logger.debug("The device with address {} is of type {}, version {}, subversion {}", address, type, version, + subVersion); } else { logger.debug("The KNX device with address {} does not expose a Device Descriptor", address); } diff --git a/bundles/org.smarthomej.binding.knx/src/main/java/org/smarthomej/binding/knx/internal/client/ReadDatapoint.java b/bundles/org.smarthomej.binding.knx/src/main/java/org/smarthomej/binding/knx/internal/client/ReadDatapoint.java index ff4e82ed26..5b49b63c24 100644 --- a/bundles/org.smarthomej.binding.knx/src/main/java/org/smarthomej/binding/knx/internal/client/ReadDatapoint.java +++ b/bundles/org.smarthomej.binding.knx/src/main/java/org/smarthomej/binding/knx/internal/client/ReadDatapoint.java @@ -13,6 +13,8 @@ */ package org.smarthomej.binding.knx.internal.client; +import org.eclipse.jdt.annotation.Nullable; + import tuwien.auto.calimero.datapoint.Datapoint; /** @@ -57,7 +59,7 @@ public int hashCode() { } @Override - public boolean equals(Object obj) { + public boolean equals(@Nullable Object obj) { if (this == obj) { return true; } diff --git a/bundles/org.smarthomej.binding.knx/src/main/java/org/smarthomej/binding/knx/internal/handler/AbstractKNXThingHandler.java b/bundles/org.smarthomej.binding.knx/src/main/java/org/smarthomej/binding/knx/internal/handler/AbstractKNXThingHandler.java index c94f4a44f1..ac3194d140 100644 --- a/bundles/org.smarthomej.binding.knx/src/main/java/org/smarthomej/binding/knx/internal/handler/AbstractKNXThingHandler.java +++ b/bundles/org.smarthomej.binding.knx/src/main/java/org/smarthomej/binding/knx/internal/handler/AbstractKNXThingHandler.java @@ -175,7 +175,8 @@ protected void attachToClient() { } DeviceConfig config = getConfigAs(DeviceConfig.class); try { - if (config.getAddress() != null && !config.getAddress().isEmpty()) { + String configAddress = config.getAddress(); + if (configAddress != null && !configAddress.isEmpty()) { updateStatus(ThingStatus.UNKNOWN); address = new IndividualAddress(config.getAddress()); diff --git a/bundles/org.smarthomej.binding.knx/src/main/java/org/smarthomej/binding/knx/internal/handler/DeviceThingHandler.java b/bundles/org.smarthomej.binding.knx/src/main/java/org/smarthomej/binding/knx/internal/handler/DeviceThingHandler.java index 998ef03941..cc6060ca96 100644 --- a/bundles/org.smarthomej.binding.knx/src/main/java/org/smarthomej/binding/knx/internal/handler/DeviceThingHandler.java +++ b/bundles/org.smarthomej.binding.knx/src/main/java/org/smarthomej/binding/knx/internal/handler/DeviceThingHandler.java @@ -216,7 +216,9 @@ public boolean listensTo(GroupAddress destination) { @SuppressWarnings("null") private void rememberRespondingSpec(OutboundSpec commandSpec, boolean add) { GroupAddress ga = commandSpec.getGroupAddress(); - groupAddressesRespondingSpec.removeIf(spec -> spec.getGroupAddress().equals(ga)); + if (ga != null) { + groupAddressesRespondingSpec.removeIf(spec -> ga.equals(spec.getGroupAddress())); + } if (add) { groupAddressesRespondingSpec.add(commandSpec); } diff --git a/bundles/org.smarthomej.binding.knx/src/main/java/org/smarthomej/binding/knx/internal/handler/Firmware.java b/bundles/org.smarthomej.binding.knx/src/main/java/org/smarthomej/binding/knx/internal/handler/Firmware.java index 853b32d161..25e8f4ccd0 100644 --- a/bundles/org.smarthomej.binding.knx/src/main/java/org/smarthomej/binding/knx/internal/handler/Firmware.java +++ b/bundles/org.smarthomej.binding.knx/src/main/java/org/smarthomej/binding/knx/internal/handler/Firmware.java @@ -13,11 +13,15 @@ */ package org.smarthomej.binding.knx.internal.handler; +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; + /** * Enumeration containing the firmware types. * * @author Karel Goderis - Initial contribution */ +@NonNullByDefault public enum Firmware { F0(0, "BCU 1, BCU 2, BIM M113"), F1(1, "Unidirectional devices"), @@ -26,10 +30,10 @@ public enum Firmware { F8(8, "IR Decoder, TP1 legacy"), F9(9, "Repeater, Coupler"); - private int code; - private String name; + private final int code; + private final String name; - private Firmware(int code, String name) { + Firmware(int code, String name) { this.code = code; this.name = name; } @@ -39,7 +43,7 @@ public String toString() { return name; } - public static String getName(int code) { + public static @Nullable String getName(int code) { for (Firmware c : Firmware.values()) { if (c.code == code) { return c.name; diff --git a/bundles/org.smarthomej.binding.knx/src/main/java/org/smarthomej/binding/knx/internal/handler/SerialBridgeThingHandler.java b/bundles/org.smarthomej.binding.knx/src/main/java/org/smarthomej/binding/knx/internal/handler/SerialBridgeThingHandler.java index 3a8fb3ce88..f75c6d5938 100644 --- a/bundles/org.smarthomej.binding.knx/src/main/java/org/smarthomej/binding/knx/internal/handler/SerialBridgeThingHandler.java +++ b/bundles/org.smarthomej.binding.knx/src/main/java/org/smarthomej/binding/knx/internal/handler/SerialBridgeThingHandler.java @@ -49,10 +49,12 @@ public void initialize() { updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "serial port not configured"); return; } - client = new SerialClient(config.getAutoReconnectPeriod(), thing.getUID(), config.getResponseTimeout(), - config.getReadingPause(), config.getReadRetriesLimit(), getScheduler(), serialPort, this); + SerialClient client = new SerialClient(config.getAutoReconnectPeriod(), thing.getUID(), + config.getResponseTimeout(), config.getReadingPause(), config.getReadRetriesLimit(), getScheduler(), + serialPort, this); updateStatus(ThingStatus.UNKNOWN); client.initialize(); + this.client = client; } @Override diff --git a/bundles/org.smarthomej.binding.knx/src/test/java/org/smarthomej/binding/knx/internal/channel/KNXChannelTypeTest.java b/bundles/org.smarthomej.binding.knx/src/test/java/org/smarthomej/binding/knx/internal/channel/KNXChannelTypeTest.java index 304c595c0e..242de4c118 100644 --- a/bundles/org.smarthomej.binding.knx/src/test/java/org/smarthomej/binding/knx/internal/channel/KNXChannelTypeTest.java +++ b/bundles/org.smarthomej.binding.knx/src/test/java/org/smarthomej/binding/knx/internal/channel/KNXChannelTypeTest.java @@ -41,6 +41,11 @@ public void setup() { public void testParseWithDPTMultipleWithRead() { ChannelConfiguration res = ct.parse("5.001:<1/3/22+0/3/22+<0/8/15"); + if (res == null) { + fail(); + return; + } + assertEquals("5.001", res.getDPT()); assertEquals("1/3/22", res.getMainGA().getGA()); assertTrue(res.getMainGA().isRead()); @@ -52,6 +57,11 @@ public void testParseWithDPTMultipleWithRead() { public void testParseWithDPTMultipleWithoutRead() { ChannelConfiguration res = ct.parse("5.001:1/3/22+0/3/22+0/8/15"); + if (res == null) { + fail(); + return; + } + assertEquals("5.001", res.getDPT()); assertEquals("1/3/22", res.getMainGA().getGA()); assertFalse(res.getMainGA().isRead()); @@ -63,6 +73,11 @@ public void testParseWithDPTMultipleWithoutRead() { public void testParseWithoutDPTSingleWithoutRead() { ChannelConfiguration res = ct.parse("1/3/22"); + if (res == null) { + fail(); + return; + } + assertNull(res.getDPT()); assertEquals("1/3/22", res.getMainGA().getGA()); assertFalse(res.getMainGA().isRead()); @@ -74,6 +89,11 @@ public void testParseWithoutDPTSingleWithoutRead() { public void testParseWithoutDPTSingleWithRead() { ChannelConfiguration res = ct.parse("<1/3/22"); + if (res == null) { + fail(); + return; + } + assertNull(res.getDPT()); assertEquals("1/3/22", res.getMainGA().getGA()); assertTrue(res.getMainGA().isRead()); @@ -84,6 +104,12 @@ public void testParseWithoutDPTSingleWithRead() { @Test public void testParseTwoLevel() { ChannelConfiguration res = ct.parse("5.001:<3/1024+<4/1025"); + + if (res == null) { + fail(); + return; + } + assertEquals("3/1024", res.getMainGA().getGA()); assertEquals(2, res.getListenGAs().size()); assertEquals(2, res.getReadGAs().size()); @@ -92,6 +118,12 @@ public void testParseTwoLevel() { @Test public void testParseFreeLevel() { ChannelConfiguration res = ct.parse("5.001:<4610+<4611"); + + if (res == null) { + fail(); + return; + } + assertEquals("4610", res.getMainGA().getGA()); assertEquals(2, res.getListenGAs().size()); assertEquals(2, res.getReadGAs().size()); diff --git a/bundles/org.smarthomej.binding.mail/src/main/java/org/smarthomej/binding/mail/internal/POP3IMAPHandler.java b/bundles/org.smarthomej.binding.mail/src/main/java/org/smarthomej/binding/mail/internal/POP3IMAPHandler.java index 8c7da4791e..d8ea341345 100644 --- a/bundles/org.smarthomej.binding.mail/src/main/java/org/smarthomej/binding/mail/internal/POP3IMAPHandler.java +++ b/bundles/org.smarthomej.binding.mail/src/main/java/org/smarthomej/binding/mail/internal/POP3IMAPHandler.java @@ -99,13 +99,12 @@ public void initialize() { updateStatus(ThingStatus.ONLINE); } - @SuppressWarnings("null") @Override public void dispose() { + ScheduledFuture refreshTask = this.refreshTask; if (refreshTask != null) { - if (!refreshTask.isCancelled()) { - refreshTask.cancel(true); - } + refreshTask.cancel(true); + this.refreshTask = null; } } diff --git a/bundles/org.smarthomej.binding.mail/src/main/java/org/smarthomej/binding/mail/internal/SMTPHandler.java b/bundles/org.smarthomej.binding.mail/src/main/java/org/smarthomej/binding/mail/internal/SMTPHandler.java index edeb5d37b3..c79b839af1 100644 --- a/bundles/org.smarthomej.binding.mail/src/main/java/org/smarthomej/binding/mail/internal/SMTPHandler.java +++ b/bundles/org.smarthomej.binding.mail/src/main/java/org/smarthomej/binding/mail/internal/SMTPHandler.java @@ -96,9 +96,11 @@ public boolean sendMail(Email mail) { } mail.send(); } catch (EmailException e) { - logger.warn("{}", e.getMessage()); - if (e.getCause() != null) { - logger.warn("{}", e.getCause().toString()); + Throwable cause = e.getCause(); + if (cause != null) { + logger.warn("{}", cause.toString()); + } else { + logger.warn("{}", e.getMessage()); } return false; } diff --git a/bundles/org.smarthomej.binding.onewire/src/main/java/org/smarthomej/binding/onewire/internal/Util.java b/bundles/org.smarthomej.binding.onewire/src/main/java/org/smarthomej/binding/onewire/internal/Util.java index 3cfdbb02d8..f3f33e42f0 100644 --- a/bundles/org.smarthomej.binding.onewire/src/main/java/org/smarthomej/binding/onewire/internal/Util.java +++ b/bundles/org.smarthomej.binding.onewire/src/main/java/org/smarthomej/binding/onewire/internal/Util.java @@ -15,7 +15,6 @@ import java.io.IOException; import java.net.URL; -import java.util.HashMap; import java.util.Map; import java.util.Properties; import java.util.stream.Collectors; @@ -90,6 +89,10 @@ public static State calculateDewpoint(QuantityType temperature, public static Map readPropertiesFile(String filename) { URL resource = Thread.currentThread().getContextClassLoader().getResource(filename); + if (resource == null) { + LOGGER.warn("Could not read resource file {}, binding will probably fail: resource is null", filename); + return Map.of(); + } Properties properties = new Properties(); try { properties.load(resource.openStream()); @@ -97,7 +100,7 @@ public static Map readPropertiesFile(String filename) { .collect(Collectors.toMap(e -> (String) e.getKey(), e -> (String) e.getValue())); } catch (IOException e) { LOGGER.warn("Could not read resource file {}, binding will probably fail: {}", filename, e.getMessage()); - return new HashMap<>(); + return Map.of(); } } } diff --git a/bundles/org.smarthomej.binding.onewire/src/main/java/org/smarthomej/binding/onewire/internal/handler/AdvancedMultisensorThingHandler.java b/bundles/org.smarthomej.binding.onewire/src/main/java/org/smarthomej/binding/onewire/internal/handler/AdvancedMultisensorThingHandler.java index b72bfa16af..f4113cbc2e 100644 --- a/bundles/org.smarthomej.binding.onewire/src/main/java/org/smarthomej/binding/onewire/internal/handler/AdvancedMultisensorThingHandler.java +++ b/bundles/org.smarthomej.binding.onewire/src/main/java/org/smarthomej/binding/onewire/internal/handler/AdvancedMultisensorThingHandler.java @@ -15,12 +15,7 @@ import static org.smarthomej.binding.onewire.internal.OwBindingConstants.*; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; +import java.util.*; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -160,7 +155,7 @@ protected void configureThingChannels() { // delete unwanted channels Set existingChannelIds = thing.getChannels().stream().map(channel -> channel.getUID().getId()) .collect(Collectors.toSet()); - Set wantedChannelIds = SENSOR_TYPE_CHANNEL_MAP.get(sensorType).stream() + Set wantedChannelIds = SENSOR_TYPE_CHANNEL_MAP.getOrDefault(sensorType, Set.of()).stream() .map(channelConfig -> channelConfig.channelId).collect(Collectors.toSet()); wantedChannelIds.add(CHANNEL_TEMPERATURE); wantedChannelIds.add(CHANNEL_HUMIDITY); @@ -168,13 +163,12 @@ protected void configureThingChannels() { .forEach(channelId -> removeChannelIfExisting(thingBuilder, channelId)); // add or update wanted channels - SENSOR_TYPE_CHANNEL_MAP.get(sensorType).stream().forEach(channelConfig -> { + SENSOR_TYPE_CHANNEL_MAP.getOrDefault(sensorType, Set.of()).stream().forEach(channelConfig -> { addChannelIfMissingAndEnable(thingBuilder, channelConfig); }); // temperature channel - if (configuration.containsKey(CONFIG_TEMPERATURESENSOR) - && configuration.get(CONFIG_TEMPERATURESENSOR).equals("DS18B20")) { + if ("DS18B20".equals(configuration.get(CONFIG_TEMPERATURESENSOR))) { addChannelIfMissingAndEnable(thingBuilder, new OwChannelConfig(CHANNEL_TEMPERATURE, CHANNEL_TYPE_UID_TEMPERATURE_POR_RES), 1); } else { diff --git a/bundles/org.smarthomej.binding.onewire/src/main/java/org/smarthomej/binding/onewire/internal/handler/OwBaseThingHandler.java b/bundles/org.smarthomej.binding.onewire/src/main/java/org/smarthomej/binding/onewire/internal/handler/OwBaseThingHandler.java index 5f3c3d7a32..c691387f9d 100644 --- a/bundles/org.smarthomej.binding.onewire/src/main/java/org/smarthomej/binding/onewire/internal/handler/OwBaseThingHandler.java +++ b/bundles/org.smarthomej.binding.onewire/src/main/java/org/smarthomej/binding/onewire/internal/handler/OwBaseThingHandler.java @@ -167,13 +167,13 @@ protected void configureThingChannels() { // remove unwanted channels Set existingChannelIds = thing.getChannels().stream().map(channel -> channel.getUID().getId()) .collect(Collectors.toSet()); - Set wantedChannelIds = SENSOR_TYPE_CHANNEL_MAP.get(sensorType).stream() + Set wantedChannelIds = SENSOR_TYPE_CHANNEL_MAP.getOrDefault(sensorType, Set.of()).stream() .map(channelConfig -> channelConfig.channelId).collect(Collectors.toSet()); existingChannelIds.stream().filter(channelId -> !wantedChannelIds.contains(channelId)) .forEach(channelId -> removeChannelIfExisting(thingBuilder, channelId)); // add or update wanted channels - SENSOR_TYPE_CHANNEL_MAP.get(sensorType).stream().forEach(channelConfig -> { + SENSOR_TYPE_CHANNEL_MAP.getOrDefault(sensorType, Set.of()).stream().forEach(channelConfig -> { addChannelIfMissingAndEnable(thingBuilder, channelConfig); }); diff --git a/bundles/org.smarthomej.binding.onewire/src/main/java/org/smarthomej/binding/onewire/internal/owserver/OwserverConnection.java b/bundles/org.smarthomej.binding.onewire/src/main/java/org/smarthomej/binding/onewire/internal/owserver/OwserverConnection.java index 05fb10d340..ce113e10a0 100644 --- a/bundles/org.smarthomej.binding.onewire/src/main/java/org/smarthomej/binding/onewire/internal/owserver/OwserverConnection.java +++ b/bundles/org.smarthomej.binding.onewire/src/main/java/org/smarthomej/binding/onewire/internal/owserver/OwserverConnection.java @@ -496,7 +496,7 @@ private OwserverPacket read(boolean noTimeoutException) throws OwException { throw e; } catch (IOException e) { // Read time out - if (e.getMessage().equals("Read timed out") && noTimeoutException) { + if ("Read timed out".equals(e.getMessage()) && noTimeoutException) { logger.trace("timeout - setting error code to -1"); // will lead to re-try reading in request method!!! returnPacket.setPayload("timeout"); diff --git a/bundles/org.smarthomej.binding.snmp/src/test/java/org/smarthomej/binding/snmp/internal/SnmpTargetHandlerTest.java b/bundles/org.smarthomej.binding.snmp/src/test/java/org/smarthomej/binding/snmp/internal/SnmpTargetHandlerTest.java index 3845a64d20..d1cbad449b 100644 --- a/bundles/org.smarthomej.binding.snmp/src/test/java/org/smarthomej/binding/snmp/internal/SnmpTargetHandlerTest.java +++ b/bundles/org.smarthomej.binding.snmp/src/test/java/org/smarthomej/binding/snmp/internal/SnmpTargetHandlerTest.java @@ -73,33 +73,52 @@ public void testChannelsProperlyUpdate() { } @Test - @SuppressWarnings("null") public void testCommandsAreProperlyHandledByNumberChannel() throws IOException { VariableBinding variable; variable = handleCommandNumberStringChannel(SnmpBindingConstants.CHANNEL_TYPE_UID_NUMBER, SnmpDatatype.INT32, new DecimalType(-5), true); - assertNotNull(variable); + + if (variable == null) { + fail("'variable' is null"); + return; + } + assertEquals(new OID(TEST_OID), variable.getOid()); assertTrue(variable.getVariable() instanceof Integer32); assertEquals(-5, ((Integer32) variable.getVariable()).toInt()); variable = handleCommandNumberStringChannel(SnmpBindingConstants.CHANNEL_TYPE_UID_NUMBER, SnmpDatatype.UINT32, new DecimalType(10000), true); - assertNotNull(variable); + + if (variable == null) { + fail("'variable' is null"); + return; + } + assertEquals(new OID(TEST_OID), variable.getOid()); assertTrue(variable.getVariable() instanceof UnsignedInteger32); assertEquals(10000, ((UnsignedInteger32) variable.getVariable()).toInt()); variable = handleCommandNumberStringChannel(SnmpBindingConstants.CHANNEL_TYPE_UID_NUMBER, SnmpDatatype.COUNTER64, new DecimalType(10000), true); - assertNotNull(variable); + + if (variable == null) { + fail("'variable' is null"); + return; + } + assertEquals(new OID(TEST_OID), variable.getOid()); assertTrue(variable.getVariable() instanceof Counter64); assertEquals(10000, ((Counter64) variable.getVariable()).toInt()); variable = handleCommandNumberStringChannel(SnmpBindingConstants.CHANNEL_TYPE_UID_NUMBER, SnmpDatatype.FLOAT, new DecimalType("12.4"), true); - assertNotNull(variable); + + if (variable == null) { + fail("'variable' is null"); + return; + } + assertEquals(new OID(TEST_OID), variable.getOid()); assertTrue(variable.getVariable() instanceof OctetString); assertEquals("12.4", variable.getVariable().toString()); diff --git a/bundles/org.smarthomej.binding.snmp/src/test/java/org/smarthomej/binding/snmp/internal/StringChannelTest.java b/bundles/org.smarthomej.binding.snmp/src/test/java/org/smarthomej/binding/snmp/internal/StringChannelTest.java index 8ff01bb4d2..7c73e9a1ca 100644 --- a/bundles/org.smarthomej.binding.snmp/src/test/java/org/smarthomej/binding/snmp/internal/StringChannelTest.java +++ b/bundles/org.smarthomej.binding.snmp/src/test/java/org/smarthomej/binding/snmp/internal/StringChannelTest.java @@ -43,13 +43,17 @@ public class StringChannelTest extends AbstractSnmpTargetHandlerTest { @Test - @SuppressWarnings("null") public void testCommandsAreProperlyHandledByStringChannel() throws IOException { VariableBinding variable; variable = handleCommandNumberStringChannel(SnmpBindingConstants.CHANNEL_TYPE_UID_STRING, SnmpDatatype.STRING, new StringType(TEST_STRING), true); - assertNotNull(variable); + + if (variable == null) { + fail("'variable' is null"); + return; + } + assertEquals(new OID(TEST_OID), variable.getOid()); assertTrue(variable.getVariable() instanceof OctetString); assertEquals(TEST_STRING, ((OctetString) variable.getVariable()).toString()); @@ -64,14 +68,24 @@ public void testCommandsAreProperlyHandledByStringChannel() throws IOException { variable = handleCommandNumberStringChannel(SnmpBindingConstants.CHANNEL_TYPE_UID_STRING, SnmpDatatype.HEXSTRING, new StringType("AA bf 11"), true); - assertNotNull(variable); + + if (variable == null) { + fail("'variable' is null"); + return; + } + assertEquals(new OID(TEST_OID), variable.getOid()); assertTrue(variable.getVariable() instanceof OctetString); assertEquals("aa bf 11", ((OctetString) variable.getVariable()).toHexString(' ')); variable = handleCommandNumberStringChannel(SnmpBindingConstants.CHANNEL_TYPE_UID_STRING, SnmpDatatype.IPADDRESS, new StringType(TEST_ADDRESS), true); - assertNotNull(variable); + + if (variable == null) { + fail("'variable' is null"); + return; + } + assertEquals(new OID(TEST_OID), variable.getOid()); assertTrue(variable.getVariable() instanceof IpAddress); assertEquals(TEST_ADDRESS, ((IpAddress) variable.getVariable()).toString()); diff --git a/bundles/org.smarthomej.binding.snmp/src/test/java/org/smarthomej/binding/snmp/internal/SwitchChannelTest.java b/bundles/org.smarthomej.binding.snmp/src/test/java/org/smarthomej/binding/snmp/internal/SwitchChannelTest.java index 9951102125..fa558c9fd9 100644 --- a/bundles/org.smarthomej.binding.snmp/src/test/java/org/smarthomej/binding/snmp/internal/SwitchChannelTest.java +++ b/bundles/org.smarthomej.binding.snmp/src/test/java/org/smarthomej/binding/snmp/internal/SwitchChannelTest.java @@ -51,13 +51,23 @@ public void testCommandsAreProperlyHandledBySwitchChannel() throws IOException { VariableBinding variable; variable = handleCommandSwitchChannel(SnmpDatatype.STRING, OnOffType.ON, "on", "off", true); - assertNotNull(variable); + + if (variable == null) { + fail("'variable' is null"); + return; + } + assertEquals(new OID(TEST_OID), variable.getOid()); assertTrue(variable.getVariable() instanceof OctetString); assertEquals("on", ((OctetString) variable.getVariable()).toString()); variable = handleCommandSwitchChannel(SnmpDatatype.STRING, OnOffType.OFF, "on", "off", true); - assertNotNull(variable); + + if (variable == null) { + fail("'variable' is null"); + return; + } + assertEquals(new OID(TEST_OID), variable.getOid()); assertTrue(variable.getVariable() instanceof OctetString); assertEquals("off", ((OctetString) variable.getVariable()).toString()); diff --git a/bundles/org.smarthomej.binding.tr064/src/main/java/org/smarthomej/binding/tr064/internal/Tr064CommunicationException.java b/bundles/org.smarthomej.binding.tr064/src/main/java/org/smarthomej/binding/tr064/internal/Tr064CommunicationException.java index ae9a6d8485..32333f6186 100644 --- a/bundles/org.smarthomej.binding.tr064/src/main/java/org/smarthomej/binding/tr064/internal/Tr064CommunicationException.java +++ b/bundles/org.smarthomej.binding.tr064/src/main/java/org/smarthomej/binding/tr064/internal/Tr064CommunicationException.java @@ -13,7 +13,10 @@ */ package org.smarthomej.binding.tr064.internal; +import java.util.Objects; + import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; /** * The {@link Tr064CommunicationException} is thrown for communication errors @@ -34,10 +37,10 @@ public Tr064CommunicationException(String s) { super(s); } - public Tr064CommunicationException(String s, Integer httpError, String soapError) { + public Tr064CommunicationException(String s, Integer httpError, @Nullable String soapError) { super(s); this.httpError = httpError; - this.soapError = soapError; + this.soapError = Objects.requireNonNullElse(soapError, ""); }; public String getSoapError() { diff --git a/bundles/org.smarthomej.binding.tr064/src/main/java/org/smarthomej/binding/tr064/internal/Tr064RootHandler.java b/bundles/org.smarthomej.binding.tr064/src/main/java/org/smarthomej/binding/tr064/internal/Tr064RootHandler.java index fad3a5234c..ddf0a1311f 100644 --- a/bundles/org.smarthomej.binding.tr064/src/main/java/org/smarthomej/binding/tr064/internal/Tr064RootHandler.java +++ b/bundles/org.smarthomej.binding.tr064/src/main/java/org/smarthomej/binding/tr064/internal/Tr064RootHandler.java @@ -332,20 +332,23 @@ private void installPolling() { private Collection processPhonebookList(SOAPMessage soapMessagePhonebookList, SCPDServiceType scpdService) { SOAPValueConverter soapValueConverter = new SOAPValueConverter(httpClient); - return (Collection) soapValueConverter + Optional> phonebookStream = soapValueConverter .getStateFromSOAPValue(soapMessagePhonebookList, "NewPhonebookList", null) - .map(phonebookList -> Arrays.stream(phonebookList.toString().split(","))).orElse(Stream.empty()) - .map(index -> { - try { - SOAPMessage soapMessageURL = soapConnector.doSOAPRequest( - new SOAPRequest(scpdService, "GetPhonebook", Map.of("NewPhonebookID", index))); - return soapValueConverter.getStateFromSOAPValue(soapMessageURL, "NewPhonebookURL", null) - .map(url -> (Phonebook) new Tr064PhonebookImpl(httpClient, url.toString())); - } catch (Tr064CommunicationException e) { - logger.warn("Failed to get phonebook with index {}:", index, e); - } - return Optional.empty(); - }).filter(Optional::isPresent).map(Optional::get).collect(Collectors.toList()); + .map(phonebookList -> Arrays.stream(phonebookList.toString().split(","))); + if (!phonebookStream.isPresent()) { + return Set.of(); + } + return (Collection) phonebookStream.get().map(index -> { + try { + SOAPMessage soapMessageURL = soapConnector + .doSOAPRequest(new SOAPRequest(scpdService, "GetPhonebook", Map.of("NewPhonebookID", index))); + return soapValueConverter.getStateFromSOAPValue(soapMessageURL, "NewPhonebookURL", null) + .map(url -> (Phonebook) new Tr064PhonebookImpl(httpClient, url.toString())); + } catch (Tr064CommunicationException e) { + logger.warn("Failed to get phonebook with index {}:", index, e); + } + return Optional.empty(); + }).filter(Optional::isPresent).map(Optional::get).collect(Collectors.toList()); } private void retrievePhonebooks() { @@ -358,14 +361,14 @@ private void retrievePhonebooks() { Optional scpdService = scpdUtil.getDevice("").flatMap(deviceType -> deviceType.getServiceList() .stream().filter(service -> service.getServiceId().equals(serviceId)).findFirst()); - phonebooks = scpdService.map(service -> { + phonebooks = Objects.requireNonNull(scpdService.map(service -> { try { return processPhonebookList(soapConnector.doSOAPRequest(new SOAPRequest(service, "GetPhonebookList")), service); } catch (Tr064CommunicationException e) { return Collections. emptyList(); } - }).orElse(List.of()); + }).orElse(List.of())); if (phonebooks.isEmpty()) { logger.warn("Could not get phonebooks for thing {}", thing.getUID()); diff --git a/bundles/org.smarthomej.binding.tr064/src/main/java/org/smarthomej/binding/tr064/internal/Tr064SubHandler.java b/bundles/org.smarthomej.binding.tr064/src/main/java/org/smarthomej/binding/tr064/internal/Tr064SubHandler.java index c289e8067b..a645f9803c 100644 --- a/bundles/org.smarthomej.binding.tr064/src/main/java/org/smarthomej/binding/tr064/internal/Tr064SubHandler.java +++ b/bundles/org.smarthomej.binding.tr064/src/main/java/org/smarthomej/binding/tr064/internal/Tr064SubHandler.java @@ -73,7 +73,6 @@ public class Tr064SubHandler extends BaseThingHandler { } @Override - @SuppressWarnings("null") public void handleCommand(ChannelUID channelUID, Command command) { Tr064ChannelConfig channelConfig = channels.get(channelUID); if (channelConfig == null) { @@ -82,6 +81,7 @@ public void handleCommand(ChannelUID channelUID, Command command) { } if (command instanceof RefreshType) { + final SOAPConnector soapConnector = this.soapConnector; State state = stateCache.putIfAbsentAndGet(channelUID, () -> soapConnector == null ? UnDefType.UNDEF : soapConnector.getChannelStateFromDevice(channelConfig, channels, stateCache)); if (state != null) { @@ -95,6 +95,7 @@ public void handleCommand(ChannelUID channelUID, Command command) { return; } scheduler.execute(() -> { + final SOAPConnector soapConnector = this.soapConnector; if (soapConnector == null) { logger.warn("Could not send command because connector not available"); } else { diff --git a/bundles/org.smarthomej.binding.tr064/src/main/java/org/smarthomej/binding/tr064/internal/phonebook/PhonebookActions.java b/bundles/org.smarthomej.binding.tr064/src/main/java/org/smarthomej/binding/tr064/internal/phonebook/PhonebookActions.java index cd46d88569..6a3548994f 100644 --- a/bundles/org.smarthomej.binding.tr064/src/main/java/org/smarthomej/binding/tr064/internal/phonebook/PhonebookActions.java +++ b/bundles/org.smarthomej.binding.tr064/src/main/java/org/smarthomej/binding/tr064/internal/phonebook/PhonebookActions.java @@ -77,12 +77,12 @@ public class PhonebookActions implements ThingActions { } else { int matchCountInt = matchCount == null ? 0 : matchCount; if (phonebook != null && !phonebook.isEmpty()) { - return handler.getPhonebookByName(phonebook).flatMap(p -> p.lookupNumber(phonenumber, matchCountInt)) - .orElse(phonenumber); + return Objects.requireNonNull(handler.getPhonebookByName(phonebook) + .flatMap(p -> p.lookupNumber(phonenumber, matchCountInt)).orElse(phonenumber)); } else { Collection phonebooks = handler.getPhonebooks(); - return phonebooks.stream().map(p -> p.lookupNumber(phonenumber, matchCountInt)) - .filter(Optional::isPresent).map(Optional::get).findAny().orElse(phonenumber); + return Objects.requireNonNull(phonebooks.stream().map(p -> p.lookupNumber(phonenumber, matchCountInt)) + .filter(Optional::isPresent).map(Optional::get).findAny().orElse(phonenumber)); } } } diff --git a/bundles/org.smarthomej.binding.tr064/src/main/java/org/smarthomej/binding/tr064/internal/phonebook/PhonebookProfile.java b/bundles/org.smarthomej.binding.tr064/src/main/java/org/smarthomej/binding/tr064/internal/phonebook/PhonebookProfile.java index b3002b2850..27d9856b7b 100644 --- a/bundles/org.smarthomej.binding.tr064/src/main/java/org/smarthomej/binding/tr064/internal/phonebook/PhonebookProfile.java +++ b/bundles/org.smarthomej.binding.tr064/src/main/java/org/smarthomej/binding/tr064/internal/phonebook/PhonebookProfile.java @@ -15,6 +15,7 @@ import java.math.BigDecimal; import java.util.Map; +import java.util.Objects; import java.util.Optional; import org.eclipse.jdt.annotation.NonNullByDefault; @@ -139,7 +140,7 @@ public void onStateUpdateFromHandler(State state) { } if (state instanceof StringType) { Optional match = resolveNumber(state.toString()); - State newState = match.map(name -> (State) new StringType(name)).orElse(state); + State newState = Objects.requireNonNull(match.map(name -> (State) new StringType(name)).orElse(state)); if (newState == state) { logger.debug("Number '{}' not found in phonebook '{}' from provider '{}'", state, phonebookName, thingUID); diff --git a/bundles/org.smarthomej.persistence.influxdb/src/main/java/org/smarthomej/persistence/influxdb/internal/InfluxPoint.java b/bundles/org.smarthomej.persistence.influxdb/src/main/java/org/smarthomej/persistence/influxdb/internal/InfluxPoint.java index a048df2e58..6c7ea90115 100644 --- a/bundles/org.smarthomej.persistence.influxdb/src/main/java/org/smarthomej/persistence/influxdb/internal/InfluxPoint.java +++ b/bundles/org.smarthomej.persistence.influxdb/src/main/java/org/smarthomej/persistence/influxdb/internal/InfluxPoint.java @@ -19,6 +19,7 @@ import java.util.Map; import org.eclipse.jdt.annotation.DefaultLocation; +import org.eclipse.jdt.annotation.NonNull; import org.eclipse.jdt.annotation.NonNullByDefault; /** @@ -91,7 +92,7 @@ public InfluxPoint build() { } @Override - public String toString() { + public @NonNull String toString() { return "InfluxPoint{" + "measurementName='" + measurementName + '\'' + ", time=" + time + ", value=" + value + ", tags=" + tags + '}'; } diff --git a/bundles/org.smarthomej.persistence.influxdb/src/main/java/org/smarthomej/persistence/influxdb/internal/influx2/InfluxDB2RepositoryImpl.java b/bundles/org.smarthomej.persistence.influxdb/src/main/java/org/smarthomej/persistence/influxdb/internal/influx2/InfluxDB2RepositoryImpl.java index 85bffe6e80..5c8b380149 100644 --- a/bundles/org.smarthomej.persistence.influxdb/src/main/java/org/smarthomej/persistence/influxdb/internal/influx2/InfluxDB2RepositoryImpl.java +++ b/bundles/org.smarthomej.persistence.influxdb/src/main/java/org/smarthomej/persistence/influxdb/internal/influx2/InfluxDB2RepositoryImpl.java @@ -16,10 +16,7 @@ import static org.smarthomej.persistence.influxdb.internal.InfluxDBConstants.*; import java.time.Instant; -import java.util.Collections; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -219,9 +216,10 @@ public Map getStoredItemsCount() { + " |> group()"; List queryResult = currentQueryAPI.query(query); - queryResult.stream().findFirst().orElse(new FluxTable()).getRecords().forEach(row -> { - result.put((String) row.getValueByKey(TAG_ITEM_NAME), ((Number) row.getValue()).intValue()); - }); + Objects.requireNonNull(queryResult.stream().findFirst().orElse(new FluxTable())).getRecords() + .forEach(row -> { + result.put((String) row.getValueByKey(TAG_ITEM_NAME), ((Number) row.getValue()).intValue()); + }); return result; } else { logger.warn("Returning empty result because queryAPI isn't present"); diff --git a/bundles/org.smarthomej.persistence.influxdb/src/test/java/org/smarthomej/persistence/influxdb/internal/ItemToStorePointCreatorTest.java b/bundles/org.smarthomej.persistence.influxdb/src/test/java/org/smarthomej/persistence/influxdb/internal/ItemToStorePointCreatorTest.java index 48abd293da..1a34ac4b09 100644 --- a/bundles/org.smarthomej.persistence.influxdb/src/test/java/org/smarthomej/persistence/influxdb/internal/ItemToStorePointCreatorTest.java +++ b/bundles/org.smarthomej.persistence.influxdb/src/test/java/org/smarthomej/persistence/influxdb/internal/ItemToStorePointCreatorTest.java @@ -24,6 +24,7 @@ import org.eclipse.jdt.annotation.DefaultLocation; import org.eclipse.jdt.annotation.NonNullByDefault; import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -41,7 +42,6 @@ * @author Joan Pujol Espinar - Initial contribution */ @ExtendWith(MockitoExtension.class) -@SuppressWarnings("null") // In case of any NPE it will cause test fail that it's the expected result @NonNullByDefault(value = { DefaultLocation.PARAMETER, DefaultLocation.RETURN_TYPE }) public class ItemToStorePointCreatorTest { @@ -72,6 +72,11 @@ public void convertBasicItem(Number number) { NumberItem item = ItemTestHelper.createNumberItem("myitem", number); InfluxPoint point = instance.convert(item, null); + if (point == null) { + Assertions.fail("'point' is null"); + return; + } + assertThat(point.getMeasurementName(), equalTo(item.getName())); assertThat("Must Store item name", point.getTags(), hasEntry("item", item.getName())); assertThat(point.getValue(), equalTo(new BigDecimal(number.toString()))); @@ -85,6 +90,12 @@ private static Stream convertBasicItem() { public void shouldUseAliasAsMeasurementNameIfProvided() { NumberItem item = ItemTestHelper.createNumberItem("myitem", 5); InfluxPoint point = instance.convert(item, "aliasName"); + + if (point == null) { + Assertions.fail("'point' is null"); + return; + } + assertThat(point.getMeasurementName(), is("aliasName")); } @@ -95,10 +106,22 @@ public void shouldStoreCategoryTagIfProvidedAndConfigured() { when(influxDBConfiguration.isAddCategoryTag()).thenReturn(true); InfluxPoint point = instance.convert(item, null); + + if (point == null) { + Assertions.fail("'point' is null"); + return; + } + assertThat(point.getTags(), hasEntry(InfluxDBConstants.TAG_CATEGORY_NAME, "categoryValue")); when(influxDBConfiguration.isAddCategoryTag()).thenReturn(false); point = instance.convert(item, null); + + if (point == null) { + Assertions.fail("'point' is null"); + return; + } + assertThat(point.getTags(), not(hasKey(InfluxDBConstants.TAG_CATEGORY_NAME))); } @@ -108,10 +131,22 @@ public void shouldStoreTypeTagIfProvidedAndConfigured() { when(influxDBConfiguration.isAddTypeTag()).thenReturn(true); InfluxPoint point = instance.convert(item, null); + + if (point == null) { + Assertions.fail("'point' is null"); + return; + } + assertThat(point.getTags(), hasEntry(InfluxDBConstants.TAG_TYPE_NAME, "Number")); when(influxDBConfiguration.isAddTypeTag()).thenReturn(false); point = instance.convert(item, null); + + if (point == null) { + Assertions.fail("'point' is null"); + return; + } + assertThat(point.getTags(), not(hasKey(InfluxDBConstants.TAG_TYPE_NAME))); } @@ -122,10 +157,22 @@ public void shouldStoreTypeLabelIfProvidedAndConfigured() { when(influxDBConfiguration.isAddLabelTag()).thenReturn(true); InfluxPoint point = instance.convert(item, null); + + if (point == null) { + Assertions.fail("'point' is null"); + return; + } + assertThat(point.getTags(), hasEntry(InfluxDBConstants.TAG_LABEL_NAME, "ItemLabel")); when(influxDBConfiguration.isAddLabelTag()).thenReturn(false); point = instance.convert(item, null); + + if (point == null) { + Assertions.fail("'point' is null"); + return; + } + assertThat(point.getTags(), not(hasKey(InfluxDBConstants.TAG_LABEL_NAME))); } @@ -138,6 +185,12 @@ public void shouldStoreMetadataAsTagsIfProvided() { .thenReturn(new Metadata(metadataKey, "", Map.of("key1", "val1", "key2", "val2"))); InfluxPoint point = instance.convert(item, null); + + if (point == null) { + Assertions.fail("'point' is null"); + return; + } + assertThat(point.getTags(), hasEntry("key1", "val1")); assertThat(point.getTags(), hasEntry("key2", "val2")); } diff --git a/pom.xml b/pom.xml index 7976f6d9c7..efbec90b06 100644 --- a/pom.xml +++ b/pom.xml @@ -80,7 +80,7 @@ 3.0.0 5.3.0 3.7.2 - 2.2.1 + 2.3.0 4.2.7 0.10.0 1.7.21 @@ -302,11 +302,8 @@ Import-Package: \\ CLASSPATH ${project.build.directory}/dependency + ${basedirRoot}/tools/org.eclipse.jdt.core.prefs - - -err:+nullAnnot(org.eclipse.jdt.annotation.Nullable|org.eclipse.jdt.annotation.NonNull|org.eclipse.jdt.annotation.NonNullByDefault),+inheritNullAnnot,+nullAnnotConflict,-nullUncheckedConversion - -warn:+null,+inheritNullAnnot,-nullUncheckedConversion,+nullAnnotRedundant,+nullDereference - true true diff --git a/tools/org.eclipse.jdt.core.prefs b/tools/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000000..472a3d28d0 --- /dev/null +++ b/tools/org.eclipse.jdt.core.prefs @@ -0,0 +1,25 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.annotation.inheritNullAnnotations=warning +org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore +org.eclipse.jdt.core.compiler.annotation.nonnull=org.eclipse.jdt.annotation.NonNull +org.eclipse.jdt.core.compiler.annotation.nonnull.secondary= +org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annotation.NonNullByDefault +org.eclipse.jdt.core.compiler.annotation.nonnullbydefault.secondary= +org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable +org.eclipse.jdt.core.compiler.annotation.nullable.secondary= +org.eclipse.jdt.core.compiler.annotation.nullanalysis=enabled +org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=enabled +org.eclipse.jdt.core.compiler.problem.nonnullParameterAnnotationDropped=warning +org.eclipse.jdt.core.compiler.problem.nonnullTypeVariableFromLegacyInvocation=warning +org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=error +org.eclipse.jdt.core.compiler.problem.nullReference=error +org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error +org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=info +org.eclipse.jdt.core.compiler.problem.pessimisticNullAnalysisForFreeTypeVariables=warning +org.eclipse.jdt.core.compiler.problem.potentialNullReference=error +org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning +org.eclipse.jdt.core.compiler.problem.redundantNullCheck=warning +org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled +org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled +org.eclipse.jdt.core.compiler.problem.suppressWarningsNotFullyAnalysed=info +org.eclipse.jdt.core.compiler.problem.syntacticNullAnalysisForFields=disabled \ No newline at end of file