From b32f03b23abece9d5803f49579ce37b09b38cc73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Richard=20K=C3=B6rber?= Date: Tue, 2 Jun 2020 12:42:49 +0200 Subject: [PATCH] Replace JSR305 null-safe annotations by SpotBugs annotations Reason is that JSR305 annotations cannot be used in a modular environment due to split package issues. --- .../java/org/shredzone/acme4j/Account.java | 10 +++----- .../org/shredzone/acme4j/AccountBuilder.java | 15 ++++++----- .../shredzone/acme4j/AcmeJsonResource.java | 6 ++--- .../org/shredzone/acme4j/AcmeResource.java | 5 ++-- .../org/shredzone/acme4j/Authorization.java | 11 +++----- .../org/shredzone/acme4j/Certificate.java | 12 +++------ .../java/org/shredzone/acme4j/Identifier.java | 5 ---- .../main/java/org/shredzone/acme4j/Login.java | 5 ---- .../java/org/shredzone/acme4j/Metadata.java | 13 ++++------ .../main/java/org/shredzone/acme4j/Order.java | 25 ++++++++----------- .../org/shredzone/acme4j/OrderBuilder.java | 16 ++++++------ .../java/org/shredzone/acme4j/Problem.java | 15 ++++------- .../shredzone/acme4j/RevocationReason.java | 8 ++---- .../java/org/shredzone/acme4j/Session.java | 20 ++++++--------- .../java/org/shredzone/acme4j/Status.java | 5 ---- .../shredzone/acme4j/challenge/Challenge.java | 9 +++---- .../acme4j/challenge/Dns01Challenge.java | 3 --- .../acme4j/challenge/Http01Challenge.java | 3 --- .../acme4j/challenge/TlsAlpn01Challenge.java | 3 --- .../acme4j/challenge/TokenChallenge.java | 3 --- .../acme4j/challenge/package-info.java | 23 +++++++++++++++++ .../acme4j/connector/Connection.java | 10 +++----- .../acme4j/connector/DefaultConnection.java | 16 +++++------- .../acme4j/connector/HttpConnector.java | 7 ------ .../acme4j/connector/NetworkSettings.java | 4 +-- .../shredzone/acme4j/connector/Resource.java | 5 ---- .../acme4j/connector/ResourceIterator.java | 7 ++---- .../acme4j/connector/TrimmingInputStream.java | 3 --- .../acme4j/connector/package-info.java | 23 +++++++++++++++++ .../acme4j/exception/AcmeException.java | 5 ---- .../exception/AcmeLazyLoadingException.java | 5 ---- .../exception/AcmeNetworkException.java | 5 ---- .../exception/AcmeProtocolException.java | 5 ---- .../exception/AcmeRateLimitedException.java | 16 ++++-------- .../exception/AcmeRetryAfterException.java | 5 ---- .../acme4j/exception/AcmeServerException.java | 5 ---- .../exception/AcmeUnauthorizedException.java | 5 ---- .../AcmeUserActionRequiredException.java | 12 +++------ .../acme4j/exception/package-info.java | 23 +++++++++++++++++ .../org/shredzone/acme4j/package-info.java | 23 +++++++++++++++++ .../acme4j/provider/AbstractAcmeProvider.java | 3 --- .../acme4j/provider/AcmeProvider.java | 9 +++---- .../acme4j/provider/GenericAcmeProvider.java | 3 --- .../letsencrypt/LetsEncryptAcmeProvider.java | 3 --- .../provider/letsencrypt/package-info.java | 23 +++++++++++++++++ .../acme4j/provider/package-info.java | 23 +++++++++++++++++ .../provider/pebble/PebbleAcmeProvider.java | 3 --- .../provider/pebble/PebbleHttpConnector.java | 10 +++----- .../acme4j/provider/pebble/package-info.java | 23 +++++++++++++++++ .../shredzone/acme4j/toolbox/AcmeUtils.java | 16 +++--------- .../org/shredzone/acme4j/toolbox/JSON.java | 17 +++---------- .../shredzone/acme4j/toolbox/JSONBuilder.java | 5 +--- .../shredzone/acme4j/toolbox/JoseUtils.java | 6 ++--- .../acme4j/toolbox/package-info.java | 23 +++++++++++++++++ .../provider/AbstractAcmeProviderTest.java | 3 --- .../shredzone/acme4j/it/BammBammClient.java | 3 --- .../org/shredzone/acme4j/it/package-info.java | 23 +++++++++++++++++ .../org/shredzone/acme4j/util/CSRBuilder.java | 11 +++----- .../acme4j/util/CertificateUtils.java | 6 +---- .../shredzone/acme4j/util/KeyPairUtils.java | 8 ++---- .../shredzone/acme4j/util/package-info.java | 23 +++++++++++++++++ pom.xml | 22 ++++++++-------- src/doc/docs/migration.md | 3 +++ 63 files changed, 350 insertions(+), 318 deletions(-) create mode 100644 acme4j-client/src/main/java/org/shredzone/acme4j/challenge/package-info.java create mode 100644 acme4j-client/src/main/java/org/shredzone/acme4j/connector/package-info.java create mode 100644 acme4j-client/src/main/java/org/shredzone/acme4j/exception/package-info.java create mode 100644 acme4j-client/src/main/java/org/shredzone/acme4j/package-info.java create mode 100644 acme4j-client/src/main/java/org/shredzone/acme4j/provider/letsencrypt/package-info.java create mode 100644 acme4j-client/src/main/java/org/shredzone/acme4j/provider/package-info.java create mode 100644 acme4j-client/src/main/java/org/shredzone/acme4j/provider/pebble/package-info.java create mode 100644 acme4j-client/src/main/java/org/shredzone/acme4j/toolbox/package-info.java create mode 100644 acme4j-it/src/main/java/org/shredzone/acme4j/it/package-info.java create mode 100644 acme4j-utils/src/main/java/org/shredzone/acme4j/util/package-info.java diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/Account.java b/acme4j-client/src/main/java/org/shredzone/acme4j/Account.java index 109d79af..56c6b494 100644 --- a/acme4j-client/src/main/java/org/shredzone/acme4j/Account.java +++ b/acme4j-client/src/main/java/org/shredzone/acme4j/Account.java @@ -26,9 +26,7 @@ import java.util.List; import java.util.Objects; import java.util.Optional; -import javax.annotation.CheckForNull; -import javax.annotation.ParametersAreNonnullByDefault; - +import edu.umd.cs.findbugs.annotations.Nullable; import org.shredzone.acme4j.connector.Connection; import org.shredzone.acme4j.connector.Resource; import org.shredzone.acme4j.connector.ResourceIterator; @@ -46,7 +44,6 @@ import org.slf4j.LoggerFactory; /** * Represents an account at the ACME server. */ -@ParametersAreNonnullByDefault public class Account extends AcmeJsonResource { private static final long serialVersionUID = 7042863483428051319L; private static final Logger LOG = LoggerFactory.getLogger(Account.class); @@ -67,7 +64,7 @@ public class Account extends AcmeJsonResource { * @return {@code true} if the user agreed to the terms of service. May be * {@code null} if the server did not provide such an information. */ - @CheckForNull + @Nullable public Boolean getTermsOfServiceAgreed() { return getJSON().get(KEY_TOS_AGREED).map(Value::asBoolean).orElse(null); } @@ -108,7 +105,7 @@ public class Account extends AcmeJsonResource { * * @since 2.8 */ - @CheckForNull + @Nullable public String getKeyIdentifier() { return getJSON().get(KEY_EXTERNAL_ACCOUNT_BINDING) .optional().map(Value::asObject) @@ -277,7 +274,6 @@ public class Account extends AcmeJsonResource { /** * Editable {@link Account}. */ - @ParametersAreNonnullByDefault public class EditableAccount { private final List editContacts = new ArrayList<>(); diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/AccountBuilder.java b/acme4j-client/src/main/java/org/shredzone/acme4j/AccountBuilder.java index 8fe44de7..3e69715b 100644 --- a/acme4j-client/src/main/java/org/shredzone/acme4j/AccountBuilder.java +++ b/acme4j-client/src/main/java/org/shredzone/acme4j/AccountBuilder.java @@ -21,10 +21,10 @@ import java.security.KeyPair; import java.util.ArrayList; import java.util.List; -import javax.annotation.ParametersAreNonnullByDefault; import javax.crypto.SecretKey; import javax.crypto.spec.SecretKeySpec; +import edu.umd.cs.findbugs.annotations.Nullable; import org.shredzone.acme4j.connector.Connection; import org.shredzone.acme4j.connector.Resource; import org.shredzone.acme4j.exception.AcmeException; @@ -38,16 +38,15 @@ import org.slf4j.LoggerFactory; /** * A builder for registering a new account. */ -@ParametersAreNonnullByDefault public class AccountBuilder { private static final Logger LOG = LoggerFactory.getLogger(AccountBuilder.class); - private List contacts = new ArrayList<>(); - private Boolean termsOfServiceAgreed; - private Boolean onlyExisting; - private String keyIdentifier; - private KeyPair keyPair; - private SecretKey macKey; + private final List contacts = new ArrayList<>(); + private @Nullable Boolean termsOfServiceAgreed; + private @Nullable Boolean onlyExisting; + private @Nullable String keyIdentifier; + private @Nullable KeyPair keyPair; + private @Nullable SecretKey macKey; /** * Add a contact URI to the list of contacts. diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/AcmeJsonResource.java b/acme4j-client/src/main/java/org/shredzone/acme4j/AcmeJsonResource.java index 99d2f849..86ea4952 100644 --- a/acme4j-client/src/main/java/org/shredzone/acme4j/AcmeJsonResource.java +++ b/acme4j-client/src/main/java/org/shredzone/acme4j/AcmeJsonResource.java @@ -16,8 +16,7 @@ package org.shredzone.acme4j; import java.net.URL; import java.util.Objects; -import javax.annotation.ParametersAreNonnullByDefault; - +import edu.umd.cs.findbugs.annotations.Nullable; import org.shredzone.acme4j.connector.Connection; import org.shredzone.acme4j.exception.AcmeException; import org.shredzone.acme4j.exception.AcmeLazyLoadingException; @@ -29,12 +28,11 @@ import org.slf4j.LoggerFactory; /** * An ACME resource that stores its state in a JSON structure. */ -@ParametersAreNonnullByDefault public abstract class AcmeJsonResource extends AcmeResource { private static final long serialVersionUID = -5060364275766082345L; private static final Logger LOG = LoggerFactory.getLogger(AcmeJsonResource.class); - private JSON data = null; + private @Nullable JSON data = null; /** * Create a new {@link AcmeJsonResource}. diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/AcmeResource.java b/acme4j-client/src/main/java/org/shredzone/acme4j/AcmeResource.java index 125ea232..4e320b3a 100644 --- a/acme4j-client/src/main/java/org/shredzone/acme4j/AcmeResource.java +++ b/acme4j-client/src/main/java/org/shredzone/acme4j/AcmeResource.java @@ -17,16 +17,15 @@ import java.io.Serializable; import java.net.URL; import java.util.Objects; -import javax.annotation.ParametersAreNonnullByDefault; +import edu.umd.cs.findbugs.annotations.Nullable; /** * A generic ACME resource. */ -@ParametersAreNonnullByDefault public abstract class AcmeResource implements Serializable { private static final long serialVersionUID = -7930580802257379731L; - private transient Login login; + private transient @Nullable Login login; private final URL location; /** diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/Authorization.java b/acme4j-client/src/main/java/org/shredzone/acme4j/Authorization.java index 90aa45e4..f5489deb 100644 --- a/acme4j-client/src/main/java/org/shredzone/acme4j/Authorization.java +++ b/acme4j-client/src/main/java/org/shredzone/acme4j/Authorization.java @@ -20,9 +20,7 @@ import java.time.Instant; import java.util.Collections; import java.util.List; -import javax.annotation.CheckForNull; -import javax.annotation.ParametersAreNonnullByDefault; - +import edu.umd.cs.findbugs.annotations.Nullable; import org.shredzone.acme4j.challenge.Challenge; import org.shredzone.acme4j.connector.Connection; import org.shredzone.acme4j.exception.AcmeException; @@ -36,7 +34,6 @@ import org.slf4j.LoggerFactory; /** * Represents an authorization request at the ACME server. */ -@ParametersAreNonnullByDefault public class Authorization extends AcmeJsonResource { private static final long serialVersionUID = -3116928998379417741L; private static final Logger LOG = LoggerFactory.getLogger(Authorization.class); @@ -72,7 +69,7 @@ public class Authorization extends AcmeJsonResource { /** * Gets the expiry date of the authorization, if set by the server. */ - @CheckForNull + @Nullable public Instant getExpires() { return getJSON().get("expires") .map(Value::asString) @@ -118,7 +115,7 @@ public class Authorization extends AcmeJsonResource { * @throws ClassCastException * if the type does not match the expected Challenge class type */ - @CheckForNull + @Nullable public T findChallenge(final String type) { return (T) getChallenges().stream() .filter(ch -> type.equals(ch.getType())) @@ -136,7 +133,7 @@ public class Authorization extends AcmeJsonResource { * challenge, or if the challenge alone is not sufficient for authorization. * @since 2.8 */ - @CheckForNull + @Nullable public T findChallenge(Class type) { return getChallenges().stream() .filter(type::isInstance) diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/Certificate.java b/acme4j-client/src/main/java/org/shredzone/acme4j/Certificate.java index 8f866bb1..5816109a 100644 --- a/acme4j-client/src/main/java/org/shredzone/acme4j/Certificate.java +++ b/acme4j-client/src/main/java/org/shredzone/acme4j/Certificate.java @@ -25,10 +25,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; -import javax.annotation.Nullable; -import javax.annotation.ParametersAreNonnullByDefault; -import javax.annotation.WillNotClose; - +import edu.umd.cs.findbugs.annotations.Nullable; import org.shredzone.acme4j.connector.Connection; import org.shredzone.acme4j.connector.Resource; import org.shredzone.acme4j.exception.AcmeException; @@ -45,13 +42,12 @@ import org.slf4j.LoggerFactory; * Note that a certificate is immutable once it is issued. For renewal, a new certificate * must be ordered. */ -@ParametersAreNonnullByDefault public class Certificate extends AcmeResource { private static final long serialVersionUID = 7381527770159084201L; private static final Logger LOG = LoggerFactory.getLogger(Certificate.class); - private ArrayList certChain; - private ArrayList alternates; + private @Nullable ArrayList certChain; + private @Nullable ArrayList alternates; protected Certificate(Login login, URL certUrl) { super(login, certUrl); @@ -121,7 +117,7 @@ public class Certificate extends AcmeResource { * @param out * {@link Writer} to write to. The writer is not closed after use. */ - public void writeCertificate(@WillNotClose Writer out) throws IOException { + public void writeCertificate(Writer out) throws IOException { try { for (X509Certificate cert : getCertificateChain()) { AcmeUtils.writeToPem(cert.getEncoded(), AcmeUtils.PemLabel.CERTIFICATE, out); diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/Identifier.java b/acme4j-client/src/main/java/org/shredzone/acme4j/Identifier.java index ceee5a0d..e128947a 100644 --- a/acme4j-client/src/main/java/org/shredzone/acme4j/Identifier.java +++ b/acme4j-client/src/main/java/org/shredzone/acme4j/Identifier.java @@ -21,9 +21,6 @@ import java.net.InetAddress; import java.net.UnknownHostException; import java.util.Map; -import javax.annotation.ParametersAreNonnullByDefault; -import javax.annotation.concurrent.Immutable; - import org.shredzone.acme4j.exception.AcmeProtocolException; import org.shredzone.acme4j.toolbox.JSON; import org.shredzone.acme4j.toolbox.JSONBuilder; @@ -38,8 +35,6 @@ import org.shredzone.acme4j.toolbox.JSONBuilder; * * @since 2.3 */ -@ParametersAreNonnullByDefault -@Immutable public class Identifier implements Serializable { private static final long serialVersionUID = -7777851842076362412L; diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/Login.java b/acme4j-client/src/main/java/org/shredzone/acme4j/Login.java index ebcaa296..9ce189f8 100644 --- a/acme4j-client/src/main/java/org/shredzone/acme4j/Login.java +++ b/acme4j-client/src/main/java/org/shredzone/acme4j/Login.java @@ -19,9 +19,6 @@ import java.net.URL; import java.security.KeyPair; import java.util.Objects; -import javax.annotation.ParametersAreNonnullByDefault; -import javax.annotation.concurrent.ThreadSafe; - import org.shredzone.acme4j.challenge.Challenge; import org.shredzone.acme4j.connector.Connection; import org.shredzone.acme4j.exception.AcmeException; @@ -37,8 +34,6 @@ import org.shredzone.acme4j.toolbox.JSON; * Note that {@link Login} objects are not serializable, as they contain a keypair and * volatile data. */ -@ParametersAreNonnullByDefault -@ThreadSafe public class Login { private final Session session; diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/Metadata.java b/acme4j-client/src/main/java/org/shredzone/acme4j/Metadata.java index dcb12943..db72e21b 100644 --- a/acme4j-client/src/main/java/org/shredzone/acme4j/Metadata.java +++ b/acme4j-client/src/main/java/org/shredzone/acme4j/Metadata.java @@ -21,18 +21,13 @@ import java.time.Duration; import java.util.Collection; import java.util.Optional; -import javax.annotation.CheckForNull; -import javax.annotation.ParametersAreNonnullByDefault; -import javax.annotation.concurrent.Immutable; - +import edu.umd.cs.findbugs.annotations.Nullable; import org.shredzone.acme4j.toolbox.JSON; import org.shredzone.acme4j.toolbox.JSON.Value; /** * Contains metadata related to the provider. */ -@ParametersAreNonnullByDefault -@Immutable public class Metadata { private final JSON meta; @@ -51,7 +46,7 @@ public class Metadata { * Returns an {@link URI} to the current terms of service, or {@code null} if not * available. */ - @CheckForNull + @Nullable public URI getTermsOfService() { return meta.get("termsOfService").map(Value::asURI).orElse(null); } @@ -60,7 +55,7 @@ public class Metadata { * Returns an {@link URL} to a website providing more information about the ACME * server. {@code null} if not available. */ - @CheckForNull + @Nullable public URL getWebsite() { return meta.get("website").map(Value::asURL).orElse(null); } @@ -100,6 +95,7 @@ public class Metadata { * * @since 2.3 */ + @Nullable public Duration getAutoRenewalMinLifetime() { Optional ar = meta.get("auto-renewal").optional().map(Value::asObject); if (!ar.isPresent()) { @@ -114,6 +110,7 @@ public class Metadata { * * @since 2.3 */ + @Nullable public Duration getAutoRenewalMaxDuration() { Optional ar = meta.get("auto-renewal").optional().map(Value::asObject); if (!ar.isPresent()) { diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/Order.java b/acme4j-client/src/main/java/org/shredzone/acme4j/Order.java index c9503668..a15577c3 100644 --- a/acme4j-client/src/main/java/org/shredzone/acme4j/Order.java +++ b/acme4j-client/src/main/java/org/shredzone/acme4j/Order.java @@ -21,9 +21,7 @@ import java.time.Instant; import java.util.Collections; import java.util.List; -import javax.annotation.CheckForNull; -import javax.annotation.ParametersAreNonnullByDefault; - +import edu.umd.cs.findbugs.annotations.Nullable; import org.shredzone.acme4j.connector.Connection; import org.shredzone.acme4j.exception.AcmeException; import org.shredzone.acme4j.toolbox.JSON; @@ -35,7 +33,6 @@ import org.slf4j.LoggerFactory; /** * Represents a certificate order. */ -@ParametersAreNonnullByDefault public class Order extends AcmeJsonResource { private static final long serialVersionUID = 5435808648658292177L; private static final Logger LOG = LoggerFactory.getLogger(Order.class); @@ -57,7 +54,7 @@ public class Order extends AcmeJsonResource { /** * Returns a {@link Problem} document if the order failed. */ - @CheckForNull + @Nullable public Problem getError() { return getJSON().get("error").map(v -> v.asProblem(getLocation())).orElse(null); } @@ -65,7 +62,7 @@ public class Order extends AcmeJsonResource { /** * Gets the expiry date of the authorization, if set by the server. */ - @CheckForNull + @Nullable public Instant getExpires() { return getJSON().get("expires").map(Value::asInstant).orElse(null); } @@ -86,7 +83,7 @@ public class Order extends AcmeJsonResource { /** * Gets the "not before" date that was used for the order, or {@code null}. */ - @CheckForNull + @Nullable public Instant getNotBefore() { return getJSON().get("notBefore").map(Value::asInstant).orElse(null); } @@ -94,7 +91,7 @@ public class Order extends AcmeJsonResource { /** * Gets the "not after" date that was used for the order, or {@code null}. */ - @CheckForNull + @Nullable public Instant getNotAfter() { return getJSON().get("notAfter").map(Value::asInstant).orElse(null); } @@ -124,7 +121,7 @@ public class Order extends AcmeJsonResource { /** * Gets the {@link Certificate} if it is available. {@code null} otherwise. */ - @CheckForNull + @Nullable public Certificate getCertificate() { return getJSON().get("certificate") .map(Value::asURL) @@ -138,7 +135,7 @@ public class Order extends AcmeJsonResource { * * @since 2.6 */ - @CheckForNull + @Nullable public Certificate getAutoRenewalCertificate() { return getJSON().get("star-certificate") .map(Value::asURL) @@ -188,7 +185,7 @@ public class Order extends AcmeJsonResource { * * @since 2.3 */ - @CheckForNull + @Nullable public Instant getAutoRenewalStartDate() { return getJSON().get("auto-renewal") .optional() @@ -206,7 +203,7 @@ public class Order extends AcmeJsonResource { * * @since 2.3 */ - @CheckForNull + @Nullable public Instant getAutoRenewalEndDate() { return getJSON().get("auto-renewal") .optional() @@ -223,7 +220,7 @@ public class Order extends AcmeJsonResource { * * @since 2.3 */ - @CheckForNull + @Nullable public Duration getAutoRenewalLifetime() { return getJSON().get("auto-renewal") .optional() @@ -240,7 +237,7 @@ public class Order extends AcmeJsonResource { * * @since 2.7 */ - @CheckForNull + @Nullable public Duration getAutoRenewalLifetimeAdjust() { return getJSON().get("auto-renewal") .optional() diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/OrderBuilder.java b/acme4j-client/src/main/java/org/shredzone/acme4j/OrderBuilder.java index 0b5b84ef..10dd4ff9 100644 --- a/acme4j-client/src/main/java/org/shredzone/acme4j/OrderBuilder.java +++ b/acme4j-client/src/main/java/org/shredzone/acme4j/OrderBuilder.java @@ -23,8 +23,7 @@ import java.util.Collection; import java.util.LinkedHashSet; import java.util.Set; -import javax.annotation.ParametersAreNonnullByDefault; - +import edu.umd.cs.findbugs.annotations.Nullable; import org.shredzone.acme4j.connector.Connection; import org.shredzone.acme4j.connector.Resource; import org.shredzone.acme4j.exception.AcmeException; @@ -36,20 +35,19 @@ import org.slf4j.LoggerFactory; /** * A builder for a new {@link Order} object. */ -@ParametersAreNonnullByDefault public class OrderBuilder { private static final Logger LOG = LoggerFactory.getLogger(OrderBuilder.class); private final Login login; private final Set identifierSet = new LinkedHashSet<>(); - private Instant notBefore; - private Instant notAfter; + private @Nullable Instant notBefore; + private @Nullable Instant notAfter; private boolean autoRenewal; - private Instant autoRenewalStart; - private Instant autoRenewalEnd; - private Duration autoRenewalLifetime; - private Duration autoRenewalLifetimeAdjust; + private @Nullable Instant autoRenewalStart; + private @Nullable Instant autoRenewalEnd; + private @Nullable Duration autoRenewalLifetime; + private @Nullable Duration autoRenewalLifetimeAdjust; private boolean autoRenewalGet; /** diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/Problem.java b/acme4j-client/src/main/java/org/shredzone/acme4j/Problem.java index 8daa5e74..2214b1eb 100644 --- a/acme4j-client/src/main/java/org/shredzone/acme4j/Problem.java +++ b/acme4j-client/src/main/java/org/shredzone/acme4j/Problem.java @@ -22,10 +22,7 @@ import java.net.URISyntaxException; import java.net.URL; import java.util.List; -import javax.annotation.CheckForNull; -import javax.annotation.ParametersAreNonnullByDefault; -import javax.annotation.concurrent.Immutable; - +import edu.umd.cs.findbugs.annotations.Nullable; import org.shredzone.acme4j.exception.AcmeProtocolException; import org.shredzone.acme4j.toolbox.JSON; import org.shredzone.acme4j.toolbox.JSON.Value; @@ -35,8 +32,6 @@ import org.shredzone.acme4j.toolbox.JSON.Value; * * @see RFC 7807 */ -@ParametersAreNonnullByDefault -@Immutable public class Problem implements Serializable { private static final long serialVersionUID = -8418248862966754214L; @@ -78,7 +73,7 @@ public class Problem implements Serializable { * * @see #toString() */ - @CheckForNull + @Nullable public String getTitle() { return problemJson.get("title").map(Value::asString).orElse(null); } @@ -89,7 +84,7 @@ public class Problem implements Serializable { * * @see #toString() */ - @CheckForNull + @Nullable public String getDetail() { return problemJson.get("detail").map(Value::asString).orElse(null); } @@ -98,7 +93,7 @@ public class Problem implements Serializable { * Returns an URI that identifies the specific occurence of the problem. It is always * an absolute URI. */ - @CheckForNull + @Nullable public URI getInstance() { return problemJson.get("instance") .map(Value::asString) @@ -117,7 +112,7 @@ public class Problem implements Serializable { * * @since 2.3 */ - @CheckForNull + @Nullable public Identifier getIdentifier() { return problemJson.get("identifier") .optional() diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/RevocationReason.java b/acme4j-client/src/main/java/org/shredzone/acme4j/RevocationReason.java index a6cb55a3..399c8674 100644 --- a/acme4j-client/src/main/java/org/shredzone/acme4j/RevocationReason.java +++ b/acme4j-client/src/main/java/org/shredzone/acme4j/RevocationReason.java @@ -15,9 +15,7 @@ package org.shredzone.acme4j; import java.util.Arrays; -import javax.annotation.CheckForNull; -import javax.annotation.ParametersAreNonnullByDefault; -import javax.annotation.concurrent.Immutable; +import edu.umd.cs.findbugs.annotations.Nullable; /** * Enumeration of revocation reasons. @@ -25,8 +23,6 @@ import javax.annotation.concurrent.Immutable; * @see RFC 5280 Section * 5.3.1 */ -@ParametersAreNonnullByDefault -@Immutable public enum RevocationReason { UNSPECIFIED(0), @@ -60,7 +56,7 @@ public enum RevocationReason { * Reason code as defined in RFC 5280 * @return Matching {@link RevocationReason}, or {@code null} if not known */ - @CheckForNull + @Nullable public static RevocationReason code(int reasonCode) { return Arrays.stream(values()) .filter(rr -> rr.reasonCode == reasonCode) diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/Session.java b/acme4j-client/src/main/java/org/shredzone/acme4j/Session.java index 7387be88..5cfce7e6 100644 --- a/acme4j-client/src/main/java/org/shredzone/acme4j/Session.java +++ b/acme4j-client/src/main/java/org/shredzone/acme4j/Session.java @@ -26,11 +26,7 @@ import java.util.ServiceLoader; import java.util.concurrent.atomic.AtomicReference; import java.util.stream.StreamSupport; -import javax.annotation.CheckForNull; -import javax.annotation.Nullable; -import javax.annotation.ParametersAreNonnullByDefault; -import javax.annotation.concurrent.ThreadSafe; - +import edu.umd.cs.findbugs.annotations.Nullable; import org.shredzone.acme4j.connector.Connection; import org.shredzone.acme4j.connector.NetworkSettings; import org.shredzone.acme4j.connector.Resource; @@ -43,8 +39,6 @@ import org.shredzone.acme4j.toolbox.JSON.Value; /** * A session stores the ACME server URI. It also tracks communication parameters. */ -@ParametersAreNonnullByDefault -@ThreadSafe public class Session { private static final GenericAcmeProvider GENERIC_PROVIDER = new GenericAcmeProvider(); @@ -55,10 +49,10 @@ public class Session { private final URI serverUri; private final AcmeProvider provider; - private String nonce; + private @Nullable String nonce; private Locale locale = Locale.getDefault(); - protected ZonedDateTime directoryLastModified; - protected ZonedDateTime directoryExpires; + protected @Nullable ZonedDateTime directoryLastModified; + protected @Nullable ZonedDateTime directoryExpires; /** * Creates a new {@link Session}. @@ -143,7 +137,7 @@ public class Session { /** * Gets the last base64 encoded nonce, or {@code null} if the session is new. */ - @CheckForNull + @Nullable public String getNonce() { return nonce; } @@ -256,7 +250,7 @@ public class Session { * (directory has not been read yet or did not provide this information). * @since 2.10 */ - @CheckForNull + @Nullable public ZonedDateTime getDirectoryLastModified() { return directoryLastModified; } @@ -282,7 +276,7 @@ public class Session { * information. * @since 2.10 */ - @CheckForNull + @Nullable public ZonedDateTime getDirectoryExpires() { return directoryExpires; } diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/Status.java b/acme4j-client/src/main/java/org/shredzone/acme4j/Status.java index 8e0ee2f6..17517aaa 100644 --- a/acme4j-client/src/main/java/org/shredzone/acme4j/Status.java +++ b/acme4j-client/src/main/java/org/shredzone/acme4j/Status.java @@ -15,14 +15,9 @@ package org.shredzone.acme4j; import java.util.Arrays; -import javax.annotation.ParametersAreNonnullByDefault; -import javax.annotation.concurrent.Immutable; - /** * Status codes of challenges and authorizations. */ -@ParametersAreNonnullByDefault -@Immutable public enum Status { /** diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/challenge/Challenge.java b/acme4j-client/src/main/java/org/shredzone/acme4j/challenge/Challenge.java index 7029789f..6e0bf638 100644 --- a/acme4j-client/src/main/java/org/shredzone/acme4j/challenge/Challenge.java +++ b/acme4j-client/src/main/java/org/shredzone/acme4j/challenge/Challenge.java @@ -15,9 +15,7 @@ package org.shredzone.acme4j.challenge; import java.time.Instant; -import javax.annotation.CheckForNull; -import javax.annotation.ParametersAreNonnullByDefault; - +import edu.umd.cs.findbugs.annotations.Nullable; import org.shredzone.acme4j.AcmeJsonResource; import org.shredzone.acme4j.Login; import org.shredzone.acme4j.Problem; @@ -40,7 +38,6 @@ import org.slf4j.LoggerFactory; * own type. {@link Challenge#prepareResponse(JSONBuilder)} should be overridden to put * all required data to the response. */ -@ParametersAreNonnullByDefault public class Challenge extends AcmeJsonResource { private static final long serialVersionUID = 2338794776848388099L; private static final Logger LOG = LoggerFactory.getLogger(Challenge.class); @@ -84,7 +81,7 @@ public class Challenge extends AcmeJsonResource { /** * Returns the validation date, if returned by the server. */ - @CheckForNull + @Nullable public Instant getValidated() { return getJSON().get(KEY_VALIDATED).map(Value::asInstant).orElse(null); } @@ -94,7 +91,7 @@ public class Challenge extends AcmeJsonResource { * server. If there are multiple errors, they can be found in * {@link Problem#getSubProblems()}. */ - @CheckForNull + @Nullable public Problem getError() { return getJSON().get(KEY_ERROR) .map(it -> it.asProblem(getLocation())) diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/challenge/Dns01Challenge.java b/acme4j-client/src/main/java/org/shredzone/acme4j/challenge/Dns01Challenge.java index 1e6d05af..098cf3b8 100644 --- a/acme4j-client/src/main/java/org/shredzone/acme4j/challenge/Dns01Challenge.java +++ b/acme4j-client/src/main/java/org/shredzone/acme4j/challenge/Dns01Challenge.java @@ -16,15 +16,12 @@ package org.shredzone.acme4j.challenge; import static org.shredzone.acme4j.toolbox.AcmeUtils.base64UrlEncode; import static org.shredzone.acme4j.toolbox.AcmeUtils.sha256hash; -import javax.annotation.ParametersAreNonnullByDefault; - import org.shredzone.acme4j.Login; import org.shredzone.acme4j.toolbox.JSON; /** * Implements the {@value TYPE} challenge. */ -@ParametersAreNonnullByDefault public class Dns01Challenge extends TokenChallenge { private static final long serialVersionUID = 6964687027713533075L; diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/challenge/Http01Challenge.java b/acme4j-client/src/main/java/org/shredzone/acme4j/challenge/Http01Challenge.java index 8ccc27fe..675c0a37 100644 --- a/acme4j-client/src/main/java/org/shredzone/acme4j/challenge/Http01Challenge.java +++ b/acme4j-client/src/main/java/org/shredzone/acme4j/challenge/Http01Challenge.java @@ -13,15 +13,12 @@ */ package org.shredzone.acme4j.challenge; -import javax.annotation.ParametersAreNonnullByDefault; - import org.shredzone.acme4j.Login; import org.shredzone.acme4j.toolbox.JSON; /** * Implements the {@value TYPE} challenge. */ -@ParametersAreNonnullByDefault public class Http01Challenge extends TokenChallenge { private static final long serialVersionUID = 3322211185872544605L; diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/challenge/TlsAlpn01Challenge.java b/acme4j-client/src/main/java/org/shredzone/acme4j/challenge/TlsAlpn01Challenge.java index 6f25ba51..8403164d 100644 --- a/acme4j-client/src/main/java/org/shredzone/acme4j/challenge/TlsAlpn01Challenge.java +++ b/acme4j-client/src/main/java/org/shredzone/acme4j/challenge/TlsAlpn01Challenge.java @@ -15,8 +15,6 @@ package org.shredzone.acme4j.challenge; import static org.shredzone.acme4j.toolbox.AcmeUtils.sha256hash; -import javax.annotation.ParametersAreNonnullByDefault; - import org.shredzone.acme4j.Login; import org.shredzone.acme4j.toolbox.JSON; @@ -25,7 +23,6 @@ import org.shredzone.acme4j.toolbox.JSON; * * @since 2.1 */ -@ParametersAreNonnullByDefault public class TlsAlpn01Challenge extends TokenChallenge { private static final long serialVersionUID = -5590351078176091228L; diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/challenge/TokenChallenge.java b/acme4j-client/src/main/java/org/shredzone/acme4j/challenge/TokenChallenge.java index 60c1bbd1..0dd74092 100644 --- a/acme4j-client/src/main/java/org/shredzone/acme4j/challenge/TokenChallenge.java +++ b/acme4j-client/src/main/java/org/shredzone/acme4j/challenge/TokenChallenge.java @@ -17,8 +17,6 @@ import static org.shredzone.acme4j.toolbox.AcmeUtils.base64UrlEncode; import java.security.PublicKey; -import javax.annotation.ParametersAreNonnullByDefault; - import org.shredzone.acme4j.Login; import org.shredzone.acme4j.exception.AcmeProtocolException; import org.shredzone.acme4j.toolbox.AcmeUtils; @@ -29,7 +27,6 @@ import org.shredzone.acme4j.toolbox.JoseUtils; * An extension of {@link Challenge} that handles challenges with a {@code token} and * {@code keyAuthorization}. */ -@ParametersAreNonnullByDefault public class TokenChallenge extends Challenge { private static final long serialVersionUID = 1634133407432681800L; diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/challenge/package-info.java b/acme4j-client/src/main/java/org/shredzone/acme4j/challenge/package-info.java new file mode 100644 index 00000000..8f4a8540 --- /dev/null +++ b/acme4j-client/src/main/java/org/shredzone/acme4j/challenge/package-info.java @@ -0,0 +1,23 @@ +/* + * acme4j - Java ACME client + * + * Copyright (C) 2020 Richard "Shred" Körber + * http://acme4j.shredzone.org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + */ + +@ReturnValuesAreNonnullByDefault +@DefaultAnnotationForParameters(NonNull.class) +@DefaultAnnotationForFields(NonNull.class) +package org.shredzone.acme4j.challenge; + +import edu.umd.cs.findbugs.annotations.DefaultAnnotationForFields; +import edu.umd.cs.findbugs.annotations.DefaultAnnotationForParameters; +import edu.umd.cs.findbugs.annotations.NonNull; +import edu.umd.cs.findbugs.annotations.ReturnValuesAreNonnullByDefault; diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/connector/Connection.java b/acme4j-client/src/main/java/org/shredzone/acme4j/connector/Connection.java index 15504c5e..fe1a2f81 100644 --- a/acme4j-client/src/main/java/org/shredzone/acme4j/connector/Connection.java +++ b/acme4j-client/src/main/java/org/shredzone/acme4j/connector/Connection.java @@ -22,10 +22,7 @@ import java.util.Collection; import java.util.List; import java.util.Optional; -import javax.annotation.CheckForNull; -import javax.annotation.Nullable; -import javax.annotation.ParametersAreNonnullByDefault; - +import edu.umd.cs.findbugs.annotations.Nullable; import org.shredzone.acme4j.Login; import org.shredzone.acme4j.Session; import org.shredzone.acme4j.exception.AcmeException; @@ -37,7 +34,6 @@ import org.shredzone.acme4j.toolbox.JSONBuilder; /** * Connects to the ACME server and offers different methods for invoking the API. */ -@ParametersAreNonnullByDefault public interface Connection extends AutoCloseable { /** @@ -166,7 +162,7 @@ public interface Connection extends AutoCloseable { * * @return Base64 encoded nonce, or {@code null} if no nonce header was set */ - @CheckForNull + @Nullable String getNonce(); /** @@ -176,7 +172,7 @@ public interface Connection extends AutoCloseable { * * @return Location {@link URL}, or {@code null} if no Location header was set */ - @CheckForNull + @Nullable URL getLocation(); /** diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/connector/DefaultConnection.java b/acme4j-client/src/main/java/org/shredzone/acme4j/connector/DefaultConnection.java index 2413daad..50f645ea 100644 --- a/acme4j-client/src/main/java/org/shredzone/acme4j/connector/DefaultConnection.java +++ b/acme4j-client/src/main/java/org/shredzone/acme4j/connector/DefaultConnection.java @@ -41,10 +41,7 @@ import java.util.Optional; import java.util.regex.Matcher; import java.util.regex.Pattern; -import javax.annotation.CheckForNull; -import javax.annotation.Nullable; -import javax.annotation.ParametersAreNonnullByDefault; - +import edu.umd.cs.findbugs.annotations.Nullable; import org.shredzone.acme4j.Login; import org.shredzone.acme4j.Problem; import org.shredzone.acme4j.Session; @@ -66,7 +63,6 @@ import org.slf4j.LoggerFactory; /** * Default implementation of {@link Connection}. */ -@ParametersAreNonnullByDefault public class DefaultConnection implements Connection { private static final Logger LOG = LoggerFactory.getLogger(DefaultConnection.class); @@ -95,7 +91,7 @@ public class DefaultConnection implements Connection { private static final Pattern MAX_AGE_PATTERN = Pattern.compile("(?:^|.*?,)\\s*max-age=(\\d+)\\s*(?:,.*|$)", Pattern.CASE_INSENSITIVE); protected final HttpConnector httpConnector; - protected HttpURLConnection conn; + protected @Nullable HttpURLConnection conn; /** * Creates a new {@link DefaultConnection}. @@ -232,7 +228,7 @@ public class DefaultConnection implements Connection { } @Override - @CheckForNull + @Nullable public String getNonce() { assertConnectionIsOpen(); @@ -251,7 +247,7 @@ public class DefaultConnection implements Connection { } @Override - @CheckForNull + @Nullable public URL getLocation() { assertConnectionIsOpen(); @@ -625,7 +621,7 @@ public class DefaultConnection implements Connection { * @return Absolute URL of the given link, or {@code null} if the link was * {@code null}. */ - @CheckForNull + @Nullable private URL resolveRelative(@Nullable String link) { if (link == null) { return null; @@ -647,7 +643,7 @@ public class DefaultConnection implements Connection { * @return Absolute URI of the given link, or {@code null} if the URI was * {@code null}. */ - @CheckForNull + @Nullable private URI resolveUri(@Nullable String uri) { if (uri == null) { return null; diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/connector/HttpConnector.java b/acme4j-client/src/main/java/org/shredzone/acme4j/connector/HttpConnector.java index fe7215c3..840d81e4 100644 --- a/acme4j-client/src/main/java/org/shredzone/acme4j/connector/HttpConnector.java +++ b/acme4j-client/src/main/java/org/shredzone/acme4j/connector/HttpConnector.java @@ -19,10 +19,6 @@ import java.net.HttpURLConnection; import java.net.URL; import java.util.Properties; -import javax.annotation.OverridingMethodsMustInvokeSuper; -import javax.annotation.ParametersAreNonnullByDefault; -import javax.annotation.concurrent.ThreadSafe; - import org.slf4j.LoggerFactory; /** @@ -32,8 +28,6 @@ import org.slf4j.LoggerFactory; * Subclasses may reconfigure the {@link HttpURLConnection} and pin it to a concrete SSL * certificate. */ -@ParametersAreNonnullByDefault -@ThreadSafe public class HttpConnector { private static final String USER_AGENT; @@ -90,7 +84,6 @@ public class HttpConnector { * @param settings * {@link NetworkSettings} with settings to be used */ - @OverridingMethodsMustInvokeSuper protected void configure(HttpURLConnection conn, NetworkSettings settings) { int timeout = (int) settings.getTimeout().toMillis(); conn.setConnectTimeout(timeout); diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/connector/NetworkSettings.java b/acme4j-client/src/main/java/org/shredzone/acme4j/connector/NetworkSettings.java index d8dc74b6..e504f3ea 100644 --- a/acme4j-client/src/main/java/org/shredzone/acme4j/connector/NetworkSettings.java +++ b/acme4j-client/src/main/java/org/shredzone/acme4j/connector/NetworkSettings.java @@ -16,15 +16,13 @@ package org.shredzone.acme4j.connector; import java.net.Proxy; import java.time.Duration; -import javax.annotation.Nullable; -import javax.annotation.ParametersAreNonnullByDefault; +import edu.umd.cs.findbugs.annotations.Nullable; /** * Contains network settings to be used for network connections. * * @since 2.8 */ -@ParametersAreNonnullByDefault public class NetworkSettings { private Proxy proxy = Proxy.NO_PROXY; diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/connector/Resource.java b/acme4j-client/src/main/java/org/shredzone/acme4j/connector/Resource.java index b856324d..5e67772c 100644 --- a/acme4j-client/src/main/java/org/shredzone/acme4j/connector/Resource.java +++ b/acme4j-client/src/main/java/org/shredzone/acme4j/connector/Resource.java @@ -13,14 +13,9 @@ */ package org.shredzone.acme4j.connector; -import javax.annotation.ParametersAreNonnullByDefault; -import javax.annotation.concurrent.Immutable; - /** * Enumeration of resources. */ -@ParametersAreNonnullByDefault -@Immutable public enum Resource { NEW_NONCE("newNonce"), diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/connector/ResourceIterator.java b/acme4j-client/src/main/java/org/shredzone/acme4j/connector/ResourceIterator.java index 0463617f..ff24b775 100644 --- a/acme4j-client/src/main/java/org/shredzone/acme4j/connector/ResourceIterator.java +++ b/acme4j-client/src/main/java/org/shredzone/acme4j/connector/ResourceIterator.java @@ -21,9 +21,7 @@ import java.util.NoSuchElementException; import java.util.Objects; import java.util.function.BiFunction; -import javax.annotation.Nullable; -import javax.annotation.ParametersAreNonnullByDefault; - +import edu.umd.cs.findbugs.annotations.Nullable; import org.shredzone.acme4j.AcmeResource; import org.shredzone.acme4j.Login; import org.shredzone.acme4j.Session; @@ -38,7 +36,6 @@ import org.shredzone.acme4j.toolbox.JSON; * @param * {@link AcmeResource} type to iterate over */ -@ParametersAreNonnullByDefault public class ResourceIterator implements Iterator { private final Login login; @@ -46,7 +43,7 @@ public class ResourceIterator implements Iterator { private final Deque urlList = new ArrayDeque<>(); private final BiFunction creator; private boolean eol = false; - private URL nextUrl; + private @Nullable URL nextUrl; /** * Creates a new {@link ResourceIterator}. diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/connector/TrimmingInputStream.java b/acme4j-client/src/main/java/org/shredzone/acme4j/connector/TrimmingInputStream.java index de6f6ec6..29e29f68 100644 --- a/acme4j-client/src/main/java/org/shredzone/acme4j/connector/TrimmingInputStream.java +++ b/acme4j-client/src/main/java/org/shredzone/acme4j/connector/TrimmingInputStream.java @@ -16,13 +16,10 @@ package org.shredzone.acme4j.connector; import java.io.IOException; import java.io.InputStream; -import javax.annotation.ParametersAreNonnullByDefault; - /** * Normalizes line separators in an InputStream. Converts all line separators to '\n'. * Multiple line separators are compressed to a single line separator. */ -@ParametersAreNonnullByDefault public class TrimmingInputStream extends InputStream { private final InputStream in; diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/connector/package-info.java b/acme4j-client/src/main/java/org/shredzone/acme4j/connector/package-info.java new file mode 100644 index 00000000..79d44ef6 --- /dev/null +++ b/acme4j-client/src/main/java/org/shredzone/acme4j/connector/package-info.java @@ -0,0 +1,23 @@ +/* + * acme4j - Java ACME client + * + * Copyright (C) 2020 Richard "Shred" Körber + * http://acme4j.shredzone.org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + */ + +@ReturnValuesAreNonnullByDefault +@DefaultAnnotationForParameters(NonNull.class) +@DefaultAnnotationForFields(NonNull.class) +package org.shredzone.acme4j.connector; + +import edu.umd.cs.findbugs.annotations.DefaultAnnotationForFields; +import edu.umd.cs.findbugs.annotations.DefaultAnnotationForParameters; +import edu.umd.cs.findbugs.annotations.NonNull; +import edu.umd.cs.findbugs.annotations.ReturnValuesAreNonnullByDefault; diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/exception/AcmeException.java b/acme4j-client/src/main/java/org/shredzone/acme4j/exception/AcmeException.java index 76ae24cd..2a190429 100644 --- a/acme4j-client/src/main/java/org/shredzone/acme4j/exception/AcmeException.java +++ b/acme4j-client/src/main/java/org/shredzone/acme4j/exception/AcmeException.java @@ -13,14 +13,9 @@ */ package org.shredzone.acme4j.exception; -import javax.annotation.ParametersAreNonnullByDefault; -import javax.annotation.concurrent.Immutable; - /** * A generic ACME exception. */ -@ParametersAreNonnullByDefault -@Immutable public class AcmeException extends Exception { private static final long serialVersionUID = -2935088954705632025L; diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/exception/AcmeLazyLoadingException.java b/acme4j-client/src/main/java/org/shredzone/acme4j/exception/AcmeLazyLoadingException.java index 68031c9b..463710bd 100644 --- a/acme4j-client/src/main/java/org/shredzone/acme4j/exception/AcmeLazyLoadingException.java +++ b/acme4j-client/src/main/java/org/shredzone/acme4j/exception/AcmeLazyLoadingException.java @@ -17,17 +17,12 @@ import static java.util.Objects.requireNonNull; import java.net.URL; -import javax.annotation.ParametersAreNonnullByDefault; -import javax.annotation.concurrent.Immutable; - import org.shredzone.acme4j.AcmeResource; /** * This runtime exception is thrown when an {@link AcmeException} occured while trying to * lazy-load a resource from the ACME server. */ -@ParametersAreNonnullByDefault -@Immutable public class AcmeLazyLoadingException extends RuntimeException { private static final long serialVersionUID = 1000353433913721901L; diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/exception/AcmeNetworkException.java b/acme4j-client/src/main/java/org/shredzone/acme4j/exception/AcmeNetworkException.java index a46a0f2c..4b124cf8 100644 --- a/acme4j-client/src/main/java/org/shredzone/acme4j/exception/AcmeNetworkException.java +++ b/acme4j-client/src/main/java/org/shredzone/acme4j/exception/AcmeNetworkException.java @@ -15,15 +15,10 @@ package org.shredzone.acme4j.exception; import java.io.IOException; -import javax.annotation.ParametersAreNonnullByDefault; -import javax.annotation.concurrent.Immutable; - /** * This exception is thrown when a network error occured while communicating with the * server. */ -@ParametersAreNonnullByDefault -@Immutable public class AcmeNetworkException extends AcmeException { private static final long serialVersionUID = 2054398693543329179L; diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/exception/AcmeProtocolException.java b/acme4j-client/src/main/java/org/shredzone/acme4j/exception/AcmeProtocolException.java index 4c5f3a48..d4587104 100644 --- a/acme4j-client/src/main/java/org/shredzone/acme4j/exception/AcmeProtocolException.java +++ b/acme4j-client/src/main/java/org/shredzone/acme4j/exception/AcmeProtocolException.java @@ -13,15 +13,10 @@ */ package org.shredzone.acme4j.exception; -import javax.annotation.ParametersAreNonnullByDefault; -import javax.annotation.concurrent.Immutable; - /** * This runtime exception is thrown on ACME protocol errors that should not occur. For * example, this exception is thrown when a server response could not be parsed. */ -@ParametersAreNonnullByDefault -@Immutable public class AcmeProtocolException extends RuntimeException { private static final long serialVersionUID = 2031203835755725193L; diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/exception/AcmeRateLimitedException.java b/acme4j-client/src/main/java/org/shredzone/acme4j/exception/AcmeRateLimitedException.java index 068bab98..7ea410d4 100644 --- a/acme4j-client/src/main/java/org/shredzone/acme4j/exception/AcmeRateLimitedException.java +++ b/acme4j-client/src/main/java/org/shredzone/acme4j/exception/AcmeRateLimitedException.java @@ -18,23 +18,17 @@ import java.time.Instant; import java.util.Collection; import java.util.Collections; -import javax.annotation.CheckForNull; -import javax.annotation.Nullable; -import javax.annotation.ParametersAreNonnullByDefault; -import javax.annotation.concurrent.Immutable; - +import edu.umd.cs.findbugs.annotations.Nullable; import org.shredzone.acme4j.Problem; /** * An exception that is thrown when a rate limit was exceeded. */ -@ParametersAreNonnullByDefault -@Immutable public class AcmeRateLimitedException extends AcmeServerException { private static final long serialVersionUID = 4150484059796413069L; - private final Instant retryAfter; - private final Collection documents; + private final @Nullable Instant retryAfter; + private final @Nullable Collection documents; /** * Creates a new {@link AcmeRateLimitedException}. @@ -59,7 +53,7 @@ public class AcmeRateLimitedException extends AcmeServerException { * Returns the moment the request is expected to succeed again. {@code null} if this * moment is not known. */ - @CheckForNull + @Nullable public Instant getRetryAfter() { return retryAfter; } @@ -68,7 +62,7 @@ public class AcmeRateLimitedException extends AcmeServerException { * Collection of URLs pointing to documents about the rate limit that was hit. * {@code null} if the server did not provide such URLs. */ - @CheckForNull + @Nullable public Collection getDocuments() { return documents; } diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/exception/AcmeRetryAfterException.java b/acme4j-client/src/main/java/org/shredzone/acme4j/exception/AcmeRetryAfterException.java index 247b186a..19095073 100644 --- a/acme4j-client/src/main/java/org/shredzone/acme4j/exception/AcmeRetryAfterException.java +++ b/acme4j-client/src/main/java/org/shredzone/acme4j/exception/AcmeRetryAfterException.java @@ -16,15 +16,10 @@ package org.shredzone.acme4j.exception; import java.time.Instant; import java.util.Objects; -import javax.annotation.ParametersAreNonnullByDefault; -import javax.annotation.concurrent.Immutable; - /** * This exception is thrown when a server side process has not been completed yet, and the * server returned an estimated retry date. */ -@ParametersAreNonnullByDefault -@Immutable public class AcmeRetryAfterException extends AcmeException { private static final long serialVersionUID = 4461979121063649905L; diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/exception/AcmeServerException.java b/acme4j-client/src/main/java/org/shredzone/acme4j/exception/AcmeServerException.java index 6adef63c..e299b692 100644 --- a/acme4j-client/src/main/java/org/shredzone/acme4j/exception/AcmeServerException.java +++ b/acme4j-client/src/main/java/org/shredzone/acme4j/exception/AcmeServerException.java @@ -16,17 +16,12 @@ package org.shredzone.acme4j.exception; import java.net.URI; import java.util.Objects; -import javax.annotation.ParametersAreNonnullByDefault; -import javax.annotation.concurrent.Immutable; - import org.shredzone.acme4j.Problem; /** * An exception that is thrown when the ACME server returned an error. It contains * further details of the cause. */ -@ParametersAreNonnullByDefault -@Immutable public class AcmeServerException extends AcmeException { private static final long serialVersionUID = 5971622508467042792L; diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/exception/AcmeUnauthorizedException.java b/acme4j-client/src/main/java/org/shredzone/acme4j/exception/AcmeUnauthorizedException.java index 9a4a3adc..11d8fec8 100644 --- a/acme4j-client/src/main/java/org/shredzone/acme4j/exception/AcmeUnauthorizedException.java +++ b/acme4j-client/src/main/java/org/shredzone/acme4j/exception/AcmeUnauthorizedException.java @@ -13,17 +13,12 @@ */ package org.shredzone.acme4j.exception; -import javax.annotation.ParametersAreNonnullByDefault; -import javax.annotation.concurrent.Immutable; - import org.shredzone.acme4j.Problem; /** * An exception that is thrown when the client is not authorized. The details will give * an explanation for the reasons (e.g. "client not on a whitelist"). */ -@ParametersAreNonnullByDefault -@Immutable public class AcmeUnauthorizedException extends AcmeServerException { private static final long serialVersionUID = 9064697508262919366L; diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/exception/AcmeUserActionRequiredException.java b/acme4j-client/src/main/java/org/shredzone/acme4j/exception/AcmeUserActionRequiredException.java index 4e412708..2235645a 100644 --- a/acme4j-client/src/main/java/org/shredzone/acme4j/exception/AcmeUserActionRequiredException.java +++ b/acme4j-client/src/main/java/org/shredzone/acme4j/exception/AcmeUserActionRequiredException.java @@ -17,11 +17,7 @@ import java.net.MalformedURLException; import java.net.URI; import java.net.URL; -import javax.annotation.CheckForNull; -import javax.annotation.Nullable; -import javax.annotation.ParametersAreNonnullByDefault; -import javax.annotation.concurrent.Immutable; - +import edu.umd.cs.findbugs.annotations.Nullable; import org.shredzone.acme4j.Problem; /** @@ -30,12 +26,10 @@ import org.shredzone.acme4j.Problem; * Usually this exception is thrown when the terms of service have changed, and the CA * requires an agreement to the new terms before proceeding. */ -@ParametersAreNonnullByDefault -@Immutable public class AcmeUserActionRequiredException extends AcmeServerException { private static final long serialVersionUID = 7719055447283858352L; - private final URI tosUri; + private final @Nullable URI tosUri; /** * Creates a new {@link AcmeUserActionRequiredException}. @@ -54,7 +48,7 @@ public class AcmeUserActionRequiredException extends AcmeServerException { * Returns the {@link URI} of the terms-of-service document to accept, or {@code null} * if the server did not provide a link to such a document. */ - @CheckForNull + @Nullable public URI getTermsOfServiceUri() { return tosUri; } diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/exception/package-info.java b/acme4j-client/src/main/java/org/shredzone/acme4j/exception/package-info.java new file mode 100644 index 00000000..24479702 --- /dev/null +++ b/acme4j-client/src/main/java/org/shredzone/acme4j/exception/package-info.java @@ -0,0 +1,23 @@ +/* + * acme4j - Java ACME client + * + * Copyright (C) 2020 Richard "Shred" Körber + * http://acme4j.shredzone.org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + */ + +@ReturnValuesAreNonnullByDefault +@DefaultAnnotationForParameters(NonNull.class) +@DefaultAnnotationForFields(NonNull.class) +package org.shredzone.acme4j.exception; + +import edu.umd.cs.findbugs.annotations.DefaultAnnotationForFields; +import edu.umd.cs.findbugs.annotations.DefaultAnnotationForParameters; +import edu.umd.cs.findbugs.annotations.NonNull; +import edu.umd.cs.findbugs.annotations.ReturnValuesAreNonnullByDefault; diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/package-info.java b/acme4j-client/src/main/java/org/shredzone/acme4j/package-info.java new file mode 100644 index 00000000..aac2d503 --- /dev/null +++ b/acme4j-client/src/main/java/org/shredzone/acme4j/package-info.java @@ -0,0 +1,23 @@ +/* + * acme4j - Java ACME client + * + * Copyright (C) 2020 Richard "Shred" Körber + * http://acme4j.shredzone.org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + */ + +@ReturnValuesAreNonnullByDefault +@DefaultAnnotationForParameters(NonNull.class) +@DefaultAnnotationForFields(NonNull.class) +package org.shredzone.acme4j; + +import edu.umd.cs.findbugs.annotations.DefaultAnnotationForFields; +import edu.umd.cs.findbugs.annotations.DefaultAnnotationForParameters; +import edu.umd.cs.findbugs.annotations.NonNull; +import edu.umd.cs.findbugs.annotations.ReturnValuesAreNonnullByDefault; diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/provider/AbstractAcmeProvider.java b/acme4j-client/src/main/java/org/shredzone/acme4j/provider/AbstractAcmeProvider.java index 6cf9b629..0ee2053c 100644 --- a/acme4j-client/src/main/java/org/shredzone/acme4j/provider/AbstractAcmeProvider.java +++ b/acme4j-client/src/main/java/org/shredzone/acme4j/provider/AbstractAcmeProvider.java @@ -22,8 +22,6 @@ import java.util.Map; import java.util.Objects; import java.util.function.BiFunction; -import javax.annotation.ParametersAreNonnullByDefault; - import org.shredzone.acme4j.Login; import org.shredzone.acme4j.Session; import org.shredzone.acme4j.challenge.Challenge; @@ -44,7 +42,6 @@ import org.shredzone.acme4j.toolbox.JSON; * Implementing classes must implement at least {@link AcmeProvider#accepts(URI)} * and {@link AbstractAcmeProvider#resolve(URI)}. */ -@ParametersAreNonnullByDefault public abstract class AbstractAcmeProvider implements AcmeProvider { private static final Map> CHALLENGES = challengeMap(); diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/provider/AcmeProvider.java b/acme4j-client/src/main/java/org/shredzone/acme4j/provider/AcmeProvider.java index a50b26b7..41cd93fe 100644 --- a/acme4j-client/src/main/java/org/shredzone/acme4j/provider/AcmeProvider.java +++ b/acme4j-client/src/main/java/org/shredzone/acme4j/provider/AcmeProvider.java @@ -17,9 +17,7 @@ import java.net.URI; import java.net.URL; import java.util.ServiceLoader; -import javax.annotation.CheckForNull; -import javax.annotation.ParametersAreNonnullByDefault; - +import edu.umd.cs.findbugs.annotations.Nullable; import org.shredzone.acme4j.Login; import org.shredzone.acme4j.Session; import org.shredzone.acme4j.challenge.Challenge; @@ -33,7 +31,6 @@ import org.shredzone.acme4j.toolbox.JSON; *

* Provider implementations must be registered with Java's {@link ServiceLoader}. */ -@ParametersAreNonnullByDefault public interface AcmeProvider { /** @@ -80,7 +77,7 @@ public interface AcmeProvider { * @return Directory data, as JSON object, or {@code null} if the directory has not * been changed since the last request. */ - @CheckForNull + @Nullable JSON directory(Session session, URI serverUri) throws AcmeException; /** @@ -93,7 +90,7 @@ public interface AcmeProvider { * @return {@link Challenge} instance, or {@code null} if this provider is unable to * generate a matching {@link Challenge} instance. */ - @CheckForNull + @Nullable Challenge createChallenge(Login login, JSON data); } diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/provider/GenericAcmeProvider.java b/acme4j-client/src/main/java/org/shredzone/acme4j/provider/GenericAcmeProvider.java index a74db3fb..39e4fb50 100644 --- a/acme4j-client/src/main/java/org/shredzone/acme4j/provider/GenericAcmeProvider.java +++ b/acme4j-client/src/main/java/org/shredzone/acme4j/provider/GenericAcmeProvider.java @@ -17,15 +17,12 @@ import java.net.MalformedURLException; import java.net.URI; import java.net.URL; -import javax.annotation.ParametersAreNonnullByDefault; - /** * A generic {@link AcmeProvider}. It should be working for all ACME servers complying to * the ACME specifications. *

* The {@code serverUri} is either a http or https URI to the server's directory service. */ -@ParametersAreNonnullByDefault public class GenericAcmeProvider extends AbstractAcmeProvider { @Override diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/provider/letsencrypt/LetsEncryptAcmeProvider.java b/acme4j-client/src/main/java/org/shredzone/acme4j/provider/letsencrypt/LetsEncryptAcmeProvider.java index 1df319c8..1359fd88 100644 --- a/acme4j-client/src/main/java/org/shredzone/acme4j/provider/letsencrypt/LetsEncryptAcmeProvider.java +++ b/acme4j-client/src/main/java/org/shredzone/acme4j/provider/letsencrypt/LetsEncryptAcmeProvider.java @@ -17,8 +17,6 @@ import java.net.MalformedURLException; import java.net.URI; import java.net.URL; -import javax.annotation.ParametersAreNonnullByDefault; - import org.shredzone.acme4j.exception.AcmeProtocolException; import org.shredzone.acme4j.provider.AbstractAcmeProvider; import org.shredzone.acme4j.provider.AcmeProvider; @@ -33,7 +31,6 @@ import org.shredzone.acme4j.provider.AcmeProvider; * * @see Let's Encrypt */ -@ParametersAreNonnullByDefault public class LetsEncryptAcmeProvider extends AbstractAcmeProvider { private static final String V02_DIRECTORY_URL = "https://acme-v02.api.letsencrypt.org/directory"; diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/provider/letsencrypt/package-info.java b/acme4j-client/src/main/java/org/shredzone/acme4j/provider/letsencrypt/package-info.java new file mode 100644 index 00000000..3c09a3fc --- /dev/null +++ b/acme4j-client/src/main/java/org/shredzone/acme4j/provider/letsencrypt/package-info.java @@ -0,0 +1,23 @@ +/* + * acme4j - Java ACME client + * + * Copyright (C) 2020 Richard "Shred" Körber + * http://acme4j.shredzone.org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + */ + +@ReturnValuesAreNonnullByDefault +@DefaultAnnotationForParameters(NonNull.class) +@DefaultAnnotationForFields(NonNull.class) +package org.shredzone.acme4j.provider.letsencrypt; + +import edu.umd.cs.findbugs.annotations.DefaultAnnotationForFields; +import edu.umd.cs.findbugs.annotations.DefaultAnnotationForParameters; +import edu.umd.cs.findbugs.annotations.NonNull; +import edu.umd.cs.findbugs.annotations.ReturnValuesAreNonnullByDefault; diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/provider/package-info.java b/acme4j-client/src/main/java/org/shredzone/acme4j/provider/package-info.java new file mode 100644 index 00000000..2e883e96 --- /dev/null +++ b/acme4j-client/src/main/java/org/shredzone/acme4j/provider/package-info.java @@ -0,0 +1,23 @@ +/* + * acme4j - Java ACME client + * + * Copyright (C) 2020 Richard "Shred" Körber + * http://acme4j.shredzone.org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + */ + +@ReturnValuesAreNonnullByDefault +@DefaultAnnotationForParameters(NonNull.class) +@DefaultAnnotationForFields(NonNull.class) +package org.shredzone.acme4j.provider; + +import edu.umd.cs.findbugs.annotations.DefaultAnnotationForFields; +import edu.umd.cs.findbugs.annotations.DefaultAnnotationForParameters; +import edu.umd.cs.findbugs.annotations.NonNull; +import edu.umd.cs.findbugs.annotations.ReturnValuesAreNonnullByDefault; diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/provider/pebble/PebbleAcmeProvider.java b/acme4j-client/src/main/java/org/shredzone/acme4j/provider/pebble/PebbleAcmeProvider.java index 1267dad0..0f884b22 100644 --- a/acme4j-client/src/main/java/org/shredzone/acme4j/provider/pebble/PebbleAcmeProvider.java +++ b/acme4j-client/src/main/java/org/shredzone/acme4j/provider/pebble/PebbleAcmeProvider.java @@ -19,8 +19,6 @@ import java.net.URL; import java.util.regex.Matcher; import java.util.regex.Pattern; -import javax.annotation.ParametersAreNonnullByDefault; - import org.shredzone.acme4j.connector.HttpConnector; import org.shredzone.acme4j.provider.AbstractAcmeProvider; import org.shredzone.acme4j.provider.AcmeProvider; @@ -36,7 +34,6 @@ import org.shredzone.acme4j.provider.AcmeProvider; * possible to connect to an external Pebble server on the given {@code other-host} and * port. The port is optional, and if omitted, the standard port is used. */ -@ParametersAreNonnullByDefault public class PebbleAcmeProvider extends AbstractAcmeProvider { private static final Pattern HOST_PATTERN = Pattern.compile("^/([^:/]+)(?:\\:(\\d+))?/?$"); diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/provider/pebble/PebbleHttpConnector.java b/acme4j-client/src/main/java/org/shredzone/acme4j/provider/pebble/PebbleHttpConnector.java index 10498090..2e269970 100644 --- a/acme4j-client/src/main/java/org/shredzone/acme4j/provider/pebble/PebbleHttpConnector.java +++ b/acme4j-client/src/main/java/org/shredzone/acme4j/provider/pebble/PebbleHttpConnector.java @@ -22,14 +22,14 @@ import java.security.KeyStore; import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; import java.security.cert.CertificateException; +import java.util.Objects; -import javax.annotation.ParametersAreNonnullByDefault; -import javax.annotation.concurrent.ThreadSafe; import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSocketFactory; import javax.net.ssl.TrustManagerFactory; +import edu.umd.cs.findbugs.annotations.Nullable; import org.shredzone.acme4j.connector.HttpConnector; import org.shredzone.acme4j.connector.NetworkSettings; @@ -37,10 +37,8 @@ import org.shredzone.acme4j.connector.NetworkSettings; * {@link HttpConnector} to be used for Pebble. Pebble uses a static, self signed SSL * certificate. */ -@ParametersAreNonnullByDefault -@ThreadSafe public class PebbleHttpConnector extends HttpConnector { - private static SSLSocketFactory sslSocketFactory; + private static @Nullable SSLSocketFactory sslSocketFactory = null; @Override public HttpURLConnection openConnection(URL url, NetworkSettings settings) throws IOException { @@ -75,7 +73,7 @@ public class PebbleHttpConnector extends HttpConnector { throw new IOException("Could not create truststore", ex); } } - return sslSocketFactory; + return Objects.requireNonNull(sslSocketFactory); } } diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/provider/pebble/package-info.java b/acme4j-client/src/main/java/org/shredzone/acme4j/provider/pebble/package-info.java new file mode 100644 index 00000000..28a876ed --- /dev/null +++ b/acme4j-client/src/main/java/org/shredzone/acme4j/provider/pebble/package-info.java @@ -0,0 +1,23 @@ +/* + * acme4j - Java ACME client + * + * Copyright (C) 2020 Richard "Shred" Körber + * http://acme4j.shredzone.org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + */ + +@ReturnValuesAreNonnullByDefault +@DefaultAnnotationForParameters(NonNull.class) +@DefaultAnnotationForFields(NonNull.class) +package org.shredzone.acme4j.provider.pebble; + +import edu.umd.cs.findbugs.annotations.DefaultAnnotationForFields; +import edu.umd.cs.findbugs.annotations.DefaultAnnotationForParameters; +import edu.umd.cs.findbugs.annotations.NonNull; +import edu.umd.cs.findbugs.annotations.ReturnValuesAreNonnullByDefault; diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/toolbox/AcmeUtils.java b/acme4j-client/src/main/java/org/shredzone/acme4j/toolbox/AcmeUtils.java index f765c01e..f705f5aa 100644 --- a/acme4j-client/src/main/java/org/shredzone/acme4j/toolbox/AcmeUtils.java +++ b/acme4j-client/src/main/java/org/shredzone/acme4j/toolbox/AcmeUtils.java @@ -29,12 +29,7 @@ import java.util.Objects; import java.util.regex.Matcher; import java.util.regex.Pattern; -import javax.annotation.CheckForNull; -import javax.annotation.Nullable; -import javax.annotation.ParametersAreNonnullByDefault; -import javax.annotation.WillNotClose; -import javax.annotation.concurrent.Immutable; - +import edu.umd.cs.findbugs.annotations.Nullable; import org.shredzone.acme4j.exception.AcmeProtocolException; /** @@ -43,7 +38,6 @@ import org.shredzone.acme4j.exception.AcmeProtocolException; * This class is internal. You may use it in your own code, but be warned that methods may * change their signature or disappear without prior announcement. */ -@ParametersAreNonnullByDefault public final class AcmeUtils { private static final char[] HEX = "0123456789abcdef".toCharArray(); private static final String ACME_ERROR_PREFIX = "urn:ietf:params:acme:error:"; @@ -72,8 +66,6 @@ public final class AcmeUtils { /** * Enumeration of PEM labels. */ - @ParametersAreNonnullByDefault - @Immutable public enum PemLabel { CERTIFICATE("CERTIFICATE"), CERTIFICATE_REQUEST("CERTIFICATE REQUEST"), @@ -239,7 +231,7 @@ public final class AcmeUtils { * Error type to strip the prefix from. {@code null} is safe. * @return Stripped error type, or {@code null} if the prefix was not found. */ - @CheckForNull + @Nullable public static String stripErrorPrefix(@Nullable String type) { if (type != null && type.startsWith(ACME_ERROR_PREFIX)) { return type.substring(ACME_ERROR_PREFIX.length()); @@ -258,7 +250,7 @@ public final class AcmeUtils { * @param out * {@link Writer} to write to. It will not be closed after use! */ - public static void writeToPem(byte[] encoded, PemLabel label, @WillNotClose Writer out) + public static void writeToPem(byte[] encoded, PemLabel label, Writer out) throws IOException { out.append("-----BEGIN ").append(label.toString()).append("-----\n"); out.append(new String(PEM_ENCODER.encode(encoded), StandardCharsets.US_ASCII)); @@ -274,7 +266,7 @@ public final class AcmeUtils { * @throws AcmeProtocolException * if the Content-Type header contains a different charset than "utf-8". */ - @CheckForNull + @Nullable public static String getContentType(@Nullable String header) { if (header != null) { Matcher m = CONTENT_TYPE_PATTERN.matcher(header); diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/toolbox/JSON.java b/acme4j-client/src/main/java/org/shredzone/acme4j/toolbox/JSON.java index 3dfe47d3..237e79a9 100644 --- a/acme4j-client/src/main/java/org/shredzone/acme4j/toolbox/JSON.java +++ b/acme4j-client/src/main/java/org/shredzone/acme4j/toolbox/JSON.java @@ -43,11 +43,7 @@ import java.util.function.Function; import java.util.stream.Stream; import java.util.stream.StreamSupport; -import javax.annotation.Nullable; -import javax.annotation.ParametersAreNonnullByDefault; -import javax.annotation.WillClose; -import javax.annotation.concurrent.Immutable; - +import edu.umd.cs.findbugs.annotations.Nullable; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import org.jose4j.json.JsonUtil; import org.jose4j.lang.JoseException; @@ -59,8 +55,6 @@ import org.shredzone.acme4j.exception.AcmeProtocolException; /** * A model containing a JSON result. The content is immutable. */ -@ParametersAreNonnullByDefault -@Immutable public final class JSON implements Serializable { private static final long serialVersionUID = 3091273044605709204L; @@ -101,7 +95,7 @@ public final class JSON implements Serializable { * {@link InputStream} to read from. Will be closed after use. * @return {@link JSON} of the read content. */ - public static JSON parse(@WillClose InputStream in) throws IOException { + public static JSON parse(InputStream in) throws IOException { try (BufferedReader reader = new BufferedReader(new InputStreamReader(in, "utf-8"))) { String json = reader.lines().map(String::trim).collect(joining()); return parse(json); @@ -205,8 +199,6 @@ public final class JSON implements Serializable { /** * Represents a JSON array. */ - @ParametersAreNonnullByDefault - @Immutable public static final class Array implements Iterable { private final String path; private final List data; @@ -275,11 +267,9 @@ public final class JSON implements Serializable { * All return values are never {@code null} unless specified otherwise. For optional * parameters, use {@link Value#optional()}. */ - @ParametersAreNonnullByDefault - @Immutable public static final class Value { private final String path; - private final Object val; + private final @Nullable Object val; /** * Creates a new {@link Value}. @@ -519,7 +509,6 @@ public final class JSON implements Serializable { /** * An {@link Iterator} over array {@link Value}. */ - @ParametersAreNonnullByDefault private static class ValueIterator implements Iterator { private final Array array; private int index = 0; diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/toolbox/JSONBuilder.java b/acme4j-client/src/main/java/org/shredzone/acme4j/toolbox/JSONBuilder.java index 52b1bb36..4a286eff 100644 --- a/acme4j-client/src/main/java/org/shredzone/acme4j/toolbox/JSONBuilder.java +++ b/acme4j-client/src/main/java/org/shredzone/acme4j/toolbox/JSONBuilder.java @@ -26,9 +26,7 @@ import java.util.LinkedHashMap; import java.util.Map; import java.util.Objects; -import javax.annotation.Nullable; -import javax.annotation.ParametersAreNonnullByDefault; - +import edu.umd.cs.findbugs.annotations.Nullable; import org.jose4j.json.JsonUtil; /** @@ -42,7 +40,6 @@ import org.jose4j.json.JsonUtil; * cb.array("array", 123, 456, 789); * */ -@ParametersAreNonnullByDefault public class JSONBuilder { private final Map data = new LinkedHashMap<>(); diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/toolbox/JoseUtils.java b/acme4j-client/src/main/java/org/shredzone/acme4j/toolbox/JoseUtils.java index 084c8d3d..9fbecb25 100644 --- a/acme4j-client/src/main/java/org/shredzone/acme4j/toolbox/JoseUtils.java +++ b/acme4j-client/src/main/java/org/shredzone/acme4j/toolbox/JoseUtils.java @@ -18,10 +18,9 @@ import java.security.KeyPair; import java.security.PublicKey; import java.util.Map; -import javax.annotation.Nullable; -import javax.annotation.ParametersAreNonnullByDefault; import javax.crypto.SecretKey; +import edu.umd.cs.findbugs.annotations.Nullable; import org.jose4j.jwk.EllipticCurveJsonWebKey; import org.jose4j.jwk.JsonWebKey; import org.jose4j.jwk.PublicJsonWebKey; @@ -37,7 +36,6 @@ import org.slf4j.LoggerFactory; * * @since 2.7 */ -@ParametersAreNonnullByDefault public final class JoseUtils { private static final Logger LOG = LoggerFactory.getLogger(JoseUtils.class); @@ -65,7 +63,7 @@ public final class JoseUtils { * @return JSON structure of the JOSE request, ready to be sent. */ public static JSONBuilder createJoseRequest(URL url, KeyPair keypair, - @Nullable JSONBuilder payload, @Nullable String nonce, @Nullable String kid) { + @Nullable JSONBuilder payload, @Nullable String nonce, @Nullable String kid) { try { PublicJsonWebKey jwk = PublicJsonWebKey.Factory.newPublicJwk(keypair.getPublic()); diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/toolbox/package-info.java b/acme4j-client/src/main/java/org/shredzone/acme4j/toolbox/package-info.java new file mode 100644 index 00000000..ecc4ebff --- /dev/null +++ b/acme4j-client/src/main/java/org/shredzone/acme4j/toolbox/package-info.java @@ -0,0 +1,23 @@ +/* + * acme4j - Java ACME client + * + * Copyright (C) 2020 Richard "Shred" Körber + * http://acme4j.shredzone.org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + */ + +@ReturnValuesAreNonnullByDefault +@DefaultAnnotationForParameters(NonNull.class) +@DefaultAnnotationForFields(NonNull.class) +package org.shredzone.acme4j.toolbox; + +import edu.umd.cs.findbugs.annotations.DefaultAnnotationForFields; +import edu.umd.cs.findbugs.annotations.DefaultAnnotationForParameters; +import edu.umd.cs.findbugs.annotations.NonNull; +import edu.umd.cs.findbugs.annotations.ReturnValuesAreNonnullByDefault; diff --git a/acme4j-client/src/test/java/org/shredzone/acme4j/provider/AbstractAcmeProviderTest.java b/acme4j-client/src/test/java/org/shredzone/acme4j/provider/AbstractAcmeProviderTest.java index 444143b2..da4dd57c 100644 --- a/acme4j-client/src/test/java/org/shredzone/acme4j/provider/AbstractAcmeProviderTest.java +++ b/acme4j-client/src/test/java/org/shredzone/acme4j/provider/AbstractAcmeProviderTest.java @@ -30,8 +30,6 @@ import java.time.temporal.ChronoUnit; import java.util.Optional; import java.util.concurrent.atomic.AtomicBoolean; -import javax.annotation.ParametersAreNonnullByDefault; - import org.junit.Test; import org.shredzone.acme4j.Login; import org.shredzone.acme4j.Session; @@ -310,7 +308,6 @@ public class AbstractAcmeProviderTest { } } - @ParametersAreNonnullByDefault private static class TestAbstractAcmeProvider extends AbstractAcmeProvider { private final Connection connection; diff --git a/acme4j-it/src/main/java/org/shredzone/acme4j/it/BammBammClient.java b/acme4j-it/src/main/java/org/shredzone/acme4j/it/BammBammClient.java index 5b81599e..751d68f4 100644 --- a/acme4j-it/src/main/java/org/shredzone/acme4j/it/BammBammClient.java +++ b/acme4j-it/src/main/java/org/shredzone/acme4j/it/BammBammClient.java @@ -17,8 +17,6 @@ import java.io.IOException; import java.util.Arrays; import java.util.Objects; -import javax.annotation.ParametersAreNonnullByDefault; - import org.apache.http.HttpResponse; import org.apache.http.HttpStatus; import org.apache.http.client.ClientProtocolException; @@ -33,7 +31,6 @@ import org.shredzone.acme4j.toolbox.JSONBuilder; /** * The BammBamm client connects to the pebble-challtestsrv. */ -@ParametersAreNonnullByDefault public class BammBammClient { private static final HttpClient CLIENT = HttpClients.createDefault(); diff --git a/acme4j-it/src/main/java/org/shredzone/acme4j/it/package-info.java b/acme4j-it/src/main/java/org/shredzone/acme4j/it/package-info.java new file mode 100644 index 00000000..a26624ea --- /dev/null +++ b/acme4j-it/src/main/java/org/shredzone/acme4j/it/package-info.java @@ -0,0 +1,23 @@ +/* + * acme4j - Java ACME client + * + * Copyright (C) 2020 Richard "Shred" Körber + * http://acme4j.shredzone.org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + */ + +@ReturnValuesAreNonnullByDefault +@DefaultAnnotationForParameters(NonNull.class) +@DefaultAnnotationForFields(NonNull.class) +package org.shredzone.acme4j.it; + +import edu.umd.cs.findbugs.annotations.DefaultAnnotationForFields; +import edu.umd.cs.findbugs.annotations.DefaultAnnotationForParameters; +import edu.umd.cs.findbugs.annotations.NonNull; +import edu.umd.cs.findbugs.annotations.ReturnValuesAreNonnullByDefault; diff --git a/acme4j-utils/src/main/java/org/shredzone/acme4j/util/CSRBuilder.java b/acme4j-utils/src/main/java/org/shredzone/acme4j/util/CSRBuilder.java index 00b5cfb9..d53bf0d7 100644 --- a/acme4j-utils/src/main/java/org/shredzone/acme4j/util/CSRBuilder.java +++ b/acme4j-utils/src/main/java/org/shredzone/acme4j/util/CSRBuilder.java @@ -31,9 +31,7 @@ import java.util.Collection; import java.util.List; import java.util.Objects; -import javax.annotation.ParametersAreNonnullByDefault; -import javax.annotation.WillClose; - +import edu.umd.cs.findbugs.annotations.Nullable; import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; import org.bouncycastle.asn1.x500.X500Name; import org.bouncycastle.asn1.x500.X500NameBuilder; @@ -57,7 +55,6 @@ import org.shredzone.acme4j.Identifier; *

* Requires {@code Bouncy Castle}. This class is part of the {@code acme4j-utils} module. */ -@ParametersAreNonnullByDefault public class CSRBuilder { private static final String SIGNATURE_ALG = "SHA256withRSA"; private static final String EC_SIGNATURE_ALG = "SHA256withECDSA"; @@ -65,7 +62,7 @@ public class CSRBuilder { private final X500NameBuilder namebuilder = new X500NameBuilder(X500Name.getDefaultStyle()); private final List namelist = new ArrayList<>(); private final List iplist = new ArrayList<>(); - private PKCS10CertificationRequest csr = null; + private @Nullable PKCS10CertificationRequest csr = null; /** * Adds a domain name to the CSR. The first domain name added will also be the @@ -296,7 +293,7 @@ public class CSRBuilder { * {@link Writer} to write the PEM file to. The {@link Writer} is closed * after use. */ - public void write(@WillClose Writer w) throws IOException { + public void write(Writer w) throws IOException { if (csr == null) { throw new IllegalStateException("sign CSR first"); } @@ -313,7 +310,7 @@ public class CSRBuilder { * {@link OutputStream} to write the PEM file to. The {@link OutputStream} * is closed after use. */ - public void write(@WillClose OutputStream out) throws IOException { + public void write(OutputStream out) throws IOException { write(new OutputStreamWriter(out, "utf-8")); } diff --git a/acme4j-utils/src/main/java/org/shredzone/acme4j/util/CertificateUtils.java b/acme4j-utils/src/main/java/org/shredzone/acme4j/util/CertificateUtils.java index 19a0da4e..e18624c6 100644 --- a/acme4j-utils/src/main/java/org/shredzone/acme4j/util/CertificateUtils.java +++ b/acme4j-utils/src/main/java/org/shredzone/acme4j/util/CertificateUtils.java @@ -33,9 +33,6 @@ import java.util.Date; import java.util.Objects; import java.util.function.Function; -import javax.annotation.ParametersAreNonnullByDefault; -import javax.annotation.WillClose; - import org.bouncycastle.asn1.ASN1Encodable; import org.bouncycastle.asn1.ASN1ObjectIdentifier; import org.bouncycastle.asn1.DEROctetString; @@ -64,7 +61,6 @@ import org.shredzone.acme4j.challenge.TlsAlpn01Challenge; *

* Requires {@code Bouncy Castle}. This class is part of the {@code acme4j-utils} module. */ -@ParametersAreNonnullByDefault public final class CertificateUtils { /** @@ -87,7 +83,7 @@ public final class CertificateUtils { * closed after use. * @return CSR that was read */ - public static PKCS10CertificationRequest readCSR(@WillClose InputStream in) throws IOException { + public static PKCS10CertificationRequest readCSR(InputStream in) throws IOException { try (PEMParser pemParser = new PEMParser(new InputStreamReader(in, StandardCharsets.US_ASCII))) { Object parsedObj = pemParser.readObject(); if (!(parsedObj instanceof PKCS10CertificationRequest)) { diff --git a/acme4j-utils/src/main/java/org/shredzone/acme4j/util/KeyPairUtils.java b/acme4j-utils/src/main/java/org/shredzone/acme4j/util/KeyPairUtils.java index 280fb57c..4955958f 100644 --- a/acme4j-utils/src/main/java/org/shredzone/acme4j/util/KeyPairUtils.java +++ b/acme4j-utils/src/main/java/org/shredzone/acme4j/util/KeyPairUtils.java @@ -23,9 +23,6 @@ import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; import java.security.SecureRandom; -import javax.annotation.ParametersAreNonnullByDefault; -import javax.annotation.WillClose; - import org.bouncycastle.jce.ECNamedCurveTable; import org.bouncycastle.jce.spec.ECParameterSpec; import org.bouncycastle.openssl.PEMException; @@ -39,7 +36,6 @@ import org.bouncycastle.openssl.jcajce.JcaPEMWriter; *

* Requires {@code Bouncy Castle}. This class is part of the {@code acme4j-utils} module. */ -@ParametersAreNonnullByDefault public class KeyPairUtils { private KeyPairUtils() { @@ -104,7 +100,7 @@ public class KeyPairUtils { * after use. * @return {@link KeyPair} read */ - public static KeyPair readKeyPair(@WillClose Reader r) throws IOException { + public static KeyPair readKeyPair(Reader r) throws IOException { try (PEMParser parser = new PEMParser(r)) { PEMKeyPair keyPair = (PEMKeyPair) parser.readObject(); return new JcaPEMKeyConverter().getKeyPair(keyPair); @@ -122,7 +118,7 @@ public class KeyPairUtils { * {@link Writer} to write the PEM file to. The {@link Writer} is closed * after use. */ - public static void writeKeyPair(KeyPair keypair, @WillClose Writer w) throws IOException { + public static void writeKeyPair(KeyPair keypair, Writer w) throws IOException { try (JcaPEMWriter jw = new JcaPEMWriter(w)) { jw.writeObject(keypair); } diff --git a/acme4j-utils/src/main/java/org/shredzone/acme4j/util/package-info.java b/acme4j-utils/src/main/java/org/shredzone/acme4j/util/package-info.java new file mode 100644 index 00000000..3b742876 --- /dev/null +++ b/acme4j-utils/src/main/java/org/shredzone/acme4j/util/package-info.java @@ -0,0 +1,23 @@ +/* + * acme4j - Java ACME client + * + * Copyright (C) 2020 Richard "Shred" Körber + * http://acme4j.shredzone.org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + */ + +@ReturnValuesAreNonnullByDefault +@DefaultAnnotationForParameters(NonNull.class) +@DefaultAnnotationForFields(NonNull.class) +package org.shredzone.acme4j.util; + +import edu.umd.cs.findbugs.annotations.DefaultAnnotationForFields; +import edu.umd.cs.findbugs.annotations.DefaultAnnotationForParameters; +import edu.umd.cs.findbugs.annotations.NonNull; +import edu.umd.cs.findbugs.annotations.ReturnValuesAreNonnullByDefault; diff --git a/pom.xml b/pom.xml index 3b5df440..bf1488b2 100644 --- a/pom.xml +++ b/pom.xml @@ -80,7 +80,7 @@ com.github.spotbugs spotbugs-maven-plugin - 3.1.12.2 + 4.0.0 src/config/spotbugs-exclude.xml @@ -171,16 +171,16 @@ - com.google.code.findbugs - jsr305 - 3.0.2 - provided - - - com.google.code.findbugs - annotations - 3.0.1 - provided + com.github.spotbugs + spotbugs-annotations + 4.0.3 + true + + + com.google.code.findbugs + jsr305 + + junit diff --git a/src/doc/docs/migration.md b/src/doc/docs/migration.md index 70e00a9d..538d7512 100644 --- a/src/doc/docs/migration.md +++ b/src/doc/docs/migration.md @@ -4,7 +4,10 @@ This document will help you migrate your code to the latest _acme4j_ version. ## Migration to Version 2.10 +- In a preparation for Java 9 modules, the JSR305 null-safe annotations have been replaced by SpotBugs annotations. This _should_ have no impact on your code, as the method signatures themselves are unchanged. However, the compiler could now complain about some `null` dereferences that have been undetected before. Reason is that JSR305 uses the `javax.annotations` package, which leads to split packages in a Java 9 modular environment. + - When fetching the directory, acme4j now evaluates HTTP caching headers instead of just caching the directory for 1 hour. However, Let's Encrypt explicitly forbids caching, which means that a fresh copy of the directory is now fetched from the server every time it is needed. I don't like it, but it is the RFC conformous behavior. It needs to be [fixed on Let's Encrypt side](https://github.com/letsencrypt/boulder/issues/4814). + - `AcmeProvider.directory(Session, URI)` is now responsible for maintaining the cache. Implementations can use `Session.setDirectoryExpires()`, `Session.setDirectoryLastModified()`, and the respective getters, for keeping track of the local directory state. `AcmeProvider.directory(Session, URI)` may now return `null`, to indicate that the remote directory was unchanged and the local copy is still valid. It's not permitted to return `null` if `Session.hasDirectory()` returns `false`, though! If your `AcmeProvider` is derived from `AbstractAcmeProvider`, and you haven't overridden the `directory()` method, no migration is necessary. ## Migration to Version 2.9