Browse Source

Improve null-safety of module/spring-boot-actuator

See gh-46926
pull/46973/head
Moritz Halbritter 4 months ago
parent
commit
2907fec181
  1. 1
      config/checkstyle/checkstyle-suppressions.xml
  2. 12
      module/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/audit/AuditEvent.java
  3. 6
      module/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/audit/listener/AuditApplicationEvent.java
  4. 2
      module/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/availability/AvailabilityStateHealthIndicator.java
  5. 10
      module/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/beans/BeansEndpoint.java
  6. 49
      module/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/context/properties/ConfigurationPropertiesReportEndpoint.java
  7. 2
      module/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/InvocationContext.java
  8. 4
      module/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/OperationArgumentResolver.java
  9. 4
      module/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/ProducibleOperationArgumentResolver.java
  10. 6
      module/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/SanitizableData.java
  11. 7
      module/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/SanitizingFunction.java
  12. 12
      module/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/annotation/EndpointDiscoverer.java
  13. 2
      module/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/web/PathMappedEndpoints.java
  14. 19
      module/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/env/EnvironmentEndpoint.java
  15. 3
      module/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/HealthEndpointGroups.java
  16. 2
      module/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/SimpleStatusAggregator.java
  17. 14
      module/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/info/InfoPropertiesInfoContributor.java
  18. 8
      module/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/security/AuthenticationAuditListener.java
  19. 2
      module/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/security/AuthorizationAuditListener.java
  20. 4
      module/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/ssl/SslHealthIndicator.java
  21. 8
      module/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/web/mappings/MappingsEndpoint.java

1
config/checkstyle/checkstyle-suppressions.xml

@ -75,4 +75,5 @@ @@ -75,4 +75,5 @@
<suppress files="ConditionMessage\.java" checks="NoWhitespaceBefore" message="'...' is preceded with whitespace"/>
<suppress files="EntityManagerFactoryBuilder\.java" checks="NoWhitespaceBefore" message="'...' is preceded with whitespace"/>
<suppress files="DockerApi\.java" checks="NoWhitespaceBefore" message="'...' is preceded with whitespace"/>
<suppress files="InvocationContext\.java" checks="NoWhitespaceBefore" message="'...' is preceded with whitespace"/>
</suppressions>

12
module/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/audit/AuditEvent.java

@ -53,7 +53,7 @@ public class AuditEvent implements Serializable { @@ -53,7 +53,7 @@ public class AuditEvent implements Serializable {
private final String type;
private final Map<String, Object> data;
private final Map<String, @Nullable Object> data;
/**
* Create a new audit event for the current time.
@ -61,7 +61,7 @@ public class AuditEvent implements Serializable { @@ -61,7 +61,7 @@ public class AuditEvent implements Serializable {
* @param type the event type
* @param data the event data
*/
public AuditEvent(String principal, String type, Map<String, Object> data) {
public AuditEvent(String principal, String type, Map<String, @Nullable Object> data) {
this(Instant.now(), principal, type, data);
}
@ -83,7 +83,7 @@ public class AuditEvent implements Serializable { @@ -83,7 +83,7 @@ public class AuditEvent implements Serializable {
* @param type the event type
* @param data the event data
*/
public AuditEvent(Instant timestamp, @Nullable String principal, String type, Map<String, Object> data) {
public AuditEvent(Instant timestamp, @Nullable String principal, String type, Map<String, @Nullable Object> data) {
Assert.notNull(timestamp, "'timestamp' must not be null");
Assert.notNull(type, "'type' must not be null");
this.timestamp = timestamp;
@ -92,8 +92,8 @@ public class AuditEvent implements Serializable { @@ -92,8 +92,8 @@ public class AuditEvent implements Serializable {
this.data = Collections.unmodifiableMap(data);
}
private static Map<String, Object> convert(String[] data) {
Map<String, Object> result = new HashMap<>();
private static Map<String, @Nullable Object> convert(String[] data) {
Map<String, @Nullable Object> result = new HashMap<>();
for (String entry : data) {
int index = entry.indexOf('=');
if (index != -1) {
@ -135,7 +135,7 @@ public class AuditEvent implements Serializable { @@ -135,7 +135,7 @@ public class AuditEvent implements Serializable {
* Returns the event data.
* @return the event data
*/
public Map<String, Object> getData() {
public Map<String, @Nullable Object> getData() {
return this.data;
}

6
module/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/audit/listener/AuditApplicationEvent.java

@ -19,6 +19,8 @@ package org.springframework.boot.actuate.audit.listener; @@ -19,6 +19,8 @@ package org.springframework.boot.actuate.audit.listener;
import java.time.Instant;
import java.util.Map;
import org.jspecify.annotations.Nullable;
import org.springframework.boot.actuate.audit.AuditEvent;
import org.springframework.context.ApplicationEvent;
import org.springframework.util.Assert;
@ -41,7 +43,7 @@ public class AuditApplicationEvent extends ApplicationEvent { @@ -41,7 +43,7 @@ public class AuditApplicationEvent extends ApplicationEvent {
* @param data the event data
* @see AuditEvent#AuditEvent(String, String, Map)
*/
public AuditApplicationEvent(String principal, String type, Map<String, Object> data) {
public AuditApplicationEvent(String principal, String type, Map<String, @Nullable Object> data) {
this(new AuditEvent(principal, type, data));
}
@ -66,7 +68,7 @@ public class AuditApplicationEvent extends ApplicationEvent { @@ -66,7 +68,7 @@ public class AuditApplicationEvent extends ApplicationEvent {
* @param data the event data
* @see AuditEvent#AuditEvent(Instant, String, String, Map)
*/
public AuditApplicationEvent(Instant timestamp, String principal, String type, Map<String, Object> data) {
public AuditApplicationEvent(Instant timestamp, String principal, String type, Map<String, @Nullable Object> data) {
this(new AuditEvent(timestamp, principal, type, data));
}

2
module/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/availability/AvailabilityStateHealthIndicator.java

@ -45,7 +45,7 @@ public class AvailabilityStateHealthIndicator extends AbstractHealthIndicator { @@ -45,7 +45,7 @@ public class AvailabilityStateHealthIndicator extends AbstractHealthIndicator {
private final Class<? extends AvailabilityState> stateType;
private final Map<AvailabilityState, Status> statusMappings = new HashMap<>();
private final Map<@Nullable AvailabilityState, Status> statusMappings = new HashMap<>();
/**
* Create a new {@link AvailabilityStateHealthIndicator} instance.

10
module/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/beans/BeansEndpoint.java

@ -29,6 +29,7 @@ import org.springframework.boot.actuate.endpoint.annotation.Endpoint; @@ -29,6 +29,7 @@ import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
import org.springframework.boot.actuate.endpoint.annotation.ReadOperation;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.lang.Contract;
import org.springframework.util.StringUtils;
/**
@ -56,7 +57,7 @@ public class BeansEndpoint { @@ -56,7 +57,7 @@ public class BeansEndpoint {
@ReadOperation
public BeansDescriptor beans() {
Map<String, ContextBeansDescriptor> contexts = new HashMap<>();
Map<@Nullable String, ContextBeansDescriptor> contexts = new HashMap<>();
ConfigurableApplicationContext context = this.context;
while (context != null) {
contexts.put(context.getId(), ContextBeansDescriptor.describing(context));
@ -79,13 +80,13 @@ public class BeansEndpoint { @@ -79,13 +80,13 @@ public class BeansEndpoint {
*/
public static final class BeansDescriptor implements OperationResponseBody {
private final Map<String, ContextBeansDescriptor> contexts;
private final Map<@Nullable String, ContextBeansDescriptor> contexts;
private BeansDescriptor(Map<String, ContextBeansDescriptor> contexts) {
private BeansDescriptor(Map<@Nullable String, ContextBeansDescriptor> contexts) {
this.contexts = contexts;
}
public Map<String, ContextBeansDescriptor> getContexts() {
public Map<@Nullable String, ContextBeansDescriptor> getContexts() {
return this.contexts;
}
@ -113,6 +114,7 @@ public class BeansEndpoint { @@ -113,6 +114,7 @@ public class BeansEndpoint {
return this.beans;
}
@Contract("!null -> !null")
private static @Nullable ContextBeansDescriptor describing(@Nullable ConfigurableApplicationContext context) {
if (context == null) {
return null;

49
module/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/context/properties/ConfigurationPropertiesReportEndpoint.java

@ -152,7 +152,7 @@ public class ConfigurationPropertiesReportEndpoint implements ApplicationContext @@ -152,7 +152,7 @@ public class ConfigurationPropertiesReportEndpoint implements ApplicationContext
private ConfigurationPropertiesDescriptor getConfigurationProperties(ApplicationContext context,
Predicate<ConfigurationPropertiesBean> beanFilterPredicate, boolean showUnsanitized) {
ObjectMapper mapper = getObjectMapper();
Map<String, ContextConfigurationPropertiesDescriptor> contexts = new HashMap<>();
Map<@Nullable String, ContextConfigurationPropertiesDescriptor> contexts = new HashMap<>();
ApplicationContext target = context;
while (target != null) {
@ -221,8 +221,8 @@ public class ConfigurationPropertiesReportEndpoint implements ApplicationContext @@ -221,8 +221,8 @@ public class ConfigurationPropertiesReportEndpoint implements ApplicationContext
private ConfigurationPropertiesBeanDescriptor describeBean(ObjectMapper mapper, ConfigurationPropertiesBean bean,
boolean showUnsanitized) {
String prefix = bean.getAnnotation().prefix();
Map<String, Object> serialized = safeSerialize(mapper, bean.getInstance(), prefix);
Map<String, Object> properties = sanitize(prefix, serialized, showUnsanitized);
Map<String, @Nullable Object> serialized = safeSerialize(mapper, bean.getInstance(), prefix);
Map<String, @Nullable Object> properties = sanitize(prefix, serialized, showUnsanitized);
Map<String, Object> inputs = getInputs(prefix, serialized, showUnsanitized);
return new ConfigurationPropertiesBeanDescriptor(prefix, properties, inputs);
}
@ -236,7 +236,7 @@ public class ConfigurationPropertiesReportEndpoint implements ApplicationContext @@ -236,7 +236,7 @@ public class ConfigurationPropertiesReportEndpoint implements ApplicationContext
* @return the serialized instance
*/
@SuppressWarnings({ "unchecked" })
private Map<String, Object> safeSerialize(ObjectMapper mapper, @Nullable Object bean, String prefix) {
private Map<String, @Nullable Object> safeSerialize(ObjectMapper mapper, @Nullable Object bean, String prefix) {
try {
return new HashMap<>(mapper.convertValue(bean, Map.class));
}
@ -254,11 +254,12 @@ public class ConfigurationPropertiesReportEndpoint implements ApplicationContext @@ -254,11 +254,12 @@ public class ConfigurationPropertiesReportEndpoint implements ApplicationContext
* @return the sanitized map
*/
@SuppressWarnings("unchecked")
private Map<String, Object> sanitize(String prefix, Map<String, Object> map, boolean showUnsanitized) {
private Map<String, @Nullable Object> sanitize(String prefix, Map<String, @Nullable Object> map,
boolean showUnsanitized) {
map.forEach((key, value) -> {
String qualifiedKey = getQualifiedKey(prefix, key);
if (value instanceof Map) {
map.put(key, sanitize(qualifiedKey, (Map<String, Object>) value, showUnsanitized));
map.put(key, sanitize(qualifiedKey, (Map<String, @Nullable Object>) value, showUnsanitized));
}
else if (value instanceof List) {
map.put(key, sanitize(qualifiedKey, (List<Object>) value, showUnsanitized));
@ -270,7 +271,7 @@ public class ConfigurationPropertiesReportEndpoint implements ApplicationContext @@ -270,7 +271,7 @@ public class ConfigurationPropertiesReportEndpoint implements ApplicationContext
return map;
}
private @Nullable Object sanitizeWithPropertySourceIfPresent(String qualifiedKey, Object value,
private @Nullable Object sanitizeWithPropertySourceIfPresent(String qualifiedKey, @Nullable Object value,
boolean showUnsanitized) {
ConfigurationPropertyName currentName = getCurrentName(qualifiedKey);
ConfigurationProperty candidate = getCandidate(currentName);
@ -309,13 +310,13 @@ public class ConfigurationPropertiesReportEndpoint implements ApplicationContext @@ -309,13 +310,13 @@ public class ConfigurationPropertiesReportEndpoint implements ApplicationContext
}
@SuppressWarnings("unchecked")
private List<Object> sanitize(String prefix, List<Object> list, boolean showUnsanitized) {
List<Object> sanitized = new ArrayList<>();
private List<@Nullable Object> sanitize(String prefix, List<Object> list, boolean showUnsanitized) {
List<@Nullable Object> sanitized = new ArrayList<>();
int index = 0;
for (Object item : list) {
String name = prefix + "[" + index++ + "]";
if (item instanceof Map) {
sanitized.add(sanitize(name, (Map<String, Object>) item, showUnsanitized));
sanitized.add(sanitize(name, (Map<String, @Nullable Object>) item, showUnsanitized));
}
else if (item instanceof List) {
sanitized.add(sanitize(name, (List<Object>) item, showUnsanitized));
@ -328,12 +329,12 @@ public class ConfigurationPropertiesReportEndpoint implements ApplicationContext @@ -328,12 +329,12 @@ public class ConfigurationPropertiesReportEndpoint implements ApplicationContext
}
@SuppressWarnings("unchecked")
private Map<String, Object> getInputs(String prefix, Map<String, Object> map, boolean showUnsanitized) {
private Map<String, Object> getInputs(String prefix, Map<String, @Nullable Object> map, boolean showUnsanitized) {
Map<String, Object> augmented = new LinkedHashMap<>(map);
map.forEach((key, value) -> {
String qualifiedKey = getQualifiedKey(prefix, key);
if (value instanceof Map) {
augmented.put(key, getInputs(qualifiedKey, (Map<String, Object>) value, showUnsanitized));
augmented.put(key, getInputs(qualifiedKey, (Map<String, @Nullable Object>) value, showUnsanitized));
}
else if (value instanceof List) {
augmented.put(key, getInputs(qualifiedKey, (List<Object>) value, showUnsanitized));
@ -352,7 +353,7 @@ public class ConfigurationPropertiesReportEndpoint implements ApplicationContext @@ -352,7 +353,7 @@ public class ConfigurationPropertiesReportEndpoint implements ApplicationContext
for (Object item : list) {
String name = prefix + "[" + index++ + "]";
if (item instanceof Map) {
augmented.add(getInputs(name, (Map<String, Object>) item, showUnsanitized));
augmented.add(getInputs(name, (Map<String, @Nullable Object>) item, showUnsanitized));
}
else if (item instanceof List) {
augmented.add(getInputs(name, (List<Object>) item, showUnsanitized));
@ -364,7 +365,7 @@ public class ConfigurationPropertiesReportEndpoint implements ApplicationContext @@ -364,7 +365,7 @@ public class ConfigurationPropertiesReportEndpoint implements ApplicationContext
return augmented;
}
private Map<String, Object> applyInput(String qualifiedKey, boolean showUnsanitized) {
private Map<String, @Nullable Object> applyInput(String qualifiedKey, boolean showUnsanitized) {
ConfigurationPropertyName currentName = getCurrentName(qualifiedKey);
ConfigurationProperty candidate = getCandidate(currentName);
PropertySource<?> propertySource = getPropertySource(candidate);
@ -377,8 +378,8 @@ public class ConfigurationPropertiesReportEndpoint implements ApplicationContext @@ -377,8 +378,8 @@ public class ConfigurationPropertiesReportEndpoint implements ApplicationContext
return Collections.emptyMap();
}
private Map<String, Object> getInput(ConfigurationProperty candidate, @Nullable Object sanitizedValue) {
Map<String, Object> input = new LinkedHashMap<>();
private Map<String, @Nullable Object> getInput(ConfigurationProperty candidate, @Nullable Object sanitizedValue) {
Map<String, @Nullable Object> input = new LinkedHashMap<>();
Origin origin = Origin.from(candidate);
List<Origin> originParents = Origin.parentsFrom(candidate);
input.put("value", sanitizedValue);
@ -511,7 +512,7 @@ public class ConfigurationPropertiesReportEndpoint implements ApplicationContext @@ -511,7 +512,7 @@ public class ConfigurationPropertiesReportEndpoint implements ApplicationContext
@Nullable Constructor<?> constructor) {
if (constructor != null) {
Parameter[] parameters = constructor.getParameters();
@Nullable String[] names = PARAMETER_NAME_DISCOVERER.getParameterNames(constructor);
@Nullable String @Nullable [] names = PARAMETER_NAME_DISCOVERER.getParameterNames(constructor);
if (names == null) {
names = new String[parameters.length];
}
@ -520,7 +521,7 @@ public class ConfigurationPropertiesReportEndpoint implements ApplicationContext @@ -520,7 +521,7 @@ public class ConfigurationPropertiesReportEndpoint implements ApplicationContext
.get(Name.class)
.getValue(MergedAnnotation.VALUE, String.class)
.orElse((names[i] != null) ? names[i] : parameters[i].getName());
if (name.equals(writer.getName())) {
if (name != null && name.equals(writer.getName())) {
return true;
}
}
@ -576,13 +577,13 @@ public class ConfigurationPropertiesReportEndpoint implements ApplicationContext @@ -576,13 +577,13 @@ public class ConfigurationPropertiesReportEndpoint implements ApplicationContext
*/
public static final class ConfigurationPropertiesDescriptor implements OperationResponseBody {
private final Map<String, ContextConfigurationPropertiesDescriptor> contexts;
private final Map<@Nullable String, ContextConfigurationPropertiesDescriptor> contexts;
ConfigurationPropertiesDescriptor(Map<String, ContextConfigurationPropertiesDescriptor> contexts) {
ConfigurationPropertiesDescriptor(Map<@Nullable String, ContextConfigurationPropertiesDescriptor> contexts) {
this.contexts = contexts;
}
public Map<String, ContextConfigurationPropertiesDescriptor> getContexts() {
public Map<@Nullable String, ContextConfigurationPropertiesDescriptor> getContexts() {
return this.contexts;
}
@ -621,11 +622,11 @@ public class ConfigurationPropertiesReportEndpoint implements ApplicationContext @@ -621,11 +622,11 @@ public class ConfigurationPropertiesReportEndpoint implements ApplicationContext
private final String prefix;
private final Map<String, Object> properties;
private final Map<String, @Nullable Object> properties;
private final Map<String, Object> inputs;
private ConfigurationPropertiesBeanDescriptor(String prefix, Map<String, Object> properties,
private ConfigurationPropertiesBeanDescriptor(String prefix, Map<String, @Nullable Object> properties,
Map<String, Object> inputs) {
this.prefix = prefix;
this.properties = properties;
@ -636,7 +637,7 @@ public class ConfigurationPropertiesReportEndpoint implements ApplicationContext @@ -636,7 +637,7 @@ public class ConfigurationPropertiesReportEndpoint implements ApplicationContext
return this.prefix;
}
public Map<String, Object> getProperties() {
public Map<String, @Nullable Object> getProperties() {
return this.properties;
}

2
module/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/InvocationContext.java

@ -49,7 +49,7 @@ public class InvocationContext { @@ -49,7 +49,7 @@ public class InvocationContext {
* the operation.
*/
public InvocationContext(SecurityContext securityContext, Map<String, Object> arguments,
OperationArgumentResolver... argumentResolvers) {
OperationArgumentResolver @Nullable ... argumentResolvers) {
Assert.notNull(securityContext, "'securityContext' must not be null");
Assert.notNull(arguments, "'arguments' must not be null");
this.arguments = arguments;

4
module/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/OperationArgumentResolver.java

@ -54,7 +54,7 @@ public interface OperationArgumentResolver { @@ -54,7 +54,7 @@ public interface OperationArgumentResolver {
* @param supplier the value supplier
* @return an {@link OperationArgumentResolver} instance
*/
static <T> OperationArgumentResolver of(Class<T> type, Supplier<? extends T> supplier) {
static <T> OperationArgumentResolver of(Class<T> type, Supplier<? extends @Nullable T> supplier) {
Assert.notNull(type, "'type' must not be null");
Assert.notNull(supplier, "'supplier' must not be null");
return new OperationArgumentResolver() {
@ -66,7 +66,7 @@ public interface OperationArgumentResolver { @@ -66,7 +66,7 @@ public interface OperationArgumentResolver {
@Override
@SuppressWarnings("unchecked")
public <R> R resolve(Class<R> argumentType) {
public <R> @Nullable R resolve(Class<R> argumentType) {
return (R) supplier.get();
}

4
module/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/ProducibleOperationArgumentResolver.java

@ -37,13 +37,13 @@ import org.springframework.util.MimeTypeUtils; @@ -37,13 +37,13 @@ import org.springframework.util.MimeTypeUtils;
*/
public class ProducibleOperationArgumentResolver implements OperationArgumentResolver {
private final Supplier<List<String>> accepts;
private final Supplier<@Nullable List<String>> accepts;
/**
* Create a new {@link ProducibleOperationArgumentResolver} instance.
* @param accepts supplier that returns accepted mime types
*/
public ProducibleOperationArgumentResolver(Supplier<List<String>> accepts) {
public ProducibleOperationArgumentResolver(Supplier<@Nullable List<String>> accepts) {
this.accepts = accepts;
}

6
module/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/SanitizableData.java

@ -38,7 +38,7 @@ public final class SanitizableData { @@ -38,7 +38,7 @@ public final class SanitizableData {
private final @Nullable PropertySource<?> propertySource;
private final String key;
private final @Nullable String key;
private @Nullable String lowerCaseKey;
@ -50,7 +50,7 @@ public final class SanitizableData { @@ -50,7 +50,7 @@ public final class SanitizableData {
* @param key the data key
* @param value the data value
*/
public SanitizableData(@Nullable PropertySource<?> propertySource, String key, @Nullable Object value) {
public SanitizableData(@Nullable PropertySource<?> propertySource, @Nullable String key, @Nullable Object value) {
this.propertySource = propertySource;
this.key = key;
this.value = value;
@ -69,7 +69,7 @@ public final class SanitizableData { @@ -69,7 +69,7 @@ public final class SanitizableData {
* Return the key of the data.
* @return the data key
*/
public String getKey() {
public @Nullable String getKey() {
return this.key;
}

7
module/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/SanitizingFunction.java

@ -338,7 +338,7 @@ public interface SanitizingFunction { @@ -338,7 +338,7 @@ public interface SanitizingFunction {
* @see #filter()
* @see #sanitizeValue()
*/
default SanitizingFunction ifValueMatches(Predicate<Object> predicate) {
default SanitizingFunction ifValueMatches(Predicate<@Nullable Object> predicate) {
Assert.notNull(predicate, "'predicate' must not be null");
return ifMatches((data) -> predicate.test(data.getValue()));
}
@ -373,12 +373,13 @@ public interface SanitizingFunction { @@ -373,12 +373,13 @@ public interface SanitizingFunction {
*/
default SanitizingFunction ifMatches(Predicate<SanitizableData> predicate) {
Assert.notNull(predicate, "'predicate' must not be null");
Predicate<SanitizableData> filter = (filter() != null) ? filter().or(predicate) : predicate;
Predicate<SanitizableData> filter = filter();
Predicate<SanitizableData> newFilter = (filter != null) ? filter.or(predicate) : predicate;
return new SanitizingFunction() {
@Override
public Predicate<SanitizableData> filter() {
return filter;
return newFilter;
}
@Override

12
module/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/annotation/EndpointDiscoverer.java

@ -129,10 +129,12 @@ public abstract class EndpointDiscoverer<E extends ExposableEndpoint<O>, O exten @@ -129,10 +129,12 @@ public abstract class EndpointDiscoverer<E extends ExposableEndpoint<O>, O exten
@Override
public final Collection<E> getEndpoints() {
if (this.endpoints == null) {
this.endpoints = discoverEndpoints();
Collection<E> endpoints = this.endpoints;
if (endpoints == null) {
endpoints = discoverEndpoints();
this.endpoints = endpoints;
}
return this.endpoints;
return endpoints;
}
private Collection<E> discoverEndpoints() {
@ -149,10 +151,12 @@ public abstract class EndpointDiscoverer<E extends ExposableEndpoint<O>, O exten @@ -149,10 +151,12 @@ public abstract class EndpointDiscoverer<E extends ExposableEndpoint<O>, O exten
if (!ScopedProxyUtils.isScopedTarget(beanName)) {
EndpointBean endpointBean = createEndpointBean(beanName);
EndpointBean previous = byId.putIfAbsent(endpointBean.getId(), endpointBean);
Assert.state(previous == null, () -> "Found two endpoints with the id '" + endpointBean.getId() + "': '"
if (previous != null) {
throw new IllegalStateException("Found two endpoints with the id '" + endpointBean.getId() + "': '"
+ endpointBean.getBeanName() + "' and '" + previous.getBeanName() + "'");
}
}
}
return byId.values();
}

2
module/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/endpoint/web/PathMappedEndpoints.java

@ -28,6 +28,7 @@ import org.jspecify.annotations.Nullable; @@ -28,6 +28,7 @@ import org.jspecify.annotations.Nullable;
import org.springframework.boot.actuate.endpoint.EndpointId;
import org.springframework.boot.actuate.endpoint.EndpointsSupplier;
import org.springframework.lang.Contract;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
@ -167,6 +168,7 @@ public class PathMappedEndpoints implements Iterable<PathMappedEndpoint> { @@ -167,6 +168,7 @@ public class PathMappedEndpoints implements Iterable<PathMappedEndpoint> {
return this.endpoints.values().iterator();
}
@Contract("!null -> !null")
private @Nullable String getPath(@Nullable PathMappedEndpoint endpoint) {
if (endpoint == null) {
return null;

19
module/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/env/EnvironmentEndpoint.java vendored

@ -113,22 +113,23 @@ public class EnvironmentEndpoint { @@ -113,22 +113,23 @@ public class EnvironmentEndpoint {
}
EnvironmentEntryDescriptor getEnvironmentEntryDescriptor(String propertyName, boolean showUnsanitized) {
Map<String, PropertyValueDescriptor> descriptors = getPropertySourceDescriptors(propertyName, showUnsanitized);
Map<String, @Nullable PropertyValueDescriptor> descriptors = getPropertySourceDescriptors(propertyName,
showUnsanitized);
PropertySummaryDescriptor summary = getPropertySummaryDescriptor(descriptors);
return new EnvironmentEntryDescriptor(summary, Arrays.asList(this.environment.getActiveProfiles()),
Arrays.asList(this.environment.getDefaultProfiles()), toPropertySourceDescriptors(descriptors));
}
private List<PropertySourceEntryDescriptor> toPropertySourceDescriptors(
Map<String, PropertyValueDescriptor> descriptors) {
Map<String, @Nullable PropertyValueDescriptor> descriptors) {
List<PropertySourceEntryDescriptor> result = new ArrayList<>();
descriptors.forEach((name, property) -> result.add(new PropertySourceEntryDescriptor(name, property)));
return result;
}
private @Nullable PropertySummaryDescriptor getPropertySummaryDescriptor(
Map<String, PropertyValueDescriptor> descriptors) {
for (Map.Entry<String, PropertyValueDescriptor> entry : descriptors.entrySet()) {
Map<String, @Nullable PropertyValueDescriptor> descriptors) {
for (Map.Entry<String, @Nullable PropertyValueDescriptor> entry : descriptors.entrySet()) {
if (entry.getValue() != null) {
return new PropertySummaryDescriptor(entry.getKey(), entry.getValue().getValue());
}
@ -136,9 +137,9 @@ public class EnvironmentEndpoint { @@ -136,9 +137,9 @@ public class EnvironmentEndpoint {
return null;
}
private Map<String, PropertyValueDescriptor> getPropertySourceDescriptors(String propertyName,
private Map<String, @Nullable PropertyValueDescriptor> getPropertySourceDescriptors(String propertyName,
boolean showUnsanitized) {
Map<String, PropertyValueDescriptor> propertySources = new LinkedHashMap<>();
Map<String, @Nullable PropertyValueDescriptor> propertySources = new LinkedHashMap<>();
getPropertySourcesAsMap().forEach((sourceName, source) -> propertySources.put(sourceName,
source.containsProperty(propertyName) ? describeValueOf(propertyName, source, showUnsanitized) : null));
return propertySources;
@ -335,9 +336,9 @@ public class EnvironmentEndpoint { @@ -335,9 +336,9 @@ public class EnvironmentEndpoint {
private final String name;
private final PropertyValueDescriptor property;
private final @Nullable PropertyValueDescriptor property;
private PropertySourceEntryDescriptor(String name, PropertyValueDescriptor property) {
private PropertySourceEntryDescriptor(String name, @Nullable PropertyValueDescriptor property) {
this.name = name;
this.property = property;
}
@ -346,7 +347,7 @@ public class EnvironmentEndpoint { @@ -346,7 +347,7 @@ public class EnvironmentEndpoint {
return this.name;
}
public PropertyValueDescriptor getProperty() {
public @Nullable PropertyValueDescriptor getProperty() {
return this.property;
}

3
module/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/HealthEndpointGroups.java

@ -83,7 +83,8 @@ public interface HealthEndpointGroups { @@ -83,7 +83,8 @@ public interface HealthEndpointGroups {
Set<HealthEndpointGroup> filteredGroups = new LinkedHashSet<>();
getNames().stream()
.map(this::get)
.filter((group) -> group.getAdditionalPath() != null && group.getAdditionalPath().hasNamespace(namespace))
.filter((group) -> group != null && group.getAdditionalPath() != null
&& group.getAdditionalPath().hasNamespace(namespace))
.forEach(filteredGroups::add);
return filteredGroups;
}

2
module/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/SimpleStatusAggregator.java

@ -27,6 +27,7 @@ import java.util.stream.Stream; @@ -27,6 +27,7 @@ import java.util.stream.Stream;
import org.jspecify.annotations.Nullable;
import org.springframework.boot.health.contributor.Status;
import org.springframework.lang.Contract;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
@ -86,6 +87,7 @@ public class SimpleStatusAggregator implements StatusAggregator { @@ -86,6 +87,7 @@ public class SimpleStatusAggregator implements StatusAggregator {
return codes.map(SimpleStatusAggregator::getUniformCode).toList();
}
@Contract("!null -> !null")
private static @Nullable String getUniformCode(@Nullable String code) {
if (code == null) {
return null;

14
module/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/info/InfoPropertiesInfoContributor.java

@ -25,9 +25,11 @@ import org.jspecify.annotations.Nullable; @@ -25,9 +25,11 @@ import org.jspecify.annotations.Nullable;
import org.springframework.boot.context.properties.bind.Bindable;
import org.springframework.boot.context.properties.bind.Binder;
import org.springframework.boot.context.properties.source.ConfigurationPropertySource;
import org.springframework.boot.context.properties.source.ConfigurationPropertySources;
import org.springframework.boot.info.InfoProperties;
import org.springframework.core.env.PropertySource;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
/**
@ -92,8 +94,16 @@ public abstract class InfoPropertiesInfoContributor<T extends InfoProperties> im @@ -92,8 +94,16 @@ public abstract class InfoPropertiesInfoContributor<T extends InfoProperties> im
* @return the raw content
*/
protected Map<String, Object> extractContent(PropertySource<?> propertySource) {
return new Binder(ConfigurationPropertySources.from(propertySource)).bind("", STRING_OBJECT_MAP)
.orElseGet(LinkedHashMap::new);
Iterable<@Nullable ConfigurationPropertySource> adapted = ConfigurationPropertySources.from(propertySource);
return new Binder(ensureNonNullContent(adapted)).bind("", STRING_OBJECT_MAP).orElseGet(LinkedHashMap::new);
}
private Iterable<ConfigurationPropertySource> ensureNonNullContent(
Iterable<@Nullable ConfigurationPropertySource> adapted) {
for (ConfigurationPropertySource source : adapted) {
Assert.state(source != null, "'source' must not be null");
}
return (Iterable<ConfigurationPropertySource>) adapted;
}
/**

8
module/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/security/AuthenticationAuditListener.java

@ -89,7 +89,7 @@ public class AuthenticationAuditListener extends AbstractAuthenticationAuditList @@ -89,7 +89,7 @@ public class AuthenticationAuditListener extends AbstractAuthenticationAuditList
}
private void onAuthenticationFailureEvent(AbstractAuthenticationFailureEvent event) {
Map<String, Object> data = new LinkedHashMap<>();
Map<String, @Nullable Object> data = new LinkedHashMap<>();
data.put("type", event.getException().getClass().getName());
data.put("message", event.getException().getMessage());
if (event.getAuthentication().getDetails() != null) {
@ -99,7 +99,7 @@ public class AuthenticationAuditListener extends AbstractAuthenticationAuditList @@ -99,7 +99,7 @@ public class AuthenticationAuditListener extends AbstractAuthenticationAuditList
}
private void onAuthenticationSuccessEvent(AuthenticationSuccessEvent event) {
Map<String, Object> data = new LinkedHashMap<>();
Map<String, @Nullable Object> data = new LinkedHashMap<>();
if (event.getAuthentication().getDetails() != null) {
data.put("details", event.getAuthentication().getDetails());
}
@ -107,7 +107,7 @@ public class AuthenticationAuditListener extends AbstractAuthenticationAuditList @@ -107,7 +107,7 @@ public class AuthenticationAuditListener extends AbstractAuthenticationAuditList
}
private void onLogoutSuccessEvent(LogoutSuccessEvent event) {
Map<String, Object> data = new LinkedHashMap<>();
Map<String, @Nullable Object> data = new LinkedHashMap<>();
if (event.getAuthentication().getDetails() != null) {
data.put("details", event.getAuthentication().getDetails());
}
@ -119,7 +119,7 @@ public class AuthenticationAuditListener extends AbstractAuthenticationAuditList @@ -119,7 +119,7 @@ public class AuthenticationAuditListener extends AbstractAuthenticationAuditList
void process(@Nullable AuthenticationAuditListener listener, AbstractAuthenticationEvent input) {
if (listener != null) {
AuthenticationSwitchUserEvent event = (AuthenticationSwitchUserEvent) input;
Map<String, Object> data = new HashMap<>();
Map<String, @Nullable Object> data = new HashMap<>();
if (event.getAuthentication().getDetails() != null) {
data.put("details", event.getAuthentication().getDetails());
}

2
module/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/security/AuthorizationAuditListener.java

@ -50,7 +50,7 @@ public class AuthorizationAuditListener extends AbstractAuthorizationAuditListen @@ -50,7 +50,7 @@ public class AuthorizationAuditListener extends AbstractAuthorizationAuditListen
private void onAuthorizationDeniedEvent(AuthorizationDeniedEvent<?> event) {
String name = getName(event.getAuthentication());
Map<String, Object> data = new LinkedHashMap<>();
Map<String, @Nullable Object> data = new LinkedHashMap<>();
Object details = getDetails(event.getAuthentication());
if (details != null) {
data.put("details", details);

4
module/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/ssl/SslHealthIndicator.java

@ -105,7 +105,9 @@ public class SslHealthIndicator extends AbstractHealthIndicator { @@ -105,7 +105,9 @@ public class SslHealthIndicator extends AbstractHealthIndicator {
}
private boolean isExpiringCertificate(CertificateInfo certificate) {
return Instant.now().plus(this.expiryThreshold).isAfter(certificate.getValidityEnds());
Instant validityEnds = certificate.getValidityEnds();
Assert.state(validityEnds != null, "'validityEnds' must not be null");
return Instant.now().plus(this.expiryThreshold).isAfter(validityEnds);
}
}

8
module/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/web/mappings/MappingsEndpoint.java

@ -48,7 +48,7 @@ public class MappingsEndpoint { @@ -48,7 +48,7 @@ public class MappingsEndpoint {
@ReadOperation
public ApplicationMappingsDescriptor mappings() {
ApplicationContext target = this.context;
Map<String, ContextMappingsDescriptor> contextMappings = new HashMap<>();
Map<@Nullable String, ContextMappingsDescriptor> contextMappings = new HashMap<>();
while (target != null) {
contextMappings.put(target.getId(), mappingsForContext(target));
target = target.getParent();
@ -69,13 +69,13 @@ public class MappingsEndpoint { @@ -69,13 +69,13 @@ public class MappingsEndpoint {
*/
public static final class ApplicationMappingsDescriptor implements OperationResponseBody {
private final Map<String, ContextMappingsDescriptor> contextMappings;
private final Map<@Nullable String, ContextMappingsDescriptor> contextMappings;
private ApplicationMappingsDescriptor(Map<String, ContextMappingsDescriptor> contextMappings) {
private ApplicationMappingsDescriptor(Map<@Nullable String, ContextMappingsDescriptor> contextMappings) {
this.contextMappings = contextMappings;
}
public Map<String, ContextMappingsDescriptor> getContexts() {
public Map<@Nullable String, ContextMappingsDescriptor> getContexts() {
return this.contextMappings;
}

Loading…
Cancel
Save