Another warning hunting session (#4484)

* Another warning hunting session, focusing on Potential null pointer access

Signed-off-by: Gaël L'hopital <gael@lhopital.org>
pull/4541/head
Gaël L'hopital 2025-01-06 18:49:45 +01:00 committed by GitHub
parent 1e0b3c2410
commit 13eeea96e8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
16 changed files with 69 additions and 61 deletions

View File

@ -82,11 +82,12 @@ public abstract class AbstractEvent implements Event {
if (!payload.equals(other.payload)) {
return false;
}
if (source == null) {
String localSource = source;
if (localSource == null) {
if (other.source != null) {
return false;
}
} else if (!source.equals(other.source)) {
} else if (!localSource.equals(other.source)) {
return false;
}
if (!topic.equals(other.topic)) {

View File

@ -16,6 +16,7 @@ import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Collection;
import java.util.Objects;
import java.util.concurrent.ExecutionException;
import java.util.function.Consumer;
import java.util.stream.Collectors;
@ -98,13 +99,14 @@ abstract class AbstractInvocationHandler<T> {
void handleException(Method method, InvocationTargetException e) {
Throwable cause = e.getCause();
logger.error(MSG_ERROR, toString(method), target, cause == null ? "" : cause.getMessage(), e.getCause());
if (exceptionHandler != null) {
exceptionHandler.accept(cause == null ? e : cause);
Consumer<Throwable> localConsumer = exceptionHandler;
if (localConsumer != null) {
localConsumer.accept(cause == null ? e : cause);
}
}
void handleDuplicate(Method method, DuplicateExecutionException e) {
Thread thread = e.getCallable().getThread();
Thread thread = Objects.requireNonNull(e.getCallable().getThread());
logger.debug(MSG_DUPLICATE, toString(method), target, toString(e.getCallable().getMethod()), thread.getName(),
thread.getId(), thread.getState().toString(), getStacktrace(thread));
}

View File

@ -101,16 +101,15 @@ public class MetadataStateDescriptionFragmentProvider implements StateDescriptio
builder.withReadOnly(getBoolean(readOnly));
}
if (metadata.getConfiguration().containsKey("options")) {
List<StateOption> stateOptions = Stream
.of(metadata.getConfiguration().get("options").toString().split(",")).map(o -> {
if (o.contains("=")) {
var pair = parseValueLabelPair(o.trim());
return new StateOption(pair[0], pair[1]);
} else {
return new StateOption(o.trim(), null);
}
}).toList();
if (metadata.getConfiguration().get("options") instanceof Object options) {
List<StateOption> stateOptions = Stream.of(options.toString().split(",")).map(o -> {
if (o.contains("=")) {
var pair = parseValueLabelPair(o.trim());
return new StateOption(pair[0], pair[1]);
} else {
return new StateOption(o.trim(), null);
}
}).toList();
builder.withOptions(stateOptions);
}

View File

@ -34,6 +34,7 @@ import tech.units.indriya.function.Calculus;
*/
@NonNullByDefault
public class CurrencyConverter extends AbstractConverter {
private static final long serialVersionUID = 1L;
private final BigDecimal factor;
@ -103,7 +104,7 @@ public class CurrencyConverter extends AbstractConverter {
@SuppressWarnings("unchecked")
Map<Class<? extends AbstractConverter>, Integer> original = (Map<Class<? extends AbstractConverter>, Integer>) field
.get(null);
original.put(CurrencyConverter.class, 1000);
Objects.requireNonNull(original).put(CurrencyConverter.class, 1000);
} catch (NoSuchFieldException | IllegalAccessException e) {
throw new IllegalStateException("Could not add currency converter", e);
}

View File

@ -206,8 +206,8 @@ public class SchedulerImpl implements Scheduler {
exceptionally(e -> {
synchronized (this) {
if (e instanceof CancellationException) {
if (scheduledPromise != null) {
scheduledPromise.cancel(true);
if (scheduledPromise instanceof ScheduledCompletableFuture promise) {
promise.cancel(true);
}
}
}
@ -222,7 +222,7 @@ public class SchedulerImpl implements Scheduler {
future.cancel(true);
} else {
scheduledPromise = future;
scheduledPromise.getPromise().exceptionally(ex -> {
future.getPromise().exceptionally(ex -> {
// if an error occurs in the scheduled job propagate to parent
ScheduledCompletableFutureRecurring.this.completeExceptionally(ex);
return null;
@ -233,12 +233,13 @@ public class SchedulerImpl implements Scheduler {
@Override
public long getDelay(@Nullable TimeUnit timeUnit) {
return scheduledPromise != null ? scheduledPromise.getDelay(timeUnit) : 0;
return scheduledPromise instanceof ScheduledCompletableFuture promise ? promise.getDelay(timeUnit) : 0;
}
@Override
public ZonedDateTime getScheduledTime() {
return scheduledPromise != null ? scheduledPromise.getScheduledTime() : super.getScheduledTime();
return scheduledPromise instanceof ScheduledCompletableFuture promise ? promise.getScheduledTime()
: super.getScheduledTime();
}
}

View File

@ -14,6 +14,7 @@ package org.openhab.core.internal.service;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.locks.ReentrantReadWriteLock;
@ -114,7 +115,7 @@ public class ReadyServiceImpl implements ReadyService {
}
private void notifyTracker(ReadyTracker readyTracker, Consumer<ReadyMarker> action) {
ReadyMarkerFilter f = trackers.get(readyTracker);
ReadyMarkerFilter f = Objects.requireNonNull(trackers.get(readyTracker));
markers.stream().filter(f::apply).forEach(action);
}
}

View File

@ -195,7 +195,8 @@ public class StateDescriptionFragmentImpl implements StateDescriptionFragment {
if (readOnly == null) {
readOnly = fragment.isReadOnly();
}
if (options == null || options.isEmpty()) {
List<StateOption> localOptions = options;
if (localOptions == null || localOptions.isEmpty()) {
options = fragment.getOptions();
}
return this;
@ -205,12 +206,12 @@ public class StateDescriptionFragmentImpl implements StateDescriptionFragment {
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + (minimum != null ? minimum.hashCode() : 0);
result = prime * result + (maximum != null ? maximum.hashCode() : 0);
result = prime * result + (step != null ? step.hashCode() : 0);
result = prime * result + (pattern != null ? pattern.hashCode() : 0);
result = prime * result + Objects.hashCode(minimum);
result = prime * result + Objects.hashCode(maximum);
result = prime * result + Objects.hashCode(step);
result = prime * result + Objects.hashCode(pattern);
result = prime * result + (readOnly ? 1231 : 1237);
result = prime * result + (options != null ? options.hashCode() : 0);
result = prime * result + Objects.hashCode(options);
return result;
}

View File

@ -192,8 +192,8 @@ public abstract class GenericItem implements ActiveItem {
protected void internalSend(Command command) {
// try to send the command to the bus
if (eventPublisher != null) {
eventPublisher.post(ItemEventFactory.createCommandEvent(this.getName(), command));
if (eventPublisher instanceof EventPublisher publisher) {
publisher.post(ItemEventFactory.createCommandEvent(this.getName(), command));
}
}
@ -456,8 +456,8 @@ public abstract class GenericItem implements ActiveItem {
@Override
public @Nullable StateDescription getStateDescription(@Nullable Locale locale) {
if (stateDescriptionService != null) {
return stateDescriptionService.getStateDescription(this.name, locale);
if (stateDescriptionService instanceof StateDescriptionService service) {
return service.getStateDescription(this.name, locale);
}
return null;
}
@ -499,8 +499,8 @@ public abstract class GenericItem implements ActiveItem {
}
protected @Nullable CommandDescription getCommandOptions(@Nullable Locale locale) {
if (commandDescriptionService != null) {
CommandDescription commandDescription = commandDescriptionService.getCommandDescription(this.name, locale);
if (commandDescriptionService instanceof CommandDescriptionService service) {
CommandDescription commandDescription = service.getCommandDescription(this.name, locale);
if (commandDescription != null) {
return commandDescription;
}

View File

@ -224,8 +224,8 @@ public class GroupItem extends GenericItem implements StateChangeListener, Metad
*/
@Override
public List<Class<? extends State>> getAcceptedDataTypes() {
if (baseItem != null) {
return baseItem.getAcceptedDataTypes();
if (baseItem instanceof Item item) {
return item.getAcceptedDataTypes();
} else {
List<Class<? extends State>> acceptedDataTypes = null;
@ -249,8 +249,8 @@ public class GroupItem extends GenericItem implements StateChangeListener, Metad
*/
@Override
public List<Class<? extends Command>> getAcceptedCommandTypes() {
if (baseItem != null) {
return baseItem.getAcceptedCommandTypes();
if (baseItem instanceof Item item) {
return item.getAcceptedCommandTypes();
} else {
List<Class<? extends Command>> acceptedCommandTypes = null;
@ -289,8 +289,8 @@ public class GroupItem extends GenericItem implements StateChangeListener, Metad
// if a group does not have a function it cannot have a state
@Nullable
T newState = null;
if (function != null) {
newState = function.getStateAs(getStateMembers(getMembers()), typeClass);
if (function instanceof GroupFunction groupFunction) {
newState = groupFunction.getStateAs(getStateMembers(getMembers()), typeClass);
}
Item baseItem = this.baseItem;
@ -354,8 +354,8 @@ public class GroupItem extends GenericItem implements StateChangeListener, Metad
State oldState = this.state;
State newState = oldState;
ItemStateConverter itemStateConverter = this.itemStateConverter;
if (function != null && baseItem != null && itemStateConverter != null) {
State calculatedState = function.calculate(getStateMembers(getMembers()));
if (function instanceof GroupFunction groupFunction && baseItem != null && itemStateConverter != null) {
State calculatedState = groupFunction.calculate(getStateMembers(getMembers()));
newState = itemStateConverter.convertToAcceptedState(calculatedState, baseItem);
setState(newState);
sendGroupStateUpdatedEvent(item.getName(), newState);

View File

@ -252,8 +252,8 @@ public class ManagedItemProvider extends AbstractManagedProvider<Item, String, P
private GroupFunction getGroupFunction(PersistedItem persistedItem, @Nullable Item baseItem) {
GroupFunctionDTO functionDTO = new GroupFunctionDTO();
functionDTO.name = persistedItem.functionName;
if (persistedItem.functionParams != null) {
functionDTO.params = persistedItem.functionParams.toArray(new String[persistedItem.functionParams.size()]);
if (persistedItem.functionParams instanceof List<?> list) {
functionDTO.params = list.toArray(new String[list.size()]);
}
return ItemDTOMapper.mapFunction(baseItem, functionDTO);
}

View File

@ -147,12 +147,14 @@ public interface QuantityTypeArithmeticGroupFunction extends GroupFunction {
if (unit == null) {
unit = itemState.getUnit(); // set it to the first item's unit
}
values.add(itemState.toInvertibleUnit(unit).toBigDecimal());
if (itemState.toInvertibleUnit(unit) instanceof QuantityType<?> inverted) {
values.add(inverted.toBigDecimal());
}
}
if (!values.isEmpty()) {
BigDecimal median = Statistics.median(values);
if (median != null) {
if (median != null && unit != null) {
return new QuantityType<>(median, unit);
}

View File

@ -176,8 +176,8 @@ public final class CurrencyUnit extends AbstractUnit<Currency> {
return nameCompare;
}
String thatSymbol = that.getSymbol();
if (symbol != null && thatSymbol != null) {
return symbol.compareTo(thatSymbol);
if (symbol instanceof String localSymbol && thatSymbol != null) {
return localSymbol.compareTo(thatSymbol);
} else if (symbol != null) {
return 1;
} else if (thatSymbol != null) {

View File

@ -111,8 +111,8 @@ public class NetUtil implements NetworkAddressService {
lastKnownInterfaceAddresses = List.of();
networkAddressChangeListeners = ConcurrentHashMap.newKeySet();
if (networkInterfacePollFuture != null) {
networkInterfacePollFuture.cancel(true);
if (networkInterfacePollFuture instanceof ScheduledFuture<?> future) {
future.cancel(true);
networkInterfacePollFuture = null;
}
}
@ -159,13 +159,13 @@ public class NetUtil implements NetworkAddressService {
public @Nullable String getPrimaryIpv4HostAddress() {
String primaryIP;
if (primaryAddress != null) {
String[] addrString = primaryAddress.split("/");
if (primaryAddress instanceof String address) {
String[] addrString = address.split("/");
if (addrString.length > 1) {
String ip = getIPv4inSubnet(addrString[0], addrString[1]);
if (ip == null) {
// an error has occurred, using first interface like nothing has been configured
LOGGER.warn("Invalid address '{}', will use first interface instead.", primaryAddress);
LOGGER.warn("Invalid address '{}', will use first interface instead.", address);
primaryIP = getFirstLocalIPv4Address();
} else {
primaryIP = ip;
@ -513,8 +513,8 @@ public class NetUtil implements NetworkAddressService {
}
private void scheduleToPollNetworkInterface(int intervalInSeconds) {
if (networkInterfacePollFuture != null) {
networkInterfacePollFuture.cancel(true);
if (networkInterfacePollFuture instanceof ScheduledFuture<?> future) {
future.cancel(true);
networkInterfacePollFuture = null;
}

View File

@ -70,7 +70,7 @@ public class CommandOption {
final int prime = 31;
int result = 1;
result = prime * result + command.hashCode();
result = prime * result + (label != null ? label.hashCode() : 0);
result = prime * result + Objects.hashCode(label);
return result;
}

View File

@ -116,10 +116,10 @@ public class StateDescription {
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + (minimum != null ? minimum.hashCode() : 0);
result = prime * result + (maximum != null ? maximum.hashCode() : 0);
result = prime * result + (step != null ? step.hashCode() : 0);
result = prime * result + (pattern != null ? pattern.hashCode() : 0);
result = prime * result + Objects.hashCode(minimum);
result = prime * result + Objects.hashCode(maximum);
result = prime * result + Objects.hashCode(step);
result = prime * result + Objects.hashCode(pattern);
result = prime * result + (readOnly ? 1231 : 1237);
result = prime * result + options.hashCode();
return result;

View File

@ -62,7 +62,7 @@ public final class StateOption {
final int prime = 31;
int result = 1;
result = prime * result + value.hashCode();
result = prime * result + (label != null ? label.hashCode() : 0);
result = prime * result + Objects.hashCode(label);
return result;
}