mirror of
https://github.com/shred/acme4j.git
synced 2025-12-13 11:14:02 +08:00
Update spotbugs and related new warnings (fixes #157)
This commit is contained in:
@@ -24,6 +24,7 @@ import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
||||
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
|
||||
import org.shredzone.acme4j.connector.Resource;
|
||||
import org.shredzone.acme4j.connector.ResourceIterator;
|
||||
import org.shredzone.acme4j.exception.AcmeException;
|
||||
@@ -285,6 +286,7 @@ public class Account extends AcmeJsonResource {
|
||||
* sure that they are valid according to the RFC. It is recommended to use
|
||||
* the {@code addContact()} methods below to add new contacts to the list.
|
||||
*/
|
||||
@SuppressFBWarnings("EI_EXPOSE_REP") // behavior is intended
|
||||
public List<URI> getContacts() {
|
||||
return editContacts;
|
||||
}
|
||||
|
||||
@@ -70,7 +70,7 @@ public abstract class AcmeJsonResource extends AcmeResource {
|
||||
throw new AcmeLazyLoadingException(this, ex);
|
||||
}
|
||||
}
|
||||
return data;
|
||||
return Objects.requireNonNull(data);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -87,4 +87,9 @@ public abstract class AcmeResource implements Serializable {
|
||||
return location;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void finalize() {
|
||||
// CT_CONSTRUCTOR_THROW: Prevents finalizer attack
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ package org.shredzone.acme4j;
|
||||
|
||||
import static java.util.Collections.unmodifiableList;
|
||||
import static java.util.Objects.requireNonNull;
|
||||
import static java.util.stream.Collectors.toList;
|
||||
import static java.util.stream.Collectors.toUnmodifiableList;
|
||||
import static org.shredzone.acme4j.toolbox.AcmeUtils.base64UrlEncode;
|
||||
import static org.shredzone.acme4j.toolbox.AcmeUtils.getRenewalUniqueIdentifier;
|
||||
@@ -33,6 +34,7 @@ import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import edu.umd.cs.findbugs.annotations.Nullable;
|
||||
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
|
||||
import org.bouncycastle.asn1.nist.NISTObjectIdentifiers;
|
||||
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
|
||||
import org.bouncycastle.cert.X509CertificateHolder;
|
||||
@@ -132,9 +134,9 @@ public class Certificate extends AcmeResource {
|
||||
var login = getLogin();
|
||||
alternateCerts = getAlternates().stream()
|
||||
.map(login::bindCertificate)
|
||||
.collect(toUnmodifiableList());
|
||||
.collect(toList());
|
||||
}
|
||||
return alternateCerts;
|
||||
return unmodifiableList(alternateCerts);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -274,6 +276,7 @@ public class Certificate extends AcmeResource {
|
||||
* @throws AcmeNotSupportedException if the CA does not support renewal information.
|
||||
* @since 3.0.0
|
||||
*/
|
||||
@SuppressFBWarnings("EI_EXPOSE_REP") // behavior is intended
|
||||
public RenewalInfo getRenewalInfo() {
|
||||
if (renewalInfo == null) {
|
||||
renewalInfo = getRenewalInfoLocation()
|
||||
|
||||
@@ -256,4 +256,9 @@ public class Identifier implements Serializable {
|
||||
return content.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void finalize() {
|
||||
// CT_CONSTRUCTOR_THROW: Prevents finalizer attack
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ import java.security.KeyPair;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.Objects;
|
||||
|
||||
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
|
||||
import org.shredzone.acme4j.challenge.Challenge;
|
||||
import org.shredzone.acme4j.connector.Resource;
|
||||
import org.shredzone.acme4j.exception.AcmeException;
|
||||
@@ -74,6 +75,7 @@ public class Login {
|
||||
/**
|
||||
* Gets the {@link Session} that is used.
|
||||
*/
|
||||
@SuppressFBWarnings("EI_EXPOSE_REP") // behavior is intended
|
||||
public Session getSession() {
|
||||
return session;
|
||||
}
|
||||
@@ -97,6 +99,7 @@ public class Login {
|
||||
*
|
||||
* @return {@link Account} bound to the login
|
||||
*/
|
||||
@SuppressFBWarnings("EI_EXPOSE_REP") // behavior is intended
|
||||
public Account getAccount() {
|
||||
return account;
|
||||
}
|
||||
|
||||
@@ -13,6 +13,8 @@
|
||||
*/
|
||||
package org.shredzone.acme4j;
|
||||
|
||||
import static java.util.Collections.unmodifiableList;
|
||||
import static java.util.stream.Collectors.toList;
|
||||
import static java.util.stream.Collectors.toUnmodifiableList;
|
||||
|
||||
import java.io.IOException;
|
||||
@@ -25,6 +27,7 @@ import java.util.Optional;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import edu.umd.cs.findbugs.annotations.Nullable;
|
||||
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
|
||||
import org.bouncycastle.pkcs.PKCS10CertificationRequest;
|
||||
import org.shredzone.acme4j.exception.AcmeException;
|
||||
import org.shredzone.acme4j.exception.AcmeNotSupportedException;
|
||||
@@ -114,9 +117,9 @@ public class Order extends AcmeJsonResource {
|
||||
.stream()
|
||||
.map(Value::asURL)
|
||||
.map(login::bindAuthorization)
|
||||
.collect(toUnmodifiableList());
|
||||
.collect(toList());
|
||||
}
|
||||
return authorizations;
|
||||
return unmodifiableList(authorizations);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -135,6 +138,7 @@ public class Order extends AcmeJsonResource {
|
||||
* if the order is not ready yet. You must finalize the order first, and wait
|
||||
* for the status to become {@link Status#VALID}.
|
||||
*/
|
||||
@SuppressFBWarnings("EI_EXPOSE_REP") // behavior is intended
|
||||
public Certificate getCertificate() {
|
||||
if (certificate == null) {
|
||||
certificate = getJSON().get("certificate")
|
||||
@@ -154,6 +158,7 @@ public class Order extends AcmeJsonResource {
|
||||
* for the status to become {@link Status#VALID}. It is also thrown if the
|
||||
* order has been {@link Status#CANCELED}.
|
||||
*/
|
||||
@SuppressFBWarnings("EI_EXPOSE_REP") // behavior is intended
|
||||
public Certificate getAutoRenewalCertificate() {
|
||||
if (autoRenewalCertificate == null) {
|
||||
autoRenewalCertificate = getJSON().get("star-certificate")
|
||||
|
||||
@@ -28,6 +28,7 @@ import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.stream.StreamSupport;
|
||||
|
||||
import edu.umd.cs.findbugs.annotations.Nullable;
|
||||
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
|
||||
import org.shredzone.acme4j.connector.Connection;
|
||||
import org.shredzone.acme4j.connector.NetworkSettings;
|
||||
import org.shredzone.acme4j.connector.Resource;
|
||||
@@ -200,6 +201,7 @@ public class Session {
|
||||
* @return {@link NetworkSettings}
|
||||
* @since 2.8
|
||||
*/
|
||||
@SuppressFBWarnings("EI_EXPOSE_REP") // behavior is intended
|
||||
public NetworkSettings networkSettings() {
|
||||
return networkSettings;
|
||||
}
|
||||
@@ -368,4 +370,9 @@ public class Session {
|
||||
resourceMap.set(map);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void finalize() {
|
||||
// CT_CONSTRUCTOR_THROW: Prevents finalizer attack
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ import java.net.http.HttpClient;
|
||||
import java.net.http.HttpRequest;
|
||||
import java.util.Properties;
|
||||
|
||||
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
@@ -62,6 +63,7 @@ public class HttpConnector {
|
||||
* Creates a new {@link HttpConnector} that is using the given
|
||||
* {@link NetworkSettings}.
|
||||
*/
|
||||
@SuppressFBWarnings("EI_EXPOSE_REP2") // behavior is intended
|
||||
public HttpConnector(NetworkSettings networkSettings) {
|
||||
this.networkSettings = networkSettings;
|
||||
}
|
||||
|
||||
@@ -13,12 +13,13 @@
|
||||
*/
|
||||
package org.shredzone.acme4j.connector;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
import java.net.URL;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.Deque;
|
||||
import java.util.Iterator;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.Objects;
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
import edu.umd.cs.findbugs.annotations.Nullable;
|
||||
@@ -58,10 +59,10 @@ public class ResourceIterator<T extends AcmeResource> implements Iterator<T> {
|
||||
* {@link Login} and {@link URL}.
|
||||
*/
|
||||
public ResourceIterator(Login login, String field, @Nullable URL start, BiFunction<Login, URL, T> creator) {
|
||||
this.login = Objects.requireNonNull(login, "login");
|
||||
this.field = Objects.requireNonNull(field, "field");
|
||||
this.login = requireNonNull(login, "login");
|
||||
this.field = requireNonNull(field, "field");
|
||||
this.nextUrl = start;
|
||||
this.creator = Objects.requireNonNull(creator, "creator");
|
||||
this.creator = requireNonNull(creator, "creator");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -141,7 +142,7 @@ public class ResourceIterator<T extends AcmeResource> implements Iterator<T> {
|
||||
private void readAndQueue() throws AcmeException {
|
||||
var session = login.getSession();
|
||||
try (var conn = session.connect()) {
|
||||
conn.sendSignedPostAsGetRequest(nextUrl, login);
|
||||
conn.sendSignedPostAsGetRequest(requireNonNull(nextUrl), login);
|
||||
fillUrlList(conn.readJsonResponse());
|
||||
|
||||
nextUrl = conn.getLinks("next").stream().findFirst().orElse(null);
|
||||
|
||||
@@ -49,8 +49,7 @@ public class AcmeRateLimitedException extends AcmeServerException {
|
||||
@Nullable Collection<URL> documents) {
|
||||
super(problem);
|
||||
this.retryAfter = retryAfter;
|
||||
this.documents =
|
||||
documents != null ? Collections.unmodifiableCollection(documents) : Collections.emptyList();
|
||||
this.documents = documents != null ? documents : Collections.emptyList();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -66,7 +65,7 @@ public class AcmeRateLimitedException extends AcmeServerException {
|
||||
* Empty if the server did not provide such URLs.
|
||||
*/
|
||||
public Collection<URL> getDocuments() {
|
||||
return documents;
|
||||
return Collections.unmodifiableCollection(documents);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -21,11 +21,11 @@ import java.security.KeyStoreException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.TrustManagerFactory;
|
||||
|
||||
import edu.umd.cs.findbugs.annotations.Nullable;
|
||||
import org.shredzone.acme4j.connector.HttpConnector;
|
||||
import org.shredzone.acme4j.connector.NetworkSettings;
|
||||
|
||||
@@ -34,7 +34,7 @@ import org.shredzone.acme4j.connector.NetworkSettings;
|
||||
* certificate.
|
||||
*/
|
||||
public class PebbleHttpConnector extends HttpConnector {
|
||||
private static @Nullable SSLContext sslContext = null;
|
||||
private static final AtomicReference<SSLContext> SSL_CONTEXT_REF = new AtomicReference<>();
|
||||
|
||||
public PebbleHttpConnector(NetworkSettings settings) {
|
||||
super(settings);
|
||||
@@ -51,8 +51,8 @@ public class PebbleHttpConnector extends HttpConnector {
|
||||
* Lazily creates an {@link SSLContext} that exclusively accepts the Pebble
|
||||
* certificate.
|
||||
*/
|
||||
protected synchronized SSLContext createSSLContext() {
|
||||
if (sslContext == null) {
|
||||
protected SSLContext createSSLContext() {
|
||||
if (SSL_CONTEXT_REF.get() == null) {
|
||||
try (var in = getClass().getResourceAsStream("/org/shredzone/acme4j/provider/pebble/pebble.truststore")) {
|
||||
var keystore = KeyStore.getInstance(KeyStore.getDefaultType());
|
||||
keystore.load(in, "acme4j".toCharArray());
|
||||
@@ -60,14 +60,15 @@ public class PebbleHttpConnector extends HttpConnector {
|
||||
var tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
|
||||
tmf.init(keystore);
|
||||
|
||||
sslContext = SSLContext.getInstance("TLS");
|
||||
var sslContext = SSLContext.getInstance("TLS");
|
||||
sslContext.init(null, tmf.getTrustManagers(), null);
|
||||
SSL_CONTEXT_REF.set(sslContext);
|
||||
} catch (IOException | KeyStoreException | CertificateException
|
||||
| NoSuchAlgorithmException | KeyManagementException ex) {
|
||||
throw new RuntimeException("Could not create truststore", ex);
|
||||
}
|
||||
}
|
||||
return Objects.requireNonNull(sslContext);
|
||||
return Objects.requireNonNull(SSL_CONTEXT_REF.get());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -79,7 +79,12 @@ public class SslComAcmeProvider extends AbstractAcmeProvider {
|
||||
// by EAB, but the "externalAccountRequired" flag in the directory is set to
|
||||
// false. This patch reads the directory and forcefully sets the flag to true.
|
||||
// The entire method can be removed once it is fixed on SSL.com side.
|
||||
var directory = super.directory(session, serverUri).toMap();
|
||||
var superdirectory = super.directory(session, serverUri);
|
||||
if (superdirectory == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
var directory = superdirectory.toMap();
|
||||
var meta = directory.get("meta");
|
||||
if (meta instanceof Map) {
|
||||
var metaMap = ((Map<String, Object>) meta);
|
||||
|
||||
@@ -21,8 +21,6 @@ import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.io.Serializable;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URI;
|
||||
@@ -44,7 +42,6 @@ import java.util.stream.Stream;
|
||||
import java.util.stream.StreamSupport;
|
||||
|
||||
import edu.umd.cs.findbugs.annotations.Nullable;
|
||||
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
|
||||
import org.jose4j.json.JsonUtil;
|
||||
import org.jose4j.lang.JoseException;
|
||||
import org.shredzone.acme4j.Identifier;
|
||||
@@ -57,14 +54,12 @@ import org.shredzone.acme4j.exception.AcmeProtocolException;
|
||||
* A model containing a JSON result. The content is immutable.
|
||||
*/
|
||||
public final class JSON implements Serializable {
|
||||
private static final long serialVersionUID = 3091273044605709204L;
|
||||
private static final long serialVersionUID = 418332625174149030L;
|
||||
|
||||
private static final JSON EMPTY_JSON = new JSON(new HashMap<>());
|
||||
|
||||
private final String path;
|
||||
|
||||
@SuppressFBWarnings("JCIP_FIELD_ISNT_FINAL_IN_IMMUTABLE_CLASS")
|
||||
private transient Map<String, Object> data; // Must not be final for deserialization
|
||||
private final Map<String, Object> data;
|
||||
|
||||
/**
|
||||
* Creates a new {@link JSON} root object.
|
||||
@@ -207,26 +202,6 @@ public final class JSON implements Serializable {
|
||||
return Collections.unmodifiableMap(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Serialize the data map in JSON.
|
||||
*/
|
||||
private void writeObject(ObjectOutputStream out) throws IOException {
|
||||
out.writeUTF(JsonUtil.toJson(data));
|
||||
out.defaultWriteObject();
|
||||
}
|
||||
|
||||
/**
|
||||
* Deserialize the JSON representation of the data map.
|
||||
*/
|
||||
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
|
||||
try {
|
||||
data = new HashMap<>(JsonUtil.parseJson(in.readUTF()));
|
||||
in.defaultReadObject();
|
||||
} catch (JoseException ex) {
|
||||
throw new AcmeProtocolException("Cannot deserialize", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a JSON array.
|
||||
*/
|
||||
@@ -369,20 +344,15 @@ public final class JSON implements Serializable {
|
||||
* Returns the value as {@link String}.
|
||||
*/
|
||||
public String asString() {
|
||||
required();
|
||||
return val.toString();
|
||||
return required().toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value as JSON object.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public JSON asObject() {
|
||||
required();
|
||||
try {
|
||||
return new JSON(path, (Map<String, Object>) val);
|
||||
} catch (ClassCastException ex) {
|
||||
throw new AcmeProtocolException(path + ": expected an object", ex);
|
||||
}
|
||||
return new JSON(path, (Map<String, Object>) required(Map.class));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -391,9 +361,8 @@ public final class JSON implements Serializable {
|
||||
* @since 2.8
|
||||
*/
|
||||
public JSON asEncodedObject() {
|
||||
required();
|
||||
try {
|
||||
var raw = AcmeUtils.base64UrlDecode(val.toString());
|
||||
var raw = AcmeUtils.base64UrlDecode(asString());
|
||||
return new JSON(path, JsonUtil.parseJson(new String(raw, UTF_8)));
|
||||
} catch (IllegalArgumentException | JoseException ex) {
|
||||
throw new AcmeProtocolException(path + ": expected an encoded object", ex);
|
||||
@@ -407,7 +376,6 @@ public final class JSON implements Serializable {
|
||||
* Base {@link URL} to resolve relative links against
|
||||
*/
|
||||
public Problem asProblem(URL baseUrl) {
|
||||
required();
|
||||
return new Problem(asObject(), baseUrl);
|
||||
}
|
||||
|
||||
@@ -417,7 +385,6 @@ public final class JSON implements Serializable {
|
||||
* @since 2.3
|
||||
*/
|
||||
public Identifier asIdentifier() {
|
||||
required();
|
||||
return new Identifier(asObject());
|
||||
}
|
||||
|
||||
@@ -427,6 +394,7 @@ public final class JSON implements Serializable {
|
||||
* Unlike the other getters, this method returns an empty array if the value is
|
||||
* not set. Use {@link #isPresent()} to find out if the value was actually set.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public Array asArray() {
|
||||
if (val == null) {
|
||||
return new Array(path, Collections.emptyList());
|
||||
@@ -443,33 +411,22 @@ public final class JSON implements Serializable {
|
||||
* Returns the value as int.
|
||||
*/
|
||||
public int asInt() {
|
||||
required();
|
||||
try {
|
||||
return ((Number) val).intValue();
|
||||
} catch (ClassCastException ex) {
|
||||
throw new AcmeProtocolException(path + ": bad number " + val, ex);
|
||||
}
|
||||
return (required(Number.class)).intValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value as boolean.
|
||||
*/
|
||||
public boolean asBoolean() {
|
||||
required();
|
||||
try {
|
||||
return (Boolean) val;
|
||||
} catch (ClassCastException ex) {
|
||||
throw new AcmeProtocolException(path + ": bad boolean " + val, ex);
|
||||
}
|
||||
return required(Boolean.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value as {@link URI}.
|
||||
*/
|
||||
public URI asURI() {
|
||||
required();
|
||||
try {
|
||||
return new URI(val.toString());
|
||||
return new URI(asString());
|
||||
} catch (URISyntaxException ex) {
|
||||
throw new AcmeProtocolException(path + ": bad URI " + val, ex);
|
||||
}
|
||||
@@ -479,9 +436,8 @@ public final class JSON implements Serializable {
|
||||
* Returns the value as {@link URL}.
|
||||
*/
|
||||
public URL asURL() {
|
||||
required();
|
||||
try {
|
||||
return new URL(val.toString());
|
||||
return new URL(asString());
|
||||
} catch (MalformedURLException ex) {
|
||||
throw new AcmeProtocolException(path + ": bad URL " + val, ex);
|
||||
}
|
||||
@@ -491,9 +447,8 @@ public final class JSON implements Serializable {
|
||||
* Returns the value as {@link Instant}.
|
||||
*/
|
||||
public Instant asInstant() {
|
||||
required();
|
||||
try {
|
||||
return parseTimestamp(val.toString());
|
||||
return parseTimestamp(asString());
|
||||
} catch (IllegalArgumentException ex) {
|
||||
throw new AcmeProtocolException(path + ": bad date " + val, ex);
|
||||
}
|
||||
@@ -505,38 +460,52 @@ public final class JSON implements Serializable {
|
||||
* @since 2.3
|
||||
*/
|
||||
public Duration asDuration() {
|
||||
required();
|
||||
try {
|
||||
return Duration.ofSeconds(((Number) val).longValue());
|
||||
} catch (ClassCastException ex) {
|
||||
throw new AcmeProtocolException(path + ": bad duration " + val, ex);
|
||||
}
|
||||
return Duration.ofSeconds(required(Number.class).longValue());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value as base64 decoded byte array.
|
||||
*/
|
||||
public byte[] asBinary() {
|
||||
required();
|
||||
return AcmeUtils.base64UrlDecode(val.toString());
|
||||
return AcmeUtils.base64UrlDecode(asString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the parsed {@link Status}.
|
||||
*/
|
||||
public Status asStatus() {
|
||||
required();
|
||||
return Status.parse(val.toString());
|
||||
return Status.parse(asString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the value is present. An {@link AcmeProtocolException} is thrown if
|
||||
* the value is {@code null}.
|
||||
*
|
||||
* @return val that is guaranteed to be non-{@code null}
|
||||
*/
|
||||
private void required() {
|
||||
if (!isPresent()) {
|
||||
private Object required() {
|
||||
if (val == null) {
|
||||
throw new AcmeProtocolException(path + ": required, but not set");
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the value is present. An {@link AcmeProtocolException} is thrown if
|
||||
* the value is {@code null} or is not of the expected type.
|
||||
*
|
||||
* @param type
|
||||
* expected type
|
||||
* @return val that is guaranteed to be non-{@code null}
|
||||
*/
|
||||
private <T> T required(Class<T> type) {
|
||||
if (val == null) {
|
||||
throw new AcmeProtocolException(path + ": required, but not set");
|
||||
}
|
||||
if (!type.isInstance(val)) {
|
||||
throw new AcmeProtocolException(path + ": cannot convert to " + type.getSimpleName());
|
||||
}
|
||||
return type.cast(val);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
Reference in New Issue
Block a user