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.
pull/91/head
Richard Körber 2020-06-02 12:42:49 +02:00
parent c5e85f0101
commit b32f03b23a
No known key found for this signature in database
GPG Key ID: AAB9FD19C78AA3E0
63 changed files with 350 additions and 318 deletions

View File

@ -26,9 +26,7 @@ import java.util.List;
import java.util.Objects; import java.util.Objects;
import java.util.Optional; import java.util.Optional;
import javax.annotation.CheckForNull; import edu.umd.cs.findbugs.annotations.Nullable;
import javax.annotation.ParametersAreNonnullByDefault;
import org.shredzone.acme4j.connector.Connection; import org.shredzone.acme4j.connector.Connection;
import org.shredzone.acme4j.connector.Resource; import org.shredzone.acme4j.connector.Resource;
import org.shredzone.acme4j.connector.ResourceIterator; import org.shredzone.acme4j.connector.ResourceIterator;
@ -46,7 +44,6 @@ import org.slf4j.LoggerFactory;
/** /**
* Represents an account at the ACME server. * Represents an account at the ACME server.
*/ */
@ParametersAreNonnullByDefault
public class Account extends AcmeJsonResource { public class Account extends AcmeJsonResource {
private static final long serialVersionUID = 7042863483428051319L; private static final long serialVersionUID = 7042863483428051319L;
private static final Logger LOG = LoggerFactory.getLogger(Account.class); 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 * @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. * {@code null} if the server did not provide such an information.
*/ */
@CheckForNull @Nullable
public Boolean getTermsOfServiceAgreed() { public Boolean getTermsOfServiceAgreed() {
return getJSON().get(KEY_TOS_AGREED).map(Value::asBoolean).orElse(null); return getJSON().get(KEY_TOS_AGREED).map(Value::asBoolean).orElse(null);
} }
@ -108,7 +105,7 @@ public class Account extends AcmeJsonResource {
* *
* @since 2.8 * @since 2.8
*/ */
@CheckForNull @Nullable
public String getKeyIdentifier() { public String getKeyIdentifier() {
return getJSON().get(KEY_EXTERNAL_ACCOUNT_BINDING) return getJSON().get(KEY_EXTERNAL_ACCOUNT_BINDING)
.optional().map(Value::asObject) .optional().map(Value::asObject)
@ -277,7 +274,6 @@ public class Account extends AcmeJsonResource {
/** /**
* Editable {@link Account}. * Editable {@link Account}.
*/ */
@ParametersAreNonnullByDefault
public class EditableAccount { public class EditableAccount {
private final List<URI> editContacts = new ArrayList<>(); private final List<URI> editContacts = new ArrayList<>();

View File

@ -21,10 +21,10 @@ import java.security.KeyPair;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import javax.annotation.ParametersAreNonnullByDefault;
import javax.crypto.SecretKey; import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec; import javax.crypto.spec.SecretKeySpec;
import edu.umd.cs.findbugs.annotations.Nullable;
import org.shredzone.acme4j.connector.Connection; import org.shredzone.acme4j.connector.Connection;
import org.shredzone.acme4j.connector.Resource; import org.shredzone.acme4j.connector.Resource;
import org.shredzone.acme4j.exception.AcmeException; import org.shredzone.acme4j.exception.AcmeException;
@ -38,16 +38,15 @@ import org.slf4j.LoggerFactory;
/** /**
* A builder for registering a new account. * A builder for registering a new account.
*/ */
@ParametersAreNonnullByDefault
public class AccountBuilder { public class AccountBuilder {
private static final Logger LOG = LoggerFactory.getLogger(AccountBuilder.class); private static final Logger LOG = LoggerFactory.getLogger(AccountBuilder.class);
private List<URI> contacts = new ArrayList<>(); private final List<URI> contacts = new ArrayList<>();
private Boolean termsOfServiceAgreed; private @Nullable Boolean termsOfServiceAgreed;
private Boolean onlyExisting; private @Nullable Boolean onlyExisting;
private String keyIdentifier; private @Nullable String keyIdentifier;
private KeyPair keyPair; private @Nullable KeyPair keyPair;
private SecretKey macKey; private @Nullable SecretKey macKey;
/** /**
* Add a contact URI to the list of contacts. * Add a contact URI to the list of contacts.

View File

@ -16,8 +16,7 @@ package org.shredzone.acme4j;
import java.net.URL; import java.net.URL;
import java.util.Objects; 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.connector.Connection;
import org.shredzone.acme4j.exception.AcmeException; import org.shredzone.acme4j.exception.AcmeException;
import org.shredzone.acme4j.exception.AcmeLazyLoadingException; 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. * An ACME resource that stores its state in a JSON structure.
*/ */
@ParametersAreNonnullByDefault
public abstract class AcmeJsonResource extends AcmeResource { public abstract class AcmeJsonResource extends AcmeResource {
private static final long serialVersionUID = -5060364275766082345L; private static final long serialVersionUID = -5060364275766082345L;
private static final Logger LOG = LoggerFactory.getLogger(AcmeJsonResource.class); private static final Logger LOG = LoggerFactory.getLogger(AcmeJsonResource.class);
private JSON data = null; private @Nullable JSON data = null;
/** /**
* Create a new {@link AcmeJsonResource}. * Create a new {@link AcmeJsonResource}.

View File

@ -17,16 +17,15 @@ import java.io.Serializable;
import java.net.URL; import java.net.URL;
import java.util.Objects; import java.util.Objects;
import javax.annotation.ParametersAreNonnullByDefault; import edu.umd.cs.findbugs.annotations.Nullable;
/** /**
* A generic ACME resource. * A generic ACME resource.
*/ */
@ParametersAreNonnullByDefault
public abstract class AcmeResource implements Serializable { public abstract class AcmeResource implements Serializable {
private static final long serialVersionUID = -7930580802257379731L; private static final long serialVersionUID = -7930580802257379731L;
private transient Login login; private transient @Nullable Login login;
private final URL location; private final URL location;
/** /**

View File

@ -20,9 +20,7 @@ import java.time.Instant;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import javax.annotation.CheckForNull; import edu.umd.cs.findbugs.annotations.Nullable;
import javax.annotation.ParametersAreNonnullByDefault;
import org.shredzone.acme4j.challenge.Challenge; import org.shredzone.acme4j.challenge.Challenge;
import org.shredzone.acme4j.connector.Connection; import org.shredzone.acme4j.connector.Connection;
import org.shredzone.acme4j.exception.AcmeException; import org.shredzone.acme4j.exception.AcmeException;
@ -36,7 +34,6 @@ import org.slf4j.LoggerFactory;
/** /**
* Represents an authorization request at the ACME server. * Represents an authorization request at the ACME server.
*/ */
@ParametersAreNonnullByDefault
public class Authorization extends AcmeJsonResource { public class Authorization extends AcmeJsonResource {
private static final long serialVersionUID = -3116928998379417741L; private static final long serialVersionUID = -3116928998379417741L;
private static final Logger LOG = LoggerFactory.getLogger(Authorization.class); 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. * Gets the expiry date of the authorization, if set by the server.
*/ */
@CheckForNull @Nullable
public Instant getExpires() { public Instant getExpires() {
return getJSON().get("expires") return getJSON().get("expires")
.map(Value::asString) .map(Value::asString)
@ -118,7 +115,7 @@ public class Authorization extends AcmeJsonResource {
* @throws ClassCastException * @throws ClassCastException
* if the type does not match the expected Challenge class type * if the type does not match the expected Challenge class type
*/ */
@CheckForNull @Nullable
public <T extends Challenge> T findChallenge(final String type) { public <T extends Challenge> T findChallenge(final String type) {
return (T) getChallenges().stream() return (T) getChallenges().stream()
.filter(ch -> type.equals(ch.getType())) .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. * challenge, or if the challenge alone is not sufficient for authorization.
* @since 2.8 * @since 2.8
*/ */
@CheckForNull @Nullable
public <T extends Challenge> T findChallenge(Class<T> type) { public <T extends Challenge> T findChallenge(Class<T> type) {
return getChallenges().stream() return getChallenges().stream()
.filter(type::isInstance) .filter(type::isInstance)

View File

@ -25,10 +25,7 @@ import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import javax.annotation.Nullable; import edu.umd.cs.findbugs.annotations.Nullable;
import javax.annotation.ParametersAreNonnullByDefault;
import javax.annotation.WillNotClose;
import org.shredzone.acme4j.connector.Connection; import org.shredzone.acme4j.connector.Connection;
import org.shredzone.acme4j.connector.Resource; import org.shredzone.acme4j.connector.Resource;
import org.shredzone.acme4j.exception.AcmeException; 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 * Note that a certificate is immutable once it is issued. For renewal, a new certificate
* must be ordered. * must be ordered.
*/ */
@ParametersAreNonnullByDefault
public class Certificate extends AcmeResource { public class Certificate extends AcmeResource {
private static final long serialVersionUID = 7381527770159084201L; private static final long serialVersionUID = 7381527770159084201L;
private static final Logger LOG = LoggerFactory.getLogger(Certificate.class); private static final Logger LOG = LoggerFactory.getLogger(Certificate.class);
private ArrayList<X509Certificate> certChain; private @Nullable ArrayList<X509Certificate> certChain;
private ArrayList<URL> alternates; private @Nullable ArrayList<URL> alternates;
protected Certificate(Login login, URL certUrl) { protected Certificate(Login login, URL certUrl) {
super(login, certUrl); super(login, certUrl);
@ -121,7 +117,7 @@ public class Certificate extends AcmeResource {
* @param out * @param out
* {@link Writer} to write to. The writer is not closed after use. * {@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 { try {
for (X509Certificate cert : getCertificateChain()) { for (X509Certificate cert : getCertificateChain()) {
AcmeUtils.writeToPem(cert.getEncoded(), AcmeUtils.PemLabel.CERTIFICATE, out); AcmeUtils.writeToPem(cert.getEncoded(), AcmeUtils.PemLabel.CERTIFICATE, out);

View File

@ -21,9 +21,6 @@ import java.net.InetAddress;
import java.net.UnknownHostException; import java.net.UnknownHostException;
import java.util.Map; import java.util.Map;
import javax.annotation.ParametersAreNonnullByDefault;
import javax.annotation.concurrent.Immutable;
import org.shredzone.acme4j.exception.AcmeProtocolException; import org.shredzone.acme4j.exception.AcmeProtocolException;
import org.shredzone.acme4j.toolbox.JSON; import org.shredzone.acme4j.toolbox.JSON;
import org.shredzone.acme4j.toolbox.JSONBuilder; import org.shredzone.acme4j.toolbox.JSONBuilder;
@ -38,8 +35,6 @@ import org.shredzone.acme4j.toolbox.JSONBuilder;
* *
* @since 2.3 * @since 2.3
*/ */
@ParametersAreNonnullByDefault
@Immutable
public class Identifier implements Serializable { public class Identifier implements Serializable {
private static final long serialVersionUID = -7777851842076362412L; private static final long serialVersionUID = -7777851842076362412L;

View File

@ -19,9 +19,6 @@ import java.net.URL;
import java.security.KeyPair; import java.security.KeyPair;
import java.util.Objects; import java.util.Objects;
import javax.annotation.ParametersAreNonnullByDefault;
import javax.annotation.concurrent.ThreadSafe;
import org.shredzone.acme4j.challenge.Challenge; import org.shredzone.acme4j.challenge.Challenge;
import org.shredzone.acme4j.connector.Connection; import org.shredzone.acme4j.connector.Connection;
import org.shredzone.acme4j.exception.AcmeException; 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 * Note that {@link Login} objects are not serializable, as they contain a keypair and
* volatile data. * volatile data.
*/ */
@ParametersAreNonnullByDefault
@ThreadSafe
public class Login { public class Login {
private final Session session; private final Session session;

View File

@ -21,18 +21,13 @@ import java.time.Duration;
import java.util.Collection; import java.util.Collection;
import java.util.Optional; import java.util.Optional;
import javax.annotation.CheckForNull; import edu.umd.cs.findbugs.annotations.Nullable;
import javax.annotation.ParametersAreNonnullByDefault;
import javax.annotation.concurrent.Immutable;
import org.shredzone.acme4j.toolbox.JSON; import org.shredzone.acme4j.toolbox.JSON;
import org.shredzone.acme4j.toolbox.JSON.Value; import org.shredzone.acme4j.toolbox.JSON.Value;
/** /**
* Contains metadata related to the provider. * Contains metadata related to the provider.
*/ */
@ParametersAreNonnullByDefault
@Immutable
public class Metadata { public class Metadata {
private final JSON meta; 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 * Returns an {@link URI} to the current terms of service, or {@code null} if not
* available. * available.
*/ */
@CheckForNull @Nullable
public URI getTermsOfService() { public URI getTermsOfService() {
return meta.get("termsOfService").map(Value::asURI).orElse(null); 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 * Returns an {@link URL} to a website providing more information about the ACME
* server. {@code null} if not available. * server. {@code null} if not available.
*/ */
@CheckForNull @Nullable
public URL getWebsite() { public URL getWebsite() {
return meta.get("website").map(Value::asURL).orElse(null); return meta.get("website").map(Value::asURL).orElse(null);
} }
@ -100,6 +95,7 @@ public class Metadata {
* *
* @since 2.3 * @since 2.3
*/ */
@Nullable
public Duration getAutoRenewalMinLifetime() { public Duration getAutoRenewalMinLifetime() {
Optional<JSON> ar = meta.get("auto-renewal").optional().map(Value::asObject); Optional<JSON> ar = meta.get("auto-renewal").optional().map(Value::asObject);
if (!ar.isPresent()) { if (!ar.isPresent()) {
@ -114,6 +110,7 @@ public class Metadata {
* *
* @since 2.3 * @since 2.3
*/ */
@Nullable
public Duration getAutoRenewalMaxDuration() { public Duration getAutoRenewalMaxDuration() {
Optional<JSON> ar = meta.get("auto-renewal").optional().map(Value::asObject); Optional<JSON> ar = meta.get("auto-renewal").optional().map(Value::asObject);
if (!ar.isPresent()) { if (!ar.isPresent()) {

View File

@ -21,9 +21,7 @@ import java.time.Instant;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import javax.annotation.CheckForNull; import edu.umd.cs.findbugs.annotations.Nullable;
import javax.annotation.ParametersAreNonnullByDefault;
import org.shredzone.acme4j.connector.Connection; import org.shredzone.acme4j.connector.Connection;
import org.shredzone.acme4j.exception.AcmeException; import org.shredzone.acme4j.exception.AcmeException;
import org.shredzone.acme4j.toolbox.JSON; import org.shredzone.acme4j.toolbox.JSON;
@ -35,7 +33,6 @@ import org.slf4j.LoggerFactory;
/** /**
* Represents a certificate order. * Represents a certificate order.
*/ */
@ParametersAreNonnullByDefault
public class Order extends AcmeJsonResource { public class Order extends AcmeJsonResource {
private static final long serialVersionUID = 5435808648658292177L; private static final long serialVersionUID = 5435808648658292177L;
private static final Logger LOG = LoggerFactory.getLogger(Order.class); 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. * Returns a {@link Problem} document if the order failed.
*/ */
@CheckForNull @Nullable
public Problem getError() { public Problem getError() {
return getJSON().get("error").map(v -> v.asProblem(getLocation())).orElse(null); 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. * Gets the expiry date of the authorization, if set by the server.
*/ */
@CheckForNull @Nullable
public Instant getExpires() { public Instant getExpires() {
return getJSON().get("expires").map(Value::asInstant).orElse(null); 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}. * Gets the "not before" date that was used for the order, or {@code null}.
*/ */
@CheckForNull @Nullable
public Instant getNotBefore() { public Instant getNotBefore() {
return getJSON().get("notBefore").map(Value::asInstant).orElse(null); 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}. * Gets the "not after" date that was used for the order, or {@code null}.
*/ */
@CheckForNull @Nullable
public Instant getNotAfter() { public Instant getNotAfter() {
return getJSON().get("notAfter").map(Value::asInstant).orElse(null); 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. * Gets the {@link Certificate} if it is available. {@code null} otherwise.
*/ */
@CheckForNull @Nullable
public Certificate getCertificate() { public Certificate getCertificate() {
return getJSON().get("certificate") return getJSON().get("certificate")
.map(Value::asURL) .map(Value::asURL)
@ -138,7 +135,7 @@ public class Order extends AcmeJsonResource {
* *
* @since 2.6 * @since 2.6
*/ */
@CheckForNull @Nullable
public Certificate getAutoRenewalCertificate() { public Certificate getAutoRenewalCertificate() {
return getJSON().get("star-certificate") return getJSON().get("star-certificate")
.map(Value::asURL) .map(Value::asURL)
@ -188,7 +185,7 @@ public class Order extends AcmeJsonResource {
* *
* @since 2.3 * @since 2.3
*/ */
@CheckForNull @Nullable
public Instant getAutoRenewalStartDate() { public Instant getAutoRenewalStartDate() {
return getJSON().get("auto-renewal") return getJSON().get("auto-renewal")
.optional() .optional()
@ -206,7 +203,7 @@ public class Order extends AcmeJsonResource {
* *
* @since 2.3 * @since 2.3
*/ */
@CheckForNull @Nullable
public Instant getAutoRenewalEndDate() { public Instant getAutoRenewalEndDate() {
return getJSON().get("auto-renewal") return getJSON().get("auto-renewal")
.optional() .optional()
@ -223,7 +220,7 @@ public class Order extends AcmeJsonResource {
* *
* @since 2.3 * @since 2.3
*/ */
@CheckForNull @Nullable
public Duration getAutoRenewalLifetime() { public Duration getAutoRenewalLifetime() {
return getJSON().get("auto-renewal") return getJSON().get("auto-renewal")
.optional() .optional()
@ -240,7 +237,7 @@ public class Order extends AcmeJsonResource {
* *
* @since 2.7 * @since 2.7
*/ */
@CheckForNull @Nullable
public Duration getAutoRenewalLifetimeAdjust() { public Duration getAutoRenewalLifetimeAdjust() {
return getJSON().get("auto-renewal") return getJSON().get("auto-renewal")
.optional() .optional()

View File

@ -23,8 +23,7 @@ import java.util.Collection;
import java.util.LinkedHashSet; import java.util.LinkedHashSet;
import java.util.Set; 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.Connection;
import org.shredzone.acme4j.connector.Resource; import org.shredzone.acme4j.connector.Resource;
import org.shredzone.acme4j.exception.AcmeException; import org.shredzone.acme4j.exception.AcmeException;
@ -36,20 +35,19 @@ import org.slf4j.LoggerFactory;
/** /**
* A builder for a new {@link Order} object. * A builder for a new {@link Order} object.
*/ */
@ParametersAreNonnullByDefault
public class OrderBuilder { public class OrderBuilder {
private static final Logger LOG = LoggerFactory.getLogger(OrderBuilder.class); private static final Logger LOG = LoggerFactory.getLogger(OrderBuilder.class);
private final Login login; private final Login login;
private final Set<Identifier> identifierSet = new LinkedHashSet<>(); private final Set<Identifier> identifierSet = new LinkedHashSet<>();
private Instant notBefore; private @Nullable Instant notBefore;
private Instant notAfter; private @Nullable Instant notAfter;
private boolean autoRenewal; private boolean autoRenewal;
private Instant autoRenewalStart; private @Nullable Instant autoRenewalStart;
private Instant autoRenewalEnd; private @Nullable Instant autoRenewalEnd;
private Duration autoRenewalLifetime; private @Nullable Duration autoRenewalLifetime;
private Duration autoRenewalLifetimeAdjust; private @Nullable Duration autoRenewalLifetimeAdjust;
private boolean autoRenewalGet; private boolean autoRenewalGet;
/** /**

View File

@ -22,10 +22,7 @@ import java.net.URISyntaxException;
import java.net.URL; import java.net.URL;
import java.util.List; import java.util.List;
import javax.annotation.CheckForNull; import edu.umd.cs.findbugs.annotations.Nullable;
import javax.annotation.ParametersAreNonnullByDefault;
import javax.annotation.concurrent.Immutable;
import org.shredzone.acme4j.exception.AcmeProtocolException; import org.shredzone.acme4j.exception.AcmeProtocolException;
import org.shredzone.acme4j.toolbox.JSON; import org.shredzone.acme4j.toolbox.JSON;
import org.shredzone.acme4j.toolbox.JSON.Value; import org.shredzone.acme4j.toolbox.JSON.Value;
@ -35,8 +32,6 @@ import org.shredzone.acme4j.toolbox.JSON.Value;
* *
* @see <a href="https://tools.ietf.org/html/rfc7807">RFC 7807</a> * @see <a href="https://tools.ietf.org/html/rfc7807">RFC 7807</a>
*/ */
@ParametersAreNonnullByDefault
@Immutable
public class Problem implements Serializable { public class Problem implements Serializable {
private static final long serialVersionUID = -8418248862966754214L; private static final long serialVersionUID = -8418248862966754214L;
@ -78,7 +73,7 @@ public class Problem implements Serializable {
* *
* @see #toString() * @see #toString()
*/ */
@CheckForNull @Nullable
public String getTitle() { public String getTitle() {
return problemJson.get("title").map(Value::asString).orElse(null); return problemJson.get("title").map(Value::asString).orElse(null);
} }
@ -89,7 +84,7 @@ public class Problem implements Serializable {
* *
* @see #toString() * @see #toString()
*/ */
@CheckForNull @Nullable
public String getDetail() { public String getDetail() {
return problemJson.get("detail").map(Value::asString).orElse(null); 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 * Returns an URI that identifies the specific occurence of the problem. It is always
* an absolute URI. * an absolute URI.
*/ */
@CheckForNull @Nullable
public URI getInstance() { public URI getInstance() {
return problemJson.get("instance") return problemJson.get("instance")
.map(Value::asString) .map(Value::asString)
@ -117,7 +112,7 @@ public class Problem implements Serializable {
* *
* @since 2.3 * @since 2.3
*/ */
@CheckForNull @Nullable
public Identifier getIdentifier() { public Identifier getIdentifier() {
return problemJson.get("identifier") return problemJson.get("identifier")
.optional() .optional()

View File

@ -15,9 +15,7 @@ package org.shredzone.acme4j;
import java.util.Arrays; import java.util.Arrays;
import javax.annotation.CheckForNull; import edu.umd.cs.findbugs.annotations.Nullable;
import javax.annotation.ParametersAreNonnullByDefault;
import javax.annotation.concurrent.Immutable;
/** /**
* Enumeration of revocation reasons. * Enumeration of revocation reasons.
@ -25,8 +23,6 @@ import javax.annotation.concurrent.Immutable;
* @see <a href="https://tools.ietf.org/html/rfc5280#section-5.3.1">RFC 5280 Section * @see <a href="https://tools.ietf.org/html/rfc5280#section-5.3.1">RFC 5280 Section
* 5.3.1</a> * 5.3.1</a>
*/ */
@ParametersAreNonnullByDefault
@Immutable
public enum RevocationReason { public enum RevocationReason {
UNSPECIFIED(0), UNSPECIFIED(0),
@ -60,7 +56,7 @@ public enum RevocationReason {
* Reason code as defined in RFC 5280 * Reason code as defined in RFC 5280
* @return Matching {@link RevocationReason}, or {@code null} if not known * @return Matching {@link RevocationReason}, or {@code null} if not known
*/ */
@CheckForNull @Nullable
public static RevocationReason code(int reasonCode) { public static RevocationReason code(int reasonCode) {
return Arrays.stream(values()) return Arrays.stream(values())
.filter(rr -> rr.reasonCode == reasonCode) .filter(rr -> rr.reasonCode == reasonCode)

View File

@ -26,11 +26,7 @@ import java.util.ServiceLoader;
import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.StreamSupport; import java.util.stream.StreamSupport;
import javax.annotation.CheckForNull; import edu.umd.cs.findbugs.annotations.Nullable;
import javax.annotation.Nullable;
import javax.annotation.ParametersAreNonnullByDefault;
import javax.annotation.concurrent.ThreadSafe;
import org.shredzone.acme4j.connector.Connection; import org.shredzone.acme4j.connector.Connection;
import org.shredzone.acme4j.connector.NetworkSettings; import org.shredzone.acme4j.connector.NetworkSettings;
import org.shredzone.acme4j.connector.Resource; 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. * A session stores the ACME server URI. It also tracks communication parameters.
*/ */
@ParametersAreNonnullByDefault
@ThreadSafe
public class Session { public class Session {
private static final GenericAcmeProvider GENERIC_PROVIDER = new GenericAcmeProvider(); private static final GenericAcmeProvider GENERIC_PROVIDER = new GenericAcmeProvider();
@ -55,10 +49,10 @@ public class Session {
private final URI serverUri; private final URI serverUri;
private final AcmeProvider provider; private final AcmeProvider provider;
private String nonce; private @Nullable String nonce;
private Locale locale = Locale.getDefault(); private Locale locale = Locale.getDefault();
protected ZonedDateTime directoryLastModified; protected @Nullable ZonedDateTime directoryLastModified;
protected ZonedDateTime directoryExpires; protected @Nullable ZonedDateTime directoryExpires;
/** /**
* Creates a new {@link Session}. * 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. * Gets the last base64 encoded nonce, or {@code null} if the session is new.
*/ */
@CheckForNull @Nullable
public String getNonce() { public String getNonce() {
return nonce; return nonce;
} }
@ -256,7 +250,7 @@ public class Session {
* (directory has not been read yet or did not provide this information). * (directory has not been read yet or did not provide this information).
* @since 2.10 * @since 2.10
*/ */
@CheckForNull @Nullable
public ZonedDateTime getDirectoryLastModified() { public ZonedDateTime getDirectoryLastModified() {
return directoryLastModified; return directoryLastModified;
} }
@ -282,7 +276,7 @@ public class Session {
* information. * information.
* @since 2.10 * @since 2.10
*/ */
@CheckForNull @Nullable
public ZonedDateTime getDirectoryExpires() { public ZonedDateTime getDirectoryExpires() {
return directoryExpires; return directoryExpires;
} }

View File

@ -15,14 +15,9 @@ package org.shredzone.acme4j;
import java.util.Arrays; import java.util.Arrays;
import javax.annotation.ParametersAreNonnullByDefault;
import javax.annotation.concurrent.Immutable;
/** /**
* Status codes of challenges and authorizations. * Status codes of challenges and authorizations.
*/ */
@ParametersAreNonnullByDefault
@Immutable
public enum Status { public enum Status {
/** /**

View File

@ -15,9 +15,7 @@ package org.shredzone.acme4j.challenge;
import java.time.Instant; import java.time.Instant;
import javax.annotation.CheckForNull; import edu.umd.cs.findbugs.annotations.Nullable;
import javax.annotation.ParametersAreNonnullByDefault;
import org.shredzone.acme4j.AcmeJsonResource; import org.shredzone.acme4j.AcmeJsonResource;
import org.shredzone.acme4j.Login; import org.shredzone.acme4j.Login;
import org.shredzone.acme4j.Problem; import org.shredzone.acme4j.Problem;
@ -40,7 +38,6 @@ import org.slf4j.LoggerFactory;
* own type. {@link Challenge#prepareResponse(JSONBuilder)} should be overridden to put * own type. {@link Challenge#prepareResponse(JSONBuilder)} should be overridden to put
* all required data to the response. * all required data to the response.
*/ */
@ParametersAreNonnullByDefault
public class Challenge extends AcmeJsonResource { public class Challenge extends AcmeJsonResource {
private static final long serialVersionUID = 2338794776848388099L; private static final long serialVersionUID = 2338794776848388099L;
private static final Logger LOG = LoggerFactory.getLogger(Challenge.class); 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. * Returns the validation date, if returned by the server.
*/ */
@CheckForNull @Nullable
public Instant getValidated() { public Instant getValidated() {
return getJSON().get(KEY_VALIDATED).map(Value::asInstant).orElse(null); 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 * server. If there are multiple errors, they can be found in
* {@link Problem#getSubProblems()}. * {@link Problem#getSubProblems()}.
*/ */
@CheckForNull @Nullable
public Problem getError() { public Problem getError() {
return getJSON().get(KEY_ERROR) return getJSON().get(KEY_ERROR)
.map(it -> it.asProblem(getLocation())) .map(it -> it.asProblem(getLocation()))

View File

@ -16,15 +16,12 @@ package org.shredzone.acme4j.challenge;
import static org.shredzone.acme4j.toolbox.AcmeUtils.base64UrlEncode; import static org.shredzone.acme4j.toolbox.AcmeUtils.base64UrlEncode;
import static org.shredzone.acme4j.toolbox.AcmeUtils.sha256hash; import static org.shredzone.acme4j.toolbox.AcmeUtils.sha256hash;
import javax.annotation.ParametersAreNonnullByDefault;
import org.shredzone.acme4j.Login; import org.shredzone.acme4j.Login;
import org.shredzone.acme4j.toolbox.JSON; import org.shredzone.acme4j.toolbox.JSON;
/** /**
* Implements the {@value TYPE} challenge. * Implements the {@value TYPE} challenge.
*/ */
@ParametersAreNonnullByDefault
public class Dns01Challenge extends TokenChallenge { public class Dns01Challenge extends TokenChallenge {
private static final long serialVersionUID = 6964687027713533075L; private static final long serialVersionUID = 6964687027713533075L;

View File

@ -13,15 +13,12 @@
*/ */
package org.shredzone.acme4j.challenge; package org.shredzone.acme4j.challenge;
import javax.annotation.ParametersAreNonnullByDefault;
import org.shredzone.acme4j.Login; import org.shredzone.acme4j.Login;
import org.shredzone.acme4j.toolbox.JSON; import org.shredzone.acme4j.toolbox.JSON;
/** /**
* Implements the {@value TYPE} challenge. * Implements the {@value TYPE} challenge.
*/ */
@ParametersAreNonnullByDefault
public class Http01Challenge extends TokenChallenge { public class Http01Challenge extends TokenChallenge {
private static final long serialVersionUID = 3322211185872544605L; private static final long serialVersionUID = 3322211185872544605L;

View File

@ -15,8 +15,6 @@ package org.shredzone.acme4j.challenge;
import static org.shredzone.acme4j.toolbox.AcmeUtils.sha256hash; import static org.shredzone.acme4j.toolbox.AcmeUtils.sha256hash;
import javax.annotation.ParametersAreNonnullByDefault;
import org.shredzone.acme4j.Login; import org.shredzone.acme4j.Login;
import org.shredzone.acme4j.toolbox.JSON; import org.shredzone.acme4j.toolbox.JSON;
@ -25,7 +23,6 @@ import org.shredzone.acme4j.toolbox.JSON;
* *
* @since 2.1 * @since 2.1
*/ */
@ParametersAreNonnullByDefault
public class TlsAlpn01Challenge extends TokenChallenge { public class TlsAlpn01Challenge extends TokenChallenge {
private static final long serialVersionUID = -5590351078176091228L; private static final long serialVersionUID = -5590351078176091228L;

View File

@ -17,8 +17,6 @@ import static org.shredzone.acme4j.toolbox.AcmeUtils.base64UrlEncode;
import java.security.PublicKey; import java.security.PublicKey;
import javax.annotation.ParametersAreNonnullByDefault;
import org.shredzone.acme4j.Login; import org.shredzone.acme4j.Login;
import org.shredzone.acme4j.exception.AcmeProtocolException; import org.shredzone.acme4j.exception.AcmeProtocolException;
import org.shredzone.acme4j.toolbox.AcmeUtils; 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 * An extension of {@link Challenge} that handles challenges with a {@code token} and
* {@code keyAuthorization}. * {@code keyAuthorization}.
*/ */
@ParametersAreNonnullByDefault
public class TokenChallenge extends Challenge { public class TokenChallenge extends Challenge {
private static final long serialVersionUID = 1634133407432681800L; private static final long serialVersionUID = 1634133407432681800L;

View File

@ -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;

View File

@ -22,10 +22,7 @@ import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
import javax.annotation.CheckForNull; import edu.umd.cs.findbugs.annotations.Nullable;
import javax.annotation.Nullable;
import javax.annotation.ParametersAreNonnullByDefault;
import org.shredzone.acme4j.Login; import org.shredzone.acme4j.Login;
import org.shredzone.acme4j.Session; import org.shredzone.acme4j.Session;
import org.shredzone.acme4j.exception.AcmeException; 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. * Connects to the ACME server and offers different methods for invoking the API.
*/ */
@ParametersAreNonnullByDefault
public interface Connection extends AutoCloseable { 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 * @return Base64 encoded nonce, or {@code null} if no nonce header was set
*/ */
@CheckForNull @Nullable
String getNonce(); String getNonce();
/** /**
@ -176,7 +172,7 @@ public interface Connection extends AutoCloseable {
* *
* @return Location {@link URL}, or {@code null} if no Location header was set * @return Location {@link URL}, or {@code null} if no Location header was set
*/ */
@CheckForNull @Nullable
URL getLocation(); URL getLocation();
/** /**

View File

@ -41,10 +41,7 @@ import java.util.Optional;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import javax.annotation.CheckForNull; import edu.umd.cs.findbugs.annotations.Nullable;
import javax.annotation.Nullable;
import javax.annotation.ParametersAreNonnullByDefault;
import org.shredzone.acme4j.Login; import org.shredzone.acme4j.Login;
import org.shredzone.acme4j.Problem; import org.shredzone.acme4j.Problem;
import org.shredzone.acme4j.Session; import org.shredzone.acme4j.Session;
@ -66,7 +63,6 @@ import org.slf4j.LoggerFactory;
/** /**
* Default implementation of {@link Connection}. * Default implementation of {@link Connection}.
*/ */
@ParametersAreNonnullByDefault
public class DefaultConnection implements Connection { public class DefaultConnection implements Connection {
private static final Logger LOG = LoggerFactory.getLogger(DefaultConnection.class); 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); private static final Pattern MAX_AGE_PATTERN = Pattern.compile("(?:^|.*?,)\\s*max-age=(\\d+)\\s*(?:,.*|$)", Pattern.CASE_INSENSITIVE);
protected final HttpConnector httpConnector; protected final HttpConnector httpConnector;
protected HttpURLConnection conn; protected @Nullable HttpURLConnection conn;
/** /**
* Creates a new {@link DefaultConnection}. * Creates a new {@link DefaultConnection}.
@ -232,7 +228,7 @@ public class DefaultConnection implements Connection {
} }
@Override @Override
@CheckForNull @Nullable
public String getNonce() { public String getNonce() {
assertConnectionIsOpen(); assertConnectionIsOpen();
@ -251,7 +247,7 @@ public class DefaultConnection implements Connection {
} }
@Override @Override
@CheckForNull @Nullable
public URL getLocation() { public URL getLocation() {
assertConnectionIsOpen(); assertConnectionIsOpen();
@ -625,7 +621,7 @@ public class DefaultConnection implements Connection {
* @return Absolute URL of the given link, or {@code null} if the link was * @return Absolute URL of the given link, or {@code null} if the link was
* {@code null}. * {@code null}.
*/ */
@CheckForNull @Nullable
private URL resolveRelative(@Nullable String link) { private URL resolveRelative(@Nullable String link) {
if (link == null) { if (link == null) {
return 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 * @return Absolute URI of the given link, or {@code null} if the URI was
* {@code null}. * {@code null}.
*/ */
@CheckForNull @Nullable
private URI resolveUri(@Nullable String uri) { private URI resolveUri(@Nullable String uri) {
if (uri == null) { if (uri == null) {
return null; return null;

View File

@ -19,10 +19,6 @@ import java.net.HttpURLConnection;
import java.net.URL; import java.net.URL;
import java.util.Properties; import java.util.Properties;
import javax.annotation.OverridingMethodsMustInvokeSuper;
import javax.annotation.ParametersAreNonnullByDefault;
import javax.annotation.concurrent.ThreadSafe;
import org.slf4j.LoggerFactory; 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 * Subclasses may reconfigure the {@link HttpURLConnection} and pin it to a concrete SSL
* certificate. * certificate.
*/ */
@ParametersAreNonnullByDefault
@ThreadSafe
public class HttpConnector { public class HttpConnector {
private static final String USER_AGENT; private static final String USER_AGENT;
@ -90,7 +84,6 @@ public class HttpConnector {
* @param settings * @param settings
* {@link NetworkSettings} with settings to be used * {@link NetworkSettings} with settings to be used
*/ */
@OverridingMethodsMustInvokeSuper
protected void configure(HttpURLConnection conn, NetworkSettings settings) { protected void configure(HttpURLConnection conn, NetworkSettings settings) {
int timeout = (int) settings.getTimeout().toMillis(); int timeout = (int) settings.getTimeout().toMillis();
conn.setConnectTimeout(timeout); conn.setConnectTimeout(timeout);

View File

@ -16,15 +16,13 @@ package org.shredzone.acme4j.connector;
import java.net.Proxy; import java.net.Proxy;
import java.time.Duration; import java.time.Duration;
import javax.annotation.Nullable; import edu.umd.cs.findbugs.annotations.Nullable;
import javax.annotation.ParametersAreNonnullByDefault;
/** /**
* Contains network settings to be used for network connections. * Contains network settings to be used for network connections.
* *
* @since 2.8 * @since 2.8
*/ */
@ParametersAreNonnullByDefault
public class NetworkSettings { public class NetworkSettings {
private Proxy proxy = Proxy.NO_PROXY; private Proxy proxy = Proxy.NO_PROXY;

View File

@ -13,14 +13,9 @@
*/ */
package org.shredzone.acme4j.connector; package org.shredzone.acme4j.connector;
import javax.annotation.ParametersAreNonnullByDefault;
import javax.annotation.concurrent.Immutable;
/** /**
* Enumeration of resources. * Enumeration of resources.
*/ */
@ParametersAreNonnullByDefault
@Immutable
public enum Resource { public enum Resource {
NEW_NONCE("newNonce"), NEW_NONCE("newNonce"),

View File

@ -21,9 +21,7 @@ import java.util.NoSuchElementException;
import java.util.Objects; import java.util.Objects;
import java.util.function.BiFunction; import java.util.function.BiFunction;
import javax.annotation.Nullable; import edu.umd.cs.findbugs.annotations.Nullable;
import javax.annotation.ParametersAreNonnullByDefault;
import org.shredzone.acme4j.AcmeResource; import org.shredzone.acme4j.AcmeResource;
import org.shredzone.acme4j.Login; import org.shredzone.acme4j.Login;
import org.shredzone.acme4j.Session; import org.shredzone.acme4j.Session;
@ -38,7 +36,6 @@ import org.shredzone.acme4j.toolbox.JSON;
* @param <T> * @param <T>
* {@link AcmeResource} type to iterate over * {@link AcmeResource} type to iterate over
*/ */
@ParametersAreNonnullByDefault
public class ResourceIterator<T extends AcmeResource> implements Iterator<T> { public class ResourceIterator<T extends AcmeResource> implements Iterator<T> {
private final Login login; private final Login login;
@ -46,7 +43,7 @@ public class ResourceIterator<T extends AcmeResource> implements Iterator<T> {
private final Deque<URL> urlList = new ArrayDeque<>(); private final Deque<URL> urlList = new ArrayDeque<>();
private final BiFunction<Login, URL, T> creator; private final BiFunction<Login, URL, T> creator;
private boolean eol = false; private boolean eol = false;
private URL nextUrl; private @Nullable URL nextUrl;
/** /**
* Creates a new {@link ResourceIterator}. * Creates a new {@link ResourceIterator}.

View File

@ -16,13 +16,10 @@ package org.shredzone.acme4j.connector;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import javax.annotation.ParametersAreNonnullByDefault;
/** /**
* Normalizes line separators in an InputStream. Converts all line separators to '\n'. * Normalizes line separators in an InputStream. Converts all line separators to '\n'.
* Multiple line separators are compressed to a single line separator. * Multiple line separators are compressed to a single line separator.
*/ */
@ParametersAreNonnullByDefault
public class TrimmingInputStream extends InputStream { public class TrimmingInputStream extends InputStream {
private final InputStream in; private final InputStream in;

View File

@ -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;

View File

@ -13,14 +13,9 @@
*/ */
package org.shredzone.acme4j.exception; package org.shredzone.acme4j.exception;
import javax.annotation.ParametersAreNonnullByDefault;
import javax.annotation.concurrent.Immutable;
/** /**
* A generic ACME exception. * A generic ACME exception.
*/ */
@ParametersAreNonnullByDefault
@Immutable
public class AcmeException extends Exception { public class AcmeException extends Exception {
private static final long serialVersionUID = -2935088954705632025L; private static final long serialVersionUID = -2935088954705632025L;

View File

@ -17,17 +17,12 @@ import static java.util.Objects.requireNonNull;
import java.net.URL; import java.net.URL;
import javax.annotation.ParametersAreNonnullByDefault;
import javax.annotation.concurrent.Immutable;
import org.shredzone.acme4j.AcmeResource; import org.shredzone.acme4j.AcmeResource;
/** /**
* This runtime exception is thrown when an {@link AcmeException} occured while trying to * This runtime exception is thrown when an {@link AcmeException} occured while trying to
* lazy-load a resource from the ACME server. * lazy-load a resource from the ACME server.
*/ */
@ParametersAreNonnullByDefault
@Immutable
public class AcmeLazyLoadingException extends RuntimeException { public class AcmeLazyLoadingException extends RuntimeException {
private static final long serialVersionUID = 1000353433913721901L; private static final long serialVersionUID = 1000353433913721901L;

View File

@ -15,15 +15,10 @@ package org.shredzone.acme4j.exception;
import java.io.IOException; 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 * This exception is thrown when a network error occured while communicating with the
* server. * server.
*/ */
@ParametersAreNonnullByDefault
@Immutable
public class AcmeNetworkException extends AcmeException { public class AcmeNetworkException extends AcmeException {
private static final long serialVersionUID = 2054398693543329179L; private static final long serialVersionUID = 2054398693543329179L;

View File

@ -13,15 +13,10 @@
*/ */
package org.shredzone.acme4j.exception; 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 * 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. * example, this exception is thrown when a server response could not be parsed.
*/ */
@ParametersAreNonnullByDefault
@Immutable
public class AcmeProtocolException extends RuntimeException { public class AcmeProtocolException extends RuntimeException {
private static final long serialVersionUID = 2031203835755725193L; private static final long serialVersionUID = 2031203835755725193L;

View File

@ -18,23 +18,17 @@ import java.time.Instant;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import javax.annotation.CheckForNull; import edu.umd.cs.findbugs.annotations.Nullable;
import javax.annotation.Nullable;
import javax.annotation.ParametersAreNonnullByDefault;
import javax.annotation.concurrent.Immutable;
import org.shredzone.acme4j.Problem; import org.shredzone.acme4j.Problem;
/** /**
* An exception that is thrown when a rate limit was exceeded. * An exception that is thrown when a rate limit was exceeded.
*/ */
@ParametersAreNonnullByDefault
@Immutable
public class AcmeRateLimitedException extends AcmeServerException { public class AcmeRateLimitedException extends AcmeServerException {
private static final long serialVersionUID = 4150484059796413069L; private static final long serialVersionUID = 4150484059796413069L;
private final Instant retryAfter; private final @Nullable Instant retryAfter;
private final Collection<URL> documents; private final @Nullable Collection<URL> documents;
/** /**
* Creates a new {@link AcmeRateLimitedException}. * 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 * Returns the moment the request is expected to succeed again. {@code null} if this
* moment is not known. * moment is not known.
*/ */
@CheckForNull @Nullable
public Instant getRetryAfter() { public Instant getRetryAfter() {
return retryAfter; return retryAfter;
} }
@ -68,7 +62,7 @@ public class AcmeRateLimitedException extends AcmeServerException {
* Collection of URLs pointing to documents about the rate limit that was hit. * Collection of URLs pointing to documents about the rate limit that was hit.
* {@code null} if the server did not provide such URLs. * {@code null} if the server did not provide such URLs.
*/ */
@CheckForNull @Nullable
public Collection<URL> getDocuments() { public Collection<URL> getDocuments() {
return documents; return documents;
} }

View File

@ -16,15 +16,10 @@ package org.shredzone.acme4j.exception;
import java.time.Instant; import java.time.Instant;
import java.util.Objects; 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 * This exception is thrown when a server side process has not been completed yet, and the
* server returned an estimated retry date. * server returned an estimated retry date.
*/ */
@ParametersAreNonnullByDefault
@Immutable
public class AcmeRetryAfterException extends AcmeException { public class AcmeRetryAfterException extends AcmeException {
private static final long serialVersionUID = 4461979121063649905L; private static final long serialVersionUID = 4461979121063649905L;

View File

@ -16,17 +16,12 @@ package org.shredzone.acme4j.exception;
import java.net.URI; import java.net.URI;
import java.util.Objects; import java.util.Objects;
import javax.annotation.ParametersAreNonnullByDefault;
import javax.annotation.concurrent.Immutable;
import org.shredzone.acme4j.Problem; import org.shredzone.acme4j.Problem;
/** /**
* An exception that is thrown when the ACME server returned an error. It contains * An exception that is thrown when the ACME server returned an error. It contains
* further details of the cause. * further details of the cause.
*/ */
@ParametersAreNonnullByDefault
@Immutable
public class AcmeServerException extends AcmeException { public class AcmeServerException extends AcmeException {
private static final long serialVersionUID = 5971622508467042792L; private static final long serialVersionUID = 5971622508467042792L;

View File

@ -13,17 +13,12 @@
*/ */
package org.shredzone.acme4j.exception; package org.shredzone.acme4j.exception;
import javax.annotation.ParametersAreNonnullByDefault;
import javax.annotation.concurrent.Immutable;
import org.shredzone.acme4j.Problem; import org.shredzone.acme4j.Problem;
/** /**
* An exception that is thrown when the client is not authorized. The details will give * 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"). * an explanation for the reasons (e.g. "client not on a whitelist").
*/ */
@ParametersAreNonnullByDefault
@Immutable
public class AcmeUnauthorizedException extends AcmeServerException { public class AcmeUnauthorizedException extends AcmeServerException {
private static final long serialVersionUID = 9064697508262919366L; private static final long serialVersionUID = 9064697508262919366L;

View File

@ -17,11 +17,7 @@ import java.net.MalformedURLException;
import java.net.URI; import java.net.URI;
import java.net.URL; import java.net.URL;
import javax.annotation.CheckForNull; import edu.umd.cs.findbugs.annotations.Nullable;
import javax.annotation.Nullable;
import javax.annotation.ParametersAreNonnullByDefault;
import javax.annotation.concurrent.Immutable;
import org.shredzone.acme4j.Problem; 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 * Usually this exception is thrown when the terms of service have changed, and the CA
* requires an agreement to the new terms before proceeding. * requires an agreement to the new terms before proceeding.
*/ */
@ParametersAreNonnullByDefault
@Immutable
public class AcmeUserActionRequiredException extends AcmeServerException { public class AcmeUserActionRequiredException extends AcmeServerException {
private static final long serialVersionUID = 7719055447283858352L; private static final long serialVersionUID = 7719055447283858352L;
private final URI tosUri; private final @Nullable URI tosUri;
/** /**
* Creates a new {@link AcmeUserActionRequiredException}. * 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} * 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. * if the server did not provide a link to such a document.
*/ */
@CheckForNull @Nullable
public URI getTermsOfServiceUri() { public URI getTermsOfServiceUri() {
return tosUri; return tosUri;
} }

View File

@ -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;

View File

@ -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;

View File

@ -22,8 +22,6 @@ import java.util.Map;
import java.util.Objects; import java.util.Objects;
import java.util.function.BiFunction; import java.util.function.BiFunction;
import javax.annotation.ParametersAreNonnullByDefault;
import org.shredzone.acme4j.Login; import org.shredzone.acme4j.Login;
import org.shredzone.acme4j.Session; import org.shredzone.acme4j.Session;
import org.shredzone.acme4j.challenge.Challenge; 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)} * Implementing classes must implement at least {@link AcmeProvider#accepts(URI)}
* and {@link AbstractAcmeProvider#resolve(URI)}. * and {@link AbstractAcmeProvider#resolve(URI)}.
*/ */
@ParametersAreNonnullByDefault
public abstract class AbstractAcmeProvider implements AcmeProvider { public abstract class AbstractAcmeProvider implements AcmeProvider {
private static final Map<String, BiFunction<Login, JSON, Challenge>> CHALLENGES = challengeMap(); private static final Map<String, BiFunction<Login, JSON, Challenge>> CHALLENGES = challengeMap();

View File

@ -17,9 +17,7 @@ import java.net.URI;
import java.net.URL; import java.net.URL;
import java.util.ServiceLoader; import java.util.ServiceLoader;
import javax.annotation.CheckForNull; import edu.umd.cs.findbugs.annotations.Nullable;
import javax.annotation.ParametersAreNonnullByDefault;
import org.shredzone.acme4j.Login; import org.shredzone.acme4j.Login;
import org.shredzone.acme4j.Session; import org.shredzone.acme4j.Session;
import org.shredzone.acme4j.challenge.Challenge; import org.shredzone.acme4j.challenge.Challenge;
@ -33,7 +31,6 @@ import org.shredzone.acme4j.toolbox.JSON;
* <p> * <p>
* Provider implementations must be registered with Java's {@link ServiceLoader}. * Provider implementations must be registered with Java's {@link ServiceLoader}.
*/ */
@ParametersAreNonnullByDefault
public interface AcmeProvider { public interface AcmeProvider {
/** /**
@ -80,7 +77,7 @@ public interface AcmeProvider {
* @return Directory data, as JSON object, or {@code null} if the directory has not * @return Directory data, as JSON object, or {@code null} if the directory has not
* been changed since the last request. * been changed since the last request.
*/ */
@CheckForNull @Nullable
JSON directory(Session session, URI serverUri) throws AcmeException; 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 * @return {@link Challenge} instance, or {@code null} if this provider is unable to
* generate a matching {@link Challenge} instance. * generate a matching {@link Challenge} instance.
*/ */
@CheckForNull @Nullable
Challenge createChallenge(Login login, JSON data); Challenge createChallenge(Login login, JSON data);
} }

View File

@ -17,15 +17,12 @@ import java.net.MalformedURLException;
import java.net.URI; import java.net.URI;
import java.net.URL; import java.net.URL;
import javax.annotation.ParametersAreNonnullByDefault;
/** /**
* A generic {@link AcmeProvider}. It should be working for all ACME servers complying to * A generic {@link AcmeProvider}. It should be working for all ACME servers complying to
* the ACME specifications. * the ACME specifications.
* <p> * <p>
* The {@code serverUri} is either a http or https URI to the server's directory service. * The {@code serverUri} is either a http or https URI to the server's directory service.
*/ */
@ParametersAreNonnullByDefault
public class GenericAcmeProvider extends AbstractAcmeProvider { public class GenericAcmeProvider extends AbstractAcmeProvider {
@Override @Override

View File

@ -17,8 +17,6 @@ import java.net.MalformedURLException;
import java.net.URI; import java.net.URI;
import java.net.URL; import java.net.URL;
import javax.annotation.ParametersAreNonnullByDefault;
import org.shredzone.acme4j.exception.AcmeProtocolException; import org.shredzone.acme4j.exception.AcmeProtocolException;
import org.shredzone.acme4j.provider.AbstractAcmeProvider; import org.shredzone.acme4j.provider.AbstractAcmeProvider;
import org.shredzone.acme4j.provider.AcmeProvider; import org.shredzone.acme4j.provider.AcmeProvider;
@ -33,7 +31,6 @@ import org.shredzone.acme4j.provider.AcmeProvider;
* *
* @see <a href="https://letsencrypt.org/">Let's Encrypt</a> * @see <a href="https://letsencrypt.org/">Let's Encrypt</a>
*/ */
@ParametersAreNonnullByDefault
public class LetsEncryptAcmeProvider extends AbstractAcmeProvider { public class LetsEncryptAcmeProvider extends AbstractAcmeProvider {
private static final String V02_DIRECTORY_URL = "https://acme-v02.api.letsencrypt.org/directory"; private static final String V02_DIRECTORY_URL = "https://acme-v02.api.letsencrypt.org/directory";

View File

@ -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;

View File

@ -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;

View File

@ -19,8 +19,6 @@ import java.net.URL;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import javax.annotation.ParametersAreNonnullByDefault;
import org.shredzone.acme4j.connector.HttpConnector; import org.shredzone.acme4j.connector.HttpConnector;
import org.shredzone.acme4j.provider.AbstractAcmeProvider; import org.shredzone.acme4j.provider.AbstractAcmeProvider;
import org.shredzone.acme4j.provider.AcmeProvider; 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 * 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. * port. The port is optional, and if omitted, the standard port is used.
*/ */
@ParametersAreNonnullByDefault
public class PebbleAcmeProvider extends AbstractAcmeProvider { public class PebbleAcmeProvider extends AbstractAcmeProvider {
private static final Pattern HOST_PATTERN = Pattern.compile("^/([^:/]+)(?:\\:(\\d+))?/?$"); private static final Pattern HOST_PATTERN = Pattern.compile("^/([^:/]+)(?:\\:(\\d+))?/?$");

View File

@ -22,14 +22,14 @@ import java.security.KeyStore;
import java.security.KeyStoreException; import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException; 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.HttpsURLConnection;
import javax.net.ssl.SSLContext; import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory; import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManagerFactory; import javax.net.ssl.TrustManagerFactory;
import edu.umd.cs.findbugs.annotations.Nullable;
import org.shredzone.acme4j.connector.HttpConnector; import org.shredzone.acme4j.connector.HttpConnector;
import org.shredzone.acme4j.connector.NetworkSettings; 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 * {@link HttpConnector} to be used for Pebble. Pebble uses a static, self signed SSL
* certificate. * certificate.
*/ */
@ParametersAreNonnullByDefault
@ThreadSafe
public class PebbleHttpConnector extends HttpConnector { public class PebbleHttpConnector extends HttpConnector {
private static SSLSocketFactory sslSocketFactory; private static @Nullable SSLSocketFactory sslSocketFactory = null;
@Override @Override
public HttpURLConnection openConnection(URL url, NetworkSettings settings) throws IOException { 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); throw new IOException("Could not create truststore", ex);
} }
} }
return sslSocketFactory; return Objects.requireNonNull(sslSocketFactory);
} }
} }

View File

@ -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;

View File

@ -29,12 +29,7 @@ import java.util.Objects;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import javax.annotation.CheckForNull; import edu.umd.cs.findbugs.annotations.Nullable;
import javax.annotation.Nullable;
import javax.annotation.ParametersAreNonnullByDefault;
import javax.annotation.WillNotClose;
import javax.annotation.concurrent.Immutable;
import org.shredzone.acme4j.exception.AcmeProtocolException; 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 * 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. * change their signature or disappear without prior announcement.
*/ */
@ParametersAreNonnullByDefault
public final class AcmeUtils { public final class AcmeUtils {
private static final char[] HEX = "0123456789abcdef".toCharArray(); private static final char[] HEX = "0123456789abcdef".toCharArray();
private static final String ACME_ERROR_PREFIX = "urn:ietf:params:acme:error:"; private static final String ACME_ERROR_PREFIX = "urn:ietf:params:acme:error:";
@ -72,8 +66,6 @@ public final class AcmeUtils {
/** /**
* Enumeration of PEM labels. * Enumeration of PEM labels.
*/ */
@ParametersAreNonnullByDefault
@Immutable
public enum PemLabel { public enum PemLabel {
CERTIFICATE("CERTIFICATE"), CERTIFICATE("CERTIFICATE"),
CERTIFICATE_REQUEST("CERTIFICATE REQUEST"), CERTIFICATE_REQUEST("CERTIFICATE REQUEST"),
@ -239,7 +231,7 @@ public final class AcmeUtils {
* Error type to strip the prefix from. {@code null} is safe. * Error type to strip the prefix from. {@code null} is safe.
* @return Stripped error type, or {@code null} if the prefix was not found. * @return Stripped error type, or {@code null} if the prefix was not found.
*/ */
@CheckForNull @Nullable
public static String stripErrorPrefix(@Nullable String type) { public static String stripErrorPrefix(@Nullable String type) {
if (type != null && type.startsWith(ACME_ERROR_PREFIX)) { if (type != null && type.startsWith(ACME_ERROR_PREFIX)) {
return type.substring(ACME_ERROR_PREFIX.length()); return type.substring(ACME_ERROR_PREFIX.length());
@ -258,7 +250,7 @@ public final class AcmeUtils {
* @param out * @param out
* {@link Writer} to write to. It will not be closed after use! * {@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 { throws IOException {
out.append("-----BEGIN ").append(label.toString()).append("-----\n"); out.append("-----BEGIN ").append(label.toString()).append("-----\n");
out.append(new String(PEM_ENCODER.encode(encoded), StandardCharsets.US_ASCII)); out.append(new String(PEM_ENCODER.encode(encoded), StandardCharsets.US_ASCII));
@ -274,7 +266,7 @@ public final class AcmeUtils {
* @throws AcmeProtocolException * @throws AcmeProtocolException
* if the Content-Type header contains a different charset than "utf-8". * if the Content-Type header contains a different charset than "utf-8".
*/ */
@CheckForNull @Nullable
public static String getContentType(@Nullable String header) { public static String getContentType(@Nullable String header) {
if (header != null) { if (header != null) {
Matcher m = CONTENT_TYPE_PATTERN.matcher(header); Matcher m = CONTENT_TYPE_PATTERN.matcher(header);

View File

@ -43,11 +43,7 @@ import java.util.function.Function;
import java.util.stream.Stream; import java.util.stream.Stream;
import java.util.stream.StreamSupport; import java.util.stream.StreamSupport;
import javax.annotation.Nullable; import edu.umd.cs.findbugs.annotations.Nullable;
import javax.annotation.ParametersAreNonnullByDefault;
import javax.annotation.WillClose;
import javax.annotation.concurrent.Immutable;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import org.jose4j.json.JsonUtil; import org.jose4j.json.JsonUtil;
import org.jose4j.lang.JoseException; 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. * A model containing a JSON result. The content is immutable.
*/ */
@ParametersAreNonnullByDefault
@Immutable
public final class JSON implements Serializable { public final class JSON implements Serializable {
private static final long serialVersionUID = 3091273044605709204L; 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. * {@link InputStream} to read from. Will be closed after use.
* @return {@link JSON} of the read content. * @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"))) { try (BufferedReader reader = new BufferedReader(new InputStreamReader(in, "utf-8"))) {
String json = reader.lines().map(String::trim).collect(joining()); String json = reader.lines().map(String::trim).collect(joining());
return parse(json); return parse(json);
@ -205,8 +199,6 @@ public final class JSON implements Serializable {
/** /**
* Represents a JSON array. * Represents a JSON array.
*/ */
@ParametersAreNonnullByDefault
@Immutable
public static final class Array implements Iterable<Value> { public static final class Array implements Iterable<Value> {
private final String path; private final String path;
private final List<Object> data; private final List<Object> data;
@ -275,11 +267,9 @@ public final class JSON implements Serializable {
* All return values are never {@code null} unless specified otherwise. For optional * All return values are never {@code null} unless specified otherwise. For optional
* parameters, use {@link Value#optional()}. * parameters, use {@link Value#optional()}.
*/ */
@ParametersAreNonnullByDefault
@Immutable
public static final class Value { public static final class Value {
private final String path; private final String path;
private final Object val; private final @Nullable Object val;
/** /**
* Creates a new {@link Value}. * Creates a new {@link Value}.
@ -519,7 +509,6 @@ public final class JSON implements Serializable {
/** /**
* An {@link Iterator} over array {@link Value}. * An {@link Iterator} over array {@link Value}.
*/ */
@ParametersAreNonnullByDefault
private static class ValueIterator implements Iterator<Value> { private static class ValueIterator implements Iterator<Value> {
private final Array array; private final Array array;
private int index = 0; private int index = 0;

View File

@ -26,9 +26,7 @@ import java.util.LinkedHashMap;
import java.util.Map; import java.util.Map;
import java.util.Objects; import java.util.Objects;
import javax.annotation.Nullable; import edu.umd.cs.findbugs.annotations.Nullable;
import javax.annotation.ParametersAreNonnullByDefault;
import org.jose4j.json.JsonUtil; import org.jose4j.json.JsonUtil;
/** /**
@ -42,7 +40,6 @@ import org.jose4j.json.JsonUtil;
* cb.array("array", 123, 456, 789); * cb.array("array", 123, 456, 789);
* </pre> * </pre>
*/ */
@ParametersAreNonnullByDefault
public class JSONBuilder { public class JSONBuilder {
private final Map<String, Object> data = new LinkedHashMap<>(); private final Map<String, Object> data = new LinkedHashMap<>();

View File

@ -18,10 +18,9 @@ import java.security.KeyPair;
import java.security.PublicKey; import java.security.PublicKey;
import java.util.Map; import java.util.Map;
import javax.annotation.Nullable;
import javax.annotation.ParametersAreNonnullByDefault;
import javax.crypto.SecretKey; import javax.crypto.SecretKey;
import edu.umd.cs.findbugs.annotations.Nullable;
import org.jose4j.jwk.EllipticCurveJsonWebKey; import org.jose4j.jwk.EllipticCurveJsonWebKey;
import org.jose4j.jwk.JsonWebKey; import org.jose4j.jwk.JsonWebKey;
import org.jose4j.jwk.PublicJsonWebKey; import org.jose4j.jwk.PublicJsonWebKey;
@ -37,7 +36,6 @@ import org.slf4j.LoggerFactory;
* *
* @since 2.7 * @since 2.7
*/ */
@ParametersAreNonnullByDefault
public final class JoseUtils { public final class JoseUtils {
private static final Logger LOG = LoggerFactory.getLogger(JoseUtils.class); 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. * @return JSON structure of the JOSE request, ready to be sent.
*/ */
public static JSONBuilder createJoseRequest(URL url, KeyPair keypair, 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 { try {
PublicJsonWebKey jwk = PublicJsonWebKey.Factory.newPublicJwk(keypair.getPublic()); PublicJsonWebKey jwk = PublicJsonWebKey.Factory.newPublicJwk(keypair.getPublic());

View File

@ -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;

View File

@ -30,8 +30,6 @@ import java.time.temporal.ChronoUnit;
import java.util.Optional; import java.util.Optional;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
import javax.annotation.ParametersAreNonnullByDefault;
import org.junit.Test; import org.junit.Test;
import org.shredzone.acme4j.Login; import org.shredzone.acme4j.Login;
import org.shredzone.acme4j.Session; import org.shredzone.acme4j.Session;
@ -310,7 +308,6 @@ public class AbstractAcmeProviderTest {
} }
} }
@ParametersAreNonnullByDefault
private static class TestAbstractAcmeProvider extends AbstractAcmeProvider { private static class TestAbstractAcmeProvider extends AbstractAcmeProvider {
private final Connection connection; private final Connection connection;

View File

@ -17,8 +17,6 @@ import java.io.IOException;
import java.util.Arrays; import java.util.Arrays;
import java.util.Objects; import java.util.Objects;
import javax.annotation.ParametersAreNonnullByDefault;
import org.apache.http.HttpResponse; import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus; import org.apache.http.HttpStatus;
import org.apache.http.client.ClientProtocolException; import org.apache.http.client.ClientProtocolException;
@ -33,7 +31,6 @@ import org.shredzone.acme4j.toolbox.JSONBuilder;
/** /**
* The BammBamm client connects to the pebble-challtestsrv. * The BammBamm client connects to the pebble-challtestsrv.
*/ */
@ParametersAreNonnullByDefault
public class BammBammClient { public class BammBammClient {
private static final HttpClient CLIENT = HttpClients.createDefault(); private static final HttpClient CLIENT = HttpClients.createDefault();

View File

@ -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;

View File

@ -31,9 +31,7 @@ import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
import javax.annotation.ParametersAreNonnullByDefault; import edu.umd.cs.findbugs.annotations.Nullable;
import javax.annotation.WillClose;
import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
import org.bouncycastle.asn1.x500.X500Name; import org.bouncycastle.asn1.x500.X500Name;
import org.bouncycastle.asn1.x500.X500NameBuilder; import org.bouncycastle.asn1.x500.X500NameBuilder;
@ -57,7 +55,6 @@ import org.shredzone.acme4j.Identifier;
* <p> * <p>
* Requires {@code Bouncy Castle}. This class is part of the {@code acme4j-utils} module. * Requires {@code Bouncy Castle}. This class is part of the {@code acme4j-utils} module.
*/ */
@ParametersAreNonnullByDefault
public class CSRBuilder { public class CSRBuilder {
private static final String SIGNATURE_ALG = "SHA256withRSA"; private static final String SIGNATURE_ALG = "SHA256withRSA";
private static final String EC_SIGNATURE_ALG = "SHA256withECDSA"; 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 X500NameBuilder namebuilder = new X500NameBuilder(X500Name.getDefaultStyle());
private final List<String> namelist = new ArrayList<>(); private final List<String> namelist = new ArrayList<>();
private final List<InetAddress> iplist = new ArrayList<>(); private final List<InetAddress> 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 * 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 * {@link Writer} to write the PEM file to. The {@link Writer} is closed
* after use. * after use.
*/ */
public void write(@WillClose Writer w) throws IOException { public void write(Writer w) throws IOException {
if (csr == null) { if (csr == null) {
throw new IllegalStateException("sign CSR first"); throw new IllegalStateException("sign CSR first");
} }
@ -313,7 +310,7 @@ public class CSRBuilder {
* {@link OutputStream} to write the PEM file to. The {@link OutputStream} * {@link OutputStream} to write the PEM file to. The {@link OutputStream}
* is closed after use. * 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")); write(new OutputStreamWriter(out, "utf-8"));
} }

View File

@ -33,9 +33,6 @@ import java.util.Date;
import java.util.Objects; import java.util.Objects;
import java.util.function.Function; import java.util.function.Function;
import javax.annotation.ParametersAreNonnullByDefault;
import javax.annotation.WillClose;
import org.bouncycastle.asn1.ASN1Encodable; import org.bouncycastle.asn1.ASN1Encodable;
import org.bouncycastle.asn1.ASN1ObjectIdentifier; import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.DEROctetString; import org.bouncycastle.asn1.DEROctetString;
@ -64,7 +61,6 @@ import org.shredzone.acme4j.challenge.TlsAlpn01Challenge;
* <p> * <p>
* Requires {@code Bouncy Castle}. This class is part of the {@code acme4j-utils} module. * Requires {@code Bouncy Castle}. This class is part of the {@code acme4j-utils} module.
*/ */
@ParametersAreNonnullByDefault
public final class CertificateUtils { public final class CertificateUtils {
/** /**
@ -87,7 +83,7 @@ public final class CertificateUtils {
* closed after use. * closed after use.
* @return CSR that was read * @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))) { try (PEMParser pemParser = new PEMParser(new InputStreamReader(in, StandardCharsets.US_ASCII))) {
Object parsedObj = pemParser.readObject(); Object parsedObj = pemParser.readObject();
if (!(parsedObj instanceof PKCS10CertificationRequest)) { if (!(parsedObj instanceof PKCS10CertificationRequest)) {

View File

@ -23,9 +23,6 @@ import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException; import java.security.NoSuchProviderException;
import java.security.SecureRandom; import java.security.SecureRandom;
import javax.annotation.ParametersAreNonnullByDefault;
import javax.annotation.WillClose;
import org.bouncycastle.jce.ECNamedCurveTable; import org.bouncycastle.jce.ECNamedCurveTable;
import org.bouncycastle.jce.spec.ECParameterSpec; import org.bouncycastle.jce.spec.ECParameterSpec;
import org.bouncycastle.openssl.PEMException; import org.bouncycastle.openssl.PEMException;
@ -39,7 +36,6 @@ import org.bouncycastle.openssl.jcajce.JcaPEMWriter;
* <p> * <p>
* Requires {@code Bouncy Castle}. This class is part of the {@code acme4j-utils} module. * Requires {@code Bouncy Castle}. This class is part of the {@code acme4j-utils} module.
*/ */
@ParametersAreNonnullByDefault
public class KeyPairUtils { public class KeyPairUtils {
private KeyPairUtils() { private KeyPairUtils() {
@ -104,7 +100,7 @@ public class KeyPairUtils {
* after use. * after use.
* @return {@link KeyPair} read * @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)) { try (PEMParser parser = new PEMParser(r)) {
PEMKeyPair keyPair = (PEMKeyPair) parser.readObject(); PEMKeyPair keyPair = (PEMKeyPair) parser.readObject();
return new JcaPEMKeyConverter().getKeyPair(keyPair); 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 * {@link Writer} to write the PEM file to. The {@link Writer} is closed
* after use. * 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)) { try (JcaPEMWriter jw = new JcaPEMWriter(w)) {
jw.writeObject(keypair); jw.writeObject(keypair);
} }

View File

@ -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;

22
pom.xml
View File

@ -80,7 +80,7 @@
<plugin> <plugin>
<groupId>com.github.spotbugs</groupId> <groupId>com.github.spotbugs</groupId>
<artifactId>spotbugs-maven-plugin</artifactId> <artifactId>spotbugs-maven-plugin</artifactId>
<version>3.1.12.2</version> <version>4.0.0</version>
<configuration> <configuration>
<excludeFilterFile>src/config/spotbugs-exclude.xml</excludeFilterFile> <excludeFilterFile>src/config/spotbugs-exclude.xml</excludeFilterFile>
</configuration> </configuration>
@ -171,16 +171,16 @@
</build> </build>
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>com.google.code.findbugs</groupId> <groupId>com.github.spotbugs</groupId>
<artifactId>jsr305</artifactId> <artifactId>spotbugs-annotations</artifactId>
<version>3.0.2</version> <version>4.0.3</version>
<scope>provided</scope> <optional>true</optional>
</dependency> <exclusions>
<dependency> <exclusion>
<groupId>com.google.code.findbugs</groupId> <groupId>com.google.code.findbugs</groupId>
<artifactId>annotations</artifactId> <artifactId>jsr305</artifactId>
<version>3.0.1</version> </exclusion>
<scope>provided</scope> </exclusions>
</dependency> </dependency>
<dependency> <dependency>
<groupId>junit</groupId> <groupId>junit</groupId>

View File

@ -4,7 +4,10 @@ This document will help you migrate your code to the latest _acme4j_ version.
## Migration to Version 2.10 ## 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). - 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. - `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 ## Migration to Version 2.9