Skip to content

Commit 2e9e113

Browse files
committed
Use JSpecify to indicate nullness.
Closes #902
1 parent 6ffce93 commit 2e9e113

File tree

65 files changed

+564
-386
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

65 files changed

+564
-386
lines changed

pom.xml

-1
Original file line numberDiff line numberDiff line change
@@ -383,7 +383,6 @@
383383
<configuration>
384384
<release>${java.version}</release>
385385
<parameters>true</parameters>
386-
<release>${source.level}</release>
387386
<showWarnings>true</showWarnings>
388387
<annotationProcessorPaths>
389388
<path>

spring-vault-core/src/main/java/org/springframework/vault/authentication/AppRoleAuthentication.java

+3-2
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,7 @@ private String getRoleId(RoleId roleId) throws VaultLoginException {
214214

215215
ResponseEntity<VaultResponse> entity = this.restOperations.exchange(getRoleIdIdPath(this.options),
216216
HttpMethod.GET, createHttpEntity(token), VaultResponse.class);
217-
return (String) ResponseUtil.getRequiredData(entity).get("role_id");
217+
return (String) ResponseUtil.getRequiredValue(entity, "role_id");
218218
}
219219
catch (HttpStatusCodeException e) {
220220
throw new VaultLoginException("Cannot get Role id using AppRole: %s"
@@ -233,7 +233,7 @@ private String getRoleId(RoleId roleId) throws VaultLoginException {
233233

234234
VaultResponse response = unwrappingEndpoints.unwrap(ResponseUtil.getRequiredBody(entity));
235235

236-
return (String) response.getRequiredData().get("role_id");
236+
return (String) ResponseUtil.getRequiredValue(response, "role_id");
237237
}
238238
catch (HttpStatusCodeException e) {
239239
throw new VaultLoginException("Cannot unwrap Role id using AppRole: %s"
@@ -244,6 +244,7 @@ private String getRoleId(RoleId roleId) throws VaultLoginException {
244244
throw new IllegalArgumentException("Unknown RoleId configuration: " + roleId);
245245
}
246246

247+
@SuppressWarnings("NullAway")
247248
private String getSecretId(SecretId secretId) throws VaultLoginException {
248249

249250
if (secretId instanceof Provided) {

spring-vault-core/src/main/java/org/springframework/vault/authentication/AppRoleAuthenticationOptions.java

+8-10
Original file line numberDiff line numberDiff line change
@@ -128,20 +128,15 @@ public static class AppRoleAuthenticationOptionsBuilder {
128128

129129
private String path = DEFAULT_APPROLE_AUTHENTICATION_PATH;
130130

131-
@Nullable
132-
private String providedRoleId;
131+
private @Nullable String providedRoleId;
133132

134-
@Nullable
135-
private RoleId roleId;
133+
private @Nullable RoleId roleId;
136134

137-
@Nullable
138-
private String providedSecretId;
135+
private @Nullable String providedSecretId;
139136

140-
@Nullable
141-
private SecretId secretId;
137+
private @Nullable SecretId secretId;
142138

143-
@Nullable
144-
private String appRole;
139+
private @Nullable String appRole;
145140

146141
private UnwrappingEndpoints unwrappingEndpoints = UnwrappingEndpoints.SysWrapping;
147142

@@ -250,6 +245,9 @@ public AppRoleAuthenticationOptions build() {
250245
"AppRole authentication configured for pull mode. AppRole must not be null.");
251246
}
252247

248+
Assert.notNull(this.roleId, "RoleId must not be null");
249+
Assert.notNull(this.secretId, "SecretId must not be null");
250+
253251
return new AppRoleAuthenticationOptions(this.path, this.roleId, this.secretId, this.appRole,
254252
this.unwrappingEndpoints);
255253
}

spring-vault-core/src/main/java/org/springframework/vault/authentication/AuthenticationSteps.java

+7-6
Original file line numberDiff line numberDiff line change
@@ -299,7 +299,8 @@ public static class HttpRequestBuilder {
299299
@Nullable
300300
String uriTemplate;
301301

302-
String @Nullable[] urlVariables;
302+
@Nullable
303+
String[] urlVariables = new String[0];
303304

304305
@Nullable
305306
HttpEntity<?> entity;
@@ -379,14 +380,14 @@ private HttpRequestBuilder(HttpMethod method, URI uri) {
379380
this.uri = uri;
380381
}
381382

382-
private HttpRequestBuilder(HttpMethod method, @Nullable String uriTemplate, String @Nullable[] urlVariables) {
383+
private HttpRequestBuilder(HttpMethod method, @Nullable String uriTemplate, @Nullable String[] urlVariables) {
383384
this.method = method;
384385
this.uriTemplate = uriTemplate;
385386
this.urlVariables = urlVariables;
386387
}
387388

388389
private HttpRequestBuilder(HttpMethod method, @Nullable URI uri, @Nullable String uriTemplate,
389-
String @Nullable[] urlVariables, @Nullable HttpEntity<?> entity) {
390+
@Nullable String[] urlVariables, @Nullable HttpEntity<?> entity) {
390391
this.method = method;
391392
this.uri = uri;
392393
this.uriTemplate = uriTemplate;
@@ -448,8 +449,7 @@ public static class HttpRequest<T> {
448449
@Nullable
449450
final String uriTemplate;
450451

451-
452-
final String @Nullable[] urlVariables;
452+
final @Nullable String[] urlVariables;
453453

454454
@Nullable
455455
final HttpEntity<?> entity;
@@ -485,7 +485,8 @@ String getUriTemplate() {
485485
return this.uriTemplate;
486486
}
487487

488-
String @Nullable[] getUrlVariables() {
488+
@Nullable
489+
String[] getUrlVariables() {
489490
return this.urlVariables;
490491
}
491492

spring-vault-core/src/main/java/org/springframework/vault/authentication/AuthenticationStepsExecutor.java

+15-7
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ public VaultToken login() throws VaultException {
9292
}
9393

9494
@SuppressWarnings({ "unchecked", "ConstantConditions" })
95-
private Object evaluate(Iterable<Node<?>> steps) {
95+
private @Nullable Object evaluate(Iterable<Node<?>> steps) {
9696

9797
Object state = null;
9898

@@ -108,14 +108,17 @@ private Object evaluate(Iterable<Node<?>> steps) {
108108
}
109109

110110
if (o instanceof MapStep) {
111+
Assert.state(state != null, "No state available for MapStep");
111112
state = doMapStep((MapStep<Object, Object>) o, state);
112113
}
113114

114115
if (o instanceof ZipStep) {
116+
Assert.state(state != null, "No state available for ZipStep");
115117
state = doZipStep((ZipStep<Object, Object>) o, state);
116118
}
117119

118120
if (o instanceof OnNextStep) {
121+
Assert.state(state != null, "No state available for OnNextStep");
119122
state = doOnNext((OnNextStep<Object>) o, state);
120123
}
121124

@@ -143,24 +146,28 @@ private Object evaluate(Iterable<Node<?>> steps) {
143146
}
144147

145148
@SuppressWarnings("ConstantConditions")
146-
@Nullable
147-
private Object doHttpRequest(HttpRequestNode<Object> step, @Nullable Object state) {
149+
private @Nullable Object doHttpRequest(HttpRequestNode<Object> step, @Nullable Object state) {
148150

149151
HttpRequest<Object> definition = step.getDefinition();
150152

151-
if (definition.getUri() == null) {
153+
if (definition.getUriTemplate() != null) {
152154

153155
ResponseEntity<?> exchange = this.restOperations.exchange(definition.getUriTemplate(),
154156
definition.getMethod(), getEntity(definition.getEntity(), state), definition.getResponseType(),
155157
(Object[]) definition.getUrlVariables());
156158

157159
return exchange.getBody();
158160
}
159-
ResponseEntity<?> exchange = this.restOperations.exchange(definition.getUri(), definition.getMethod(),
160-
getEntity(definition.getEntity(), state), definition.getResponseType());
161161

162-
return exchange.getBody();
162+
if (definition.getUri() != null) {
163163

164+
ResponseEntity<?> exchange = this.restOperations.exchange(definition.getUri(), definition.getMethod(),
165+
getEntity(definition.getEntity(), state), definition.getResponseType());
166+
167+
return exchange.getBody();
168+
}
169+
170+
return null;
164171
}
165172

166173
static HttpEntity<?> getEntity(@Nullable HttpEntity<?> entity, @Nullable Object state) {
@@ -185,6 +192,7 @@ private static Object doMapStep(MapStep<Object, Object> o, Object state) {
185192
return o.apply(state);
186193
}
187194

195+
@SuppressWarnings("NullAway")
188196
private Object doZipStep(ZipStep<Object, Object> o, Object state) {
189197

190198
Object result = evaluate(o.getRight());

spring-vault-core/src/main/java/org/springframework/vault/authentication/AuthenticationStepsOperator.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ private Mono<Object> createMono(Iterable<Node<?>> steps) {
155155
return state;
156156
}
157157

158-
@SuppressWarnings({"NullAway", "DataFlowIssue"})
158+
@SuppressWarnings({ "NullAway", "DataFlowIssue" })
159159
private Mono<Object> doHttpRequest(HttpRequestNode<Object> step, Object state) {
160160

161161
HttpRequest<Object> definition = step.getDefinition();

spring-vault-core/src/main/java/org/springframework/vault/authentication/AzureMsiAuthentication.java

+11-2
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ private VaultToken createTokenUsingAzureMsiCompute() {
159159
VaultResponse response = this.vaultRestOperations
160160
.postForObject(AuthenticationUtil.getLoginPath(this.options.getPath()), login, VaultResponse.class);
161161

162-
Assert.state(response != null && response.getAuth() != null, "Auth field must not be null");
162+
Assert.state(response != null, "Auth field must not be null");
163163

164164
if (logger.isDebugEnabled()) {
165165
logger.debug("Login successful using Azure authentication");
@@ -185,6 +185,7 @@ private static Map<String, String> getAzureLogin(String role, AzureVmEnvironment
185185
return loginBody;
186186
}
187187

188+
@SuppressWarnings({ "NullAway", "rawtypes" })
188189
private String getAccessToken() {
189190

190191
ResponseEntity<Map> response = this.azureMetadataRestOperations
@@ -200,6 +201,7 @@ private AzureVmEnvironment getVmEnvironment() {
200201
return vmEnvironment != null ? vmEnvironment : fetchAzureVmEnvironment();
201202
}
202203

204+
@SuppressWarnings({ "unchecked", "rawtypes" })
203205
private AzureVmEnvironment fetchAzureVmEnvironment() {
204206

205207
ResponseEntity<Map> response = this.azureMetadataRestOperations
@@ -208,16 +210,23 @@ private AzureVmEnvironment fetchAzureVmEnvironment() {
208210
return toAzureVmEnvironment(ResponseUtil.getRequiredBody(response));
209211
}
210212

211-
@SuppressWarnings("unchecked")
213+
@SuppressWarnings({ "unchecked", "rawtypes" })
212214
private static AzureVmEnvironment toAzureVmEnvironment(Map<String, Object> instanceMetadata) {
213215

214216
Map<String, String> compute = (Map) instanceMetadata.get("compute");
215217

218+
Assert.notNull(compute, "Metadata does not contain compute");
219+
216220
String subscriptionId = compute.get("subscriptionId");
217221
String resourceGroupName = compute.get("resourceGroupName");
218222
String vmName = compute.get("name");
219223
String vmScaleSetName = compute.get("vmScaleSetName");
220224

225+
Assert.notNull(subscriptionId, "Metadata does not contain subscriptionId");
226+
Assert.notNull(resourceGroupName, "Metadata does not contain resourceGroupName");
227+
Assert.notNull(vmName, "Metadata does not contain name");
228+
Assert.notNull(vmScaleSetName, "Metadata does not contain vmScaleSetName");
229+
221230
return new AzureVmEnvironment(subscriptionId, resourceGroupName, vmName, vmScaleSetName);
222231
}
223232

spring-vault-core/src/main/java/org/springframework/vault/authentication/CachingVaultTokenSupplier.java

+3-1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import java.util.Objects;
1919
import java.util.concurrent.atomic.AtomicReference;
2020

21+
import org.jspecify.annotations.NonNull;
2122
import reactor.core.publisher.Mono;
2223

2324
import org.springframework.vault.VaultException;
@@ -38,7 +39,7 @@ public class CachingVaultTokenSupplier implements VaultTokenSupplier, ReactiveSe
3839

3940
private final VaultTokenSupplier clientAuthentication;
4041

41-
private final AtomicReference<Mono<VaultToken>> tokenRef = new AtomicReference<>(EMPTY);
42+
private final AtomicReference<@NonNull Mono<VaultToken>> tokenRef = new AtomicReference<>(EMPTY);
4243

4344
private CachingVaultTokenSupplier(VaultTokenSupplier clientAuthentication) {
4445
this.clientAuthentication = clientAuthentication;
@@ -56,6 +57,7 @@ public static CachingVaultTokenSupplier of(VaultTokenSupplier delegate) {
5657
}
5758

5859
@Override
60+
@SuppressWarnings("NullAway")
5961
public Mono<VaultToken> getVaultToken() throws VaultException {
6062

6163
if (Objects.equals(this.tokenRef.get(), EMPTY)) {

spring-vault-core/src/main/java/org/springframework/vault/authentication/LifecycleAwareSessionManager.java

+3-1
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,9 @@ private RenewOutcome doRenew(TokenWrapper wrapper) {
239239
VaultResponse vaultResponse = this.restOperations.postForObject("auth/token/renew-self",
240240
new HttpEntity<>(VaultHttpHeaders.from(wrapper.token)), VaultResponse.class);
241241

242-
LoginToken renewed = LoginTokenUtil.from(vaultResponse.getRequiredAuth());
242+
Assert.notNull(vaultResponse, "VaultResponse must not be null");
243+
244+
LoginToken renewed = LoginTokenUtil.from(vaultResponse.getAuth());
243245

244246
if (isExpired(renewed)) {
245247

spring-vault-core/src/main/java/org/springframework/vault/authentication/LoginToken.java

+1-2
Original file line numberDiff line numberDiff line change
@@ -206,8 +206,7 @@ public String toString() {
206206
*/
207207
public static class LoginTokenBuilder {
208208

209-
210-
private char @Nullable[] token;
209+
private char @Nullable [] token;
211210

212211
private boolean renewable;
213212

spring-vault-core/src/main/java/org/springframework/vault/authentication/LoginTokenUtil.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,8 @@ private LoginTokenUtil() {
4040
static LoginToken from(Map<String, Object> auth) {
4141

4242
Assert.notNull(auth, "Authentication must not be null");
43-
4443
String token = (String) auth.get("client_token");
44+
Assert.notNull(token, "Authentication must contain 'client_token' key");
4545

4646
return from(token.toCharArray(), auth);
4747
}
@@ -52,6 +52,7 @@ static LoginToken from(Map<String, Object> auth) {
5252
* @return the {@link LoginToken}
5353
* @since 2.0
5454
*/
55+
@SuppressWarnings("NullAway")
5556
static LoginToken from(char[] token, Map<String, ?> auth) {
5657

5758
Assert.notNull(auth, "Authentication must not be null");

spring-vault-core/src/main/java/org/springframework/vault/authentication/ReactiveLifecycleAwareSessionManager.java

+7-2
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import java.util.Optional;
2121
import java.util.concurrent.atomic.AtomicReference;
2222

23+
import org.jspecify.annotations.NonNull;
2324
import reactor.core.publisher.Mono;
2425

2526
import org.springframework.beans.factory.DisposableBean;
@@ -91,7 +92,7 @@ public class ReactiveLifecycleAwareSessionManager extends LifecycleAwareSessionM
9192
* The token state: Contains the currently valid token that identifies the Vault
9293
* session.
9394
*/
94-
private volatile AtomicReference<Mono<TokenWrapper>> token = new AtomicReference<>(EMPTY);
95+
private final AtomicReference<@NonNull Mono<TokenWrapper>> token = new AtomicReference<>(EMPTY);
9596

9697
/**
9798
* Create a {@link ReactiveLifecycleAwareSessionManager} given
@@ -136,6 +137,7 @@ public ReactiveLifecycleAwareSessionManager(VaultTokenSupplier clientAuthenticat
136137
}
137138

138139
@Override
140+
@SuppressWarnings("NullAway")
139141
public void destroy() {
140142

141143
Mono<TokenWrapper> tokenMono = this.token.get();
@@ -149,6 +151,7 @@ public void destroy() {
149151
* @return a mono emitting completion upon successful revocation.
150152
* @since 3.0.2
151153
*/
154+
@SuppressWarnings("NullAway")
152155
public Mono<Void> revoke() {
153156
return doRevoke(this.token.get()).doOnSuccess(unused -> this.token.set(EMPTY));
154157
}
@@ -216,6 +219,7 @@ private Mono<String> onRevokeFailed(VaultToken token, Throwable e) {
216219
* obtained. {@link Mono#empty()} if a new the token expired or
217220
* {@link Mono#error(Throwable)} if refresh failed.
218221
*/
222+
@SuppressWarnings("NullAway")
219223
public Mono<VaultToken> renewToken() {
220224

221225
this.logger.info("Renewing token");
@@ -268,7 +272,7 @@ private Mono<TokenWrapper> doRenew(TokenWrapper tokenWrapper) {
268272
.doOnSubscribe(ignore -> multicastEvent(new BeforeLoginTokenRenewedEvent(tokenWrapper.getToken())))
269273
.handle((response, sink) -> {
270274

271-
LoginToken renewed = LoginTokenUtil.from(response.getRequiredAuth());
275+
LoginToken renewed = LoginTokenUtil.from(response.getAuth());
272276

273277
if (!isExpired(renewed)) {
274278
sink.next(new TokenWrapper(renewed, tokenWrapper.revocable));
@@ -301,6 +305,7 @@ private void dropCurrentToken() {
301305
}
302306

303307
@Override
308+
@SuppressWarnings("NullAway")
304309
public Mono<VaultToken> getVaultToken() throws VaultException {
305310

306311
Mono<TokenWrapper> tokenWrapper = this.token.get();

0 commit comments

Comments
 (0)