diff --git a/acme4j-client/src/main/java/module-info.java b/acme4j-client/src/main/java/module-info.java index 1d3df187..e9d9eb04 100644 --- a/acme4j-client/src/main/java/module-info.java +++ b/acme4j-client/src/main/java/module-info.java @@ -12,6 +12,9 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. */ +/** + * This is the main module of the acme4j client. + */ module org.shredzone.acme4j { requires static com.github.spotbugs.annotations; requires java.net.http; diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/Account.java b/acme4j-client/src/main/java/org/shredzone/acme4j/Account.java index 2c9415bd..edfc0507 100644 --- a/acme4j-client/src/main/java/org/shredzone/acme4j/Account.java +++ b/acme4j-client/src/main/java/org/shredzone/acme4j/Account.java @@ -37,7 +37,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** - * Represents an account at the ACME server. + * A representation of an account at the ACME server. */ public class Account extends AcmeJsonResource { private static final long serialVersionUID = 7042863483428051319L; @@ -65,7 +65,9 @@ public class Account extends AcmeJsonResource { } /** - * List of contact addresses (emails, phone numbers etc). + * List of registered contact addresses (emails, phone numbers etc). + *
+ * This list is unmodifiable. Use {@link #modify()} to change the contacts.
*/
public List
* Using the iterator will initiate one or more requests to the ACME server.
*
* @return {@link Iterator} instance that returns {@link Order} objects in no specific
- * order. {@link Iterator#hasNext()} and {@link Iterator#next()} may throw
- * {@link AcmeProtocolException} if a batch of authorization URIs could not be
- * fetched from the server. Each {@link Iterator} instance may provide the
- * {@link Order} objects in a different order.
+ * sorting order. {@link Iterator#hasNext()} and {@link Iterator#next()} may throw
+ * {@link AcmeProtocolException} if a batch of authorization URIs could not be fetched
+ * from the server.
*/
public Iterator
- * After a successful call, the new key pair is used in the bound {@link Session},
- * and the old key pair can be disposed of.
+ * After a successful call, the new key pair is already set in the associated
+ * {@link Login}. The old key pair can be discarded.
*
* @param newKeyPair
- * new {@link KeyPair} to be used for identifying this account
+ * new {@link KeyPair} to be used for identifying this account
*/
public void changeKey(KeyPair newKeyPair) throws AcmeException {
Objects.requireNonNull(newKeyPair, "newKeyPair");
@@ -267,7 +269,7 @@ public class Account extends AcmeJsonResource {
}
/**
- * Editable {@link Account}.
+ * Provides editable properties of an {@link Account}.
*/
public class EditableAccount {
private final List
+ * The modified list is not validated. If you change entries, you have to make
+ * sure that they are valid according to the RFC. It is recommended to use
+ * the {@code addContact()} methods below to add new contacts to the list.
*/
public List
- * This is a convenience call for {@link #addContact(String)} hat doesn't
- * require from you attach "mailto" scheme before email address.
+ * This is a convenience call for {@link #addContact(String)} that doesn't
+ * require to prepend the email address with the "mailto" scheme.
*
* @param email
* Contact email without "mailto" scheme (e.g. test@gmail.com)
diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/AccountBuilder.java b/acme4j-client/src/main/java/org/shredzone/acme4j/AccountBuilder.java
index 72faaf83..e9e30d2e 100644
--- a/acme4j-client/src/main/java/org/shredzone/acme4j/AccountBuilder.java
+++ b/acme4j-client/src/main/java/org/shredzone/acme4j/AccountBuilder.java
@@ -34,7 +34,21 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
- * A builder for registering a new account.
+ * A builder for registering a new account with the CA.
+ *
+ * You need to create a new key pair and set it via {@link #useKeyPair(KeyPair)}. Your
+ * account will be identified by the public part of that key pair, so make sure to store
+ * it safely! There is no automatic way to regain access to your account if the key pair
+ * is lost.
+ *
+ * Depending on the CA you register with, you might need to give additional information.
+ *
+ * A contact URI may be e.g. an email address or a phone number. It depends on the CA
+ * what kind of contact URIs are accepted, and how many must be provided as minimum.
*
* @param contact
- * Contact URI
+ * Contact URI
* @return itself
*/
public AccountBuilder addContact(URI contact) {
@@ -65,10 +82,10 @@ public class AccountBuilder {
* This is a convenience call for {@link #addContact(URI)}.
*
* @param contact
- * Contact URI as string
- * @throws IllegalArgumentException
- * if there is a syntax error in the URI string
+ * Contact URI as string
* @return itself
+ * @throws IllegalArgumentException
+ * if there is a syntax error in the URI string
*/
public AccountBuilder addContact(String contact) {
addContact(URI.create(contact));
@@ -76,16 +93,16 @@ public class AccountBuilder {
}
/**
- * Add a email address to the list of contacts.
+ * Add an email address to the list of contacts.
*
- * This is a convenience call for {@link #addContact(String)} that doesn't
- * require from you attach "mailto" scheme before email address.
+ * This is a convenience call for {@link #addContact(String)} that doesn't require
+ * to prepend the "mailto" scheme to an email address.
*
* @param email
- * Contact email without "mailto" scheme (e.g. test@gmail.com)
- * @throws IllegalArgumentException
- * if there is a syntax error in the URI string
+ * Contact email without "mailto" scheme (e.g. test@gmail.com)
* @return itself
+ * @throws IllegalArgumentException
+ * if there is a syntax error in the URI string
*/
public AccountBuilder addEmail(String email) {
addContact("mailto:" + email);
@@ -93,7 +110,12 @@ public class AccountBuilder {
}
/**
- * Signals that the user agrees to the terms of service.
+ * Documents that the user has agreed to the terms of service.
+ *
+ * If the CA requires the user to agree to the terms of service, it is your
+ * responsibility to present them to the user, and actively ask for their agreement. A
+ * link to the terms of service is provided via
+ * {@code session.getMetadata().getTermsOfService()}.
*
* @return itself
*/
@@ -104,8 +126,13 @@ public class AccountBuilder {
/**
* Signals that only an existing account should be returned. The server will not
- * create a new account if the key is not known. This is useful if you only have your
- * account's key pair available, but not your account's location URL.
+ * create a new account if the key is not known.
+ *
+ * If you have lost your account's location URL, but still have your account's key
+ * pair, you can register your account again with the same key, and use
+ * {@link #onlyExisting()} to make sure that your existing account is returned. If
+ * your key is unknown to the server, an error is thrown once the account is to be
+ * created.
*
* @return itself
*/
@@ -116,9 +143,15 @@ public class AccountBuilder {
/**
* Sets the {@link KeyPair} to be used for this account.
+ *
+ * Only the public key of the pair is sent to the server for registration. acme4j will
+ * never send the private key part.
+ *
+ * Make sure to store your key pair safely after registration! There is no automatic
+ * way to regain access to your account if the key pair is lost.
*
* @param keyPair
- * Account's {@link KeyPair}
+ * Account's {@link KeyPair}
* @return itself
*/
public AccountBuilder useKeyPair(KeyPair keyPair) {
@@ -128,13 +161,16 @@ public class AccountBuilder {
/**
* Sets a Key Identifier and MAC key provided by the CA. Use this if your CA requires
- * an individual account identification, e.g. your customer number.
+ * an individual account identification (e.g. your customer number) and a shared
+ * secret for registration. See the documentation of your CA about how to retrieve the
+ * key identifier and MAC key.
*
* @param kid
- * Key Identifier
+ * Key Identifier
* @param macKey
- * MAC key
+ * MAC key
* @return itself
+ * @see #withKeyIdentifier(String, String)
*/
public AccountBuilder withKeyIdentifier(String kid, SecretKey macKey) {
if (kid != null && kid.isEmpty()) {
@@ -147,13 +183,20 @@ public class AccountBuilder {
/**
* Sets a Key Identifier and MAC key provided by the CA. Use this if your CA requires
- * an individual account identification, e.g. your customer number.
+ * an individual account identification (e.g. your customer number) and a shared
+ * secret for registration. See the documentation of your CA about how to retrieve the
+ * key identifier and MAC key.
+ *
+ * This is a convenience call of {@link #withKeyIdentifier(String, SecretKey)} that
+ * accepts a base64url encoded MAC key, so both parameters can be passed in as
+ * strings.
*
* @param kid
- * Key Identifier
+ * Key Identifier
* @param encodedMacKey
- * Base64url encoded MAC key. It will be decoded for your convenience.
+ * Base64url encoded MAC key.
* @return itself
+ * @see #withKeyIdentifier(String, SecretKey)
*/
public AccountBuilder withKeyIdentifier(String kid, String encodedMacKey) {
var encodedKey = AcmeUtils.base64UrlDecode(requireNonNull(encodedMacKey, "encodedMacKey"));
@@ -162,10 +205,14 @@ public class AccountBuilder {
/**
* Creates a new account.
+ *
+ * Use this method to finally create your account with the given parameters. Do not
+ * use the {@link AccountBuilder} after invoking this method.
*
* @param session
- * {@link Session} to be used for registration
+ * {@link Session} to be used for registration
* @return {@link Account} referring to the new account
+ * @see #createLogin(Session)
*/
public Account create(Session session) throws AcmeException {
return createLogin(session).getAccount();
@@ -174,10 +221,11 @@ public class AccountBuilder {
/**
* Creates a new account.
*
- * This method returns a ready to use {@link Login} for the new {@link Account}.
+ * This method is identical to {@link #create(Session)}, but returns a {@link Login}
+ * that is ready to be used.
*
* @param session
- * {@link Session} to be used for registration
+ * {@link Session} to be used for registration
* @return {@link Login} referring to the new account
*/
public Login createLogin(Session session) throws AcmeException {
diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/AcmeJsonResource.java b/acme4j-client/src/main/java/org/shredzone/acme4j/AcmeJsonResource.java
index 6823ba05..4b95264d 100644
--- a/acme4j-client/src/main/java/org/shredzone/acme4j/AcmeJsonResource.java
+++ b/acme4j-client/src/main/java/org/shredzone/acme4j/AcmeJsonResource.java
@@ -25,7 +25,9 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
- * An ACME resource that stores its state in a JSON structure.
+ * An extension of {@link AcmeResource} that also contains the current state of a resource
+ * as JSON document. If the current state is not present, this class takes care of
+ * fetching it from the server if necessary.
*/
public abstract class AcmeJsonResource extends AcmeResource {
private static final long serialVersionUID = -5060364275766082345L;
@@ -53,6 +55,9 @@ public abstract class AcmeJsonResource extends AcmeResource {
* This method can be used to read proprietary data from the resources.
*
* @return Resource data, as {@link JSON}.
+ * @throws AcmeLazyLoadingException
+ * if an {@link AcmeException} occured while fetching the current state from
+ * the server.
*/
public JSON getJSON() {
if (data == null) {
diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/AcmeResource.java b/acme4j-client/src/main/java/org/shredzone/acme4j/AcmeResource.java
index 4e320b3a..4012a34a 100644
--- a/acme4j-client/src/main/java/org/shredzone/acme4j/AcmeResource.java
+++ b/acme4j-client/src/main/java/org/shredzone/acme4j/AcmeResource.java
@@ -20,7 +20,12 @@ import java.util.Objects;
import edu.umd.cs.findbugs.annotations.Nullable;
/**
- * A generic ACME resource.
+ * This is the root class of all ACME resources (like accounts, orders, certificates).
+ * Every resource is identified by its location URL.
+ *
+ * This class also takes care for proper serialization and de-serialization of the
+ * resource. After de-serialization, the resource must be bound to a {@link Login} again,
+ * using {@link #rebind(Login)}.
*/
public abstract class AcmeResource implements Serializable {
private static final long serialVersionUID = -7930580802257379731L;
diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/Certificate.java b/acme4j-client/src/main/java/org/shredzone/acme4j/Certificate.java
index c9f33e30..c0629b5e 100644
--- a/acme4j-client/src/main/java/org/shredzone/acme4j/Certificate.java
+++ b/acme4j-client/src/main/java/org/shredzone/acme4j/Certificate.java
@@ -37,10 +37,10 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
- * Represents a certificate and its certificate chain.
+ * Represents an issued certificate and its certificate chain.
*
- * Note that a certificate is immutable once it is issued. For renewal, a new certificate
- * must be ordered.
+ * A certificate is immutable once it is issued. For renewal, a new certificate must be
+ * ordered.
*/
public class Certificate extends AcmeResource {
private static final long serialVersionUID = 7381527770159084201L;
@@ -56,12 +56,12 @@ public class Certificate extends AcmeResource {
/**
* Downloads the certificate chain.
*
- * The certificate is downloaded lazily by the other methods. So usually there is no
- * need to invoke this method, unless the download is to be enforced. If the
- * certificate has been downloaded already, nothing will happen.
+ * The certificate is downloaded lazily by the other methods. Usually there is no need
+ * to invoke this method, unless the download is to be enforced. If the certificate
+ * has been downloaded already, nothing will happen.
*
* @throws AcmeException
- * if the certificate could not be downloaded
+ * if the certificate could not be downloaded
*/
public void download() throws AcmeException {
if (certChain == null) {
@@ -125,7 +125,7 @@ public class Certificate extends AcmeResource {
/**
* Writes the certificate to the given writer. It is written in PEM format, with the
- * end-entity cert coming first, followed by the intermediate ceritificates.
+ * end-entity cert coming first, followed by the intermediate certificates.
*
* @param out
* {@link Writer} to write to. The writer is not closed after use.
@@ -154,23 +154,28 @@ public class Certificate extends AcmeResource {
* {@link RevocationReason} stating the reason of the revocation that is
* used when generating OCSP responses and CRLs. {@code null} to give no
* reason.
+ * @see #revoke(Login, X509Certificate, RevocationReason)
+ * @see #revoke(Session, KeyPair, X509Certificate, RevocationReason)
*/
public void revoke(@Nullable RevocationReason reason) throws AcmeException {
revoke(getLogin(), getCertificate(), reason);
}
/**
- * Revoke a certificate. This call is meant to be used for revoking certificates if
- * only the account's key pair and the certificate itself is available.
+ * Revoke a certificate.
+ *
+ * Use this method if the certificate's location is unknown, so you cannot regenerate
+ * a {@link Certificate} instance. This method requires a {@link Login} to your
+ * account and the issued certificate.
*
* @param login
- * {@link Login} to the account
+ * {@link Login} to the account
* @param cert
- * The {@link X509Certificate} to be revoked
+ * The {@link X509Certificate} to be revoked
* @param reason
- * {@link RevocationReason} stating the reason of the revocation that is
- * used when generating OCSP responses and CRLs. {@code null} to give no
- * reason.
+ * {@link RevocationReason} stating the reason of the revocation that is used
+ * when generating OCSP responses and CRLs. {@code null} to give no reason.
+ * @see #revoke(Session, KeyPair, X509Certificate, RevocationReason)
* @since 2.6
*/
public static void revoke(Login login, X509Certificate cert, @Nullable RevocationReason reason)
@@ -195,19 +200,22 @@ public class Certificate extends AcmeResource {
}
/**
- * Revoke a certificate. This call is meant to be used for revoking certificates if
- * the account's key pair was lost.
+ * Revoke a certificate.
+ *
+ * Use this method if the key pair of your account was lost (so you are unable to
+ * login into your account), but you still have the key pair of the affected domain
+ * and the issued certificate.
*
* @param session
- * {@link Session} connected to the ACME server
+ * {@link Session} connected to the ACME server
* @param domainKeyPair
- * Key pair the CSR was signed with
+ * Key pair the CSR was signed with
* @param cert
- * The {@link X509Certificate} to be revoked
+ * The {@link X509Certificate} to be revoked
* @param reason
- * {@link RevocationReason} stating the reason of the revocation that is
- * used when generating OCSP responses and CRLs. {@code null} to give no
- * reason.
+ * {@link RevocationReason} stating the reason of the revocation that is used
+ * when generating OCSP responses and CRLs. {@code null} to give no reason.
+ * @see #revoke(Login, X509Certificate, RevocationReason)
*/
public static void revoke(Session session, KeyPair domainKeyPair, X509Certificate cert,
@Nullable RevocationReason reason) throws AcmeException {
diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/Identifier.java b/acme4j-client/src/main/java/org/shredzone/acme4j/Identifier.java
index a372e63f..87bed6ac 100644
--- a/acme4j-client/src/main/java/org/shredzone/acme4j/Identifier.java
+++ b/acme4j-client/src/main/java/org/shredzone/acme4j/Identifier.java
@@ -31,7 +31,7 @@ import org.shredzone.acme4j.toolbox.JSONBuilder;
* The ACME protocol only defines the DNS identifier, which identifies a domain name.
* acme4j also supports IP identifiers.
*
- * CAs may define further, proprietary identifier types.
+ * CAs, and other acme4j modules, may define further, proprietary identifier types.
*
* @since 2.3
*/
diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/Login.java b/acme4j-client/src/main/java/org/shredzone/acme4j/Login.java
index e6cc5c45..d0acdb96 100644
--- a/acme4j-client/src/main/java/org/shredzone/acme4j/Login.java
+++ b/acme4j-client/src/main/java/org/shredzone/acme4j/Login.java
@@ -26,12 +26,22 @@ import org.shredzone.acme4j.exception.AcmeProtocolException;
import org.shredzone.acme4j.toolbox.JSON;
/**
- * A {@link Login} is a {@link Session} that is connected to an {@link Account} at the
- * ACME server. It contains the account's {@link KeyPair} and the {@link URL} of the
- * account.
+ * A {@link Login} into an account.
*
- * Note that {@link Login} objects are not serializable, as they contain a keypair and
- * volatile data.
+ * A login is bound to a {@link Session}. However, a {@link Session} can handle multiple
+ * logins in parallel.
+ *
+ * To create a login, you need to specify the location URI of the {@link Account}, and
+ * need to provide the {@link KeyPair} the account was created with. If the account's
+ * location URL is unknown, the account can be re-registered with the
+ * {@link AccountBuilder}, using {@link AccountBuilder#onlyExisting()} to make sure that
+ * no new account will be created. If the key pair was lost though, there is no automatic
+ * way to regain access to your account, and you have to contact your CA's support hotline
+ * for assistance.
+ *
+ * Note that {@link Login} objects are intentionally not serializable, as they contain a
+ * keypair and volatile data. On distributed systems, you can create a {@link Login} to
+ * the same account for every service instance.
*/
public class Login {
@@ -88,10 +98,11 @@ public class Login {
}
/**
- * Creates a new instance of {@link Authorization} and binds it to this login.
+ * Creates a new instance of an existing {@link Authorization} and binds it to this
+ * login.
*
* @param location
- * Location of the Authorization
+ * Location of the Authorization
* @return {@link Authorization} bound to the login
*/
public Authorization bindAuthorization(URL location) {
@@ -99,10 +110,11 @@ public class Login {
}
/**
- * Creates a new instance of {@link Certificate} and binds it to this login.
+ * Creates a new instance of an existing {@link Certificate} and binds it to this
+ * login.
*
* @param location
- * Location of the Certificate
+ * Location of the Certificate
* @return {@link Certificate} bound to the login
*/
public Certificate bindCertificate(URL location) {
@@ -110,10 +122,10 @@ public class Login {
}
/**
- * Creates a new instance of {@link Order} and binds it to this login.
+ * Creates a new instance of an existing {@link Order} and binds it to this login.
*
* @param location
- * Location URL of the order
+ * Location URL of the order
* @return {@link Order} bound to the login
*/
public Order bindOrder(URL location) {
@@ -121,12 +133,14 @@ public class Login {
}
/**
- * Creates a new instance of {@link Challenge} and binds it to this login.
+ * Creates a new instance of an existing {@link Challenge} and binds it to this
+ * login. Use this method only if the resulting challenge type is unknown.
*
* @param location
- * Location URL of the challenge
+ * Location URL of the challenge
* @return {@link Challenge} bound to the login
* @since 2.8
+ * @see #bindChallenge(URL, Class)
*/
public Challenge bindChallenge(URL location) {
try (var connect = session.connect()) {
@@ -138,7 +152,8 @@ public class Login {
}
/**
- * Creates a new instance of a challenge and binds it to this login.
+ * Creates a new instance of an existing {@link Challenge} and binds it to this
+ * login. Use this method if the resulting challenge type is known.
*
* @param location
* Location URL of the challenge
@@ -175,7 +190,8 @@ public class Login {
}
/**
- * Sets a different {@link KeyPair}.
+ * Sets a different {@link KeyPair}. The new key pair is only used locally in this
+ * instance, but is not set on server side!
*/
protected void setKeyPair(KeyPair keyPair) {
this.keyPair = Objects.requireNonNull(keyPair, "keyPair");
diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/Metadata.java b/acme4j-client/src/main/java/org/shredzone/acme4j/Metadata.java
index 323124bb..93c7cde3 100644
--- a/acme4j-client/src/main/java/org/shredzone/acme4j/Metadata.java
+++ b/acme4j-client/src/main/java/org/shredzone/acme4j/Metadata.java
@@ -25,7 +25,7 @@ import org.shredzone.acme4j.toolbox.JSON;
import org.shredzone.acme4j.toolbox.JSON.Value;
/**
- * Contains metadata related to the provider.
+ * A collection of metadata related to the CA provider.
*/
public class Metadata {
@@ -42,7 +42,7 @@ public class Metadata {
}
/**
- * Returns an {@link URI} to the current terms of service, or {@code null} if not
+ * Returns an {@link URI} of the current terms of service, or {@code null} if not
* available.
*/
@Nullable
@@ -51,7 +51,7 @@ public class Metadata {
}
/**
- * Returns an {@link URL} to a website providing more information about the ACME
+ * Returns an {@link URL} of a website providing more information about the ACME
* server. {@code null} if not available.
*/
@Nullable
@@ -79,7 +79,7 @@ public class Metadata {
}
/**
- * Returns whether the CA supports short-term auto renewal of certificates.
+ * Returns whether the CA supports short-term auto-renewal of certificates.
*
* @since 2.3
*/
@@ -89,8 +89,8 @@ public class Metadata {
/**
* Returns the minimum acceptable value for the maximum validity of a certificate
- * before auto renewal. {@code null} if the CA does not support short-term auto
- * renewal.
+ * before auto-renewal. {@code null} if the CA does not support short-term
+ * auto-renewal.
*
* @since 2.3
*/
@@ -105,7 +105,7 @@ public class Metadata {
/**
* Returns the maximum delta between auto-renewal end date and auto-renewal start
- * date. {@code null} if the CA does not support short-term auto renewal.
+ * date. {@code null} if the CA does not support short-term auto-renewal.
*
* @since 2.3
*/
diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/Order.java b/acme4j-client/src/main/java/org/shredzone/acme4j/Order.java
index c16afa12..54c00cdd 100644
--- a/acme4j-client/src/main/java/org/shredzone/acme4j/Order.java
+++ b/acme4j-client/src/main/java/org/shredzone/acme4j/Order.java
@@ -29,7 +29,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
- * Represents a certificate order.
+ * A representation of a certificate order at the CA.
*/
public class Order extends AcmeJsonResource {
private static final long serialVersionUID = 5435808648658292177L;
@@ -50,7 +50,7 @@ public class Order extends AcmeJsonResource {
}
/**
- * Returns a {@link Problem} document if the order failed.
+ * Returns a {@link Problem} document with the reason if the order has failed.
*/
@Nullable
public Problem getError() {
@@ -58,7 +58,8 @@ 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, {@code null}
+ * otherwise.
*/
@Nullable
public Instant getExpires() {
@@ -66,7 +67,7 @@ public class Order extends AcmeJsonResource {
}
/**
- * Gets the list of {@link Identifier} to be ordered.
+ * Gets a list of {@link Identifier} that are connected to this order.
*
* @since 2.3
*/
@@ -95,7 +96,8 @@ public class Order extends AcmeJsonResource {
}
/**
- * Gets the {@link Authorization} required for this order, in no specific order.
+ * Gets the {@link Authorization} that are required to fulfil this order, in no
+ * specific order.
*/
public List
* Even though the ACME protocol uses the term "finalize an order", this method is
- * called {@link #execute(byte[])} to avoid confusion with the general
+ * called {@link #execute(byte[])} to avoid confusion with the problematic
* {@link Object#finalize()} method.
*
* @param csr
- * CSR containing the parameters for the certificate being requested, in
- * DER format
+ * CSR containing the parameters for the certificate being requested, in DER
+ * format
*/
public void execute(byte[] csr) throws AcmeException {
LOG.debug("finalize");
@@ -231,7 +233,7 @@ public class Order extends AcmeJsonResource {
}
/**
- * Returns the predate period of each certificate, or {@code null}.
+ * Returns the pre-date period of each certificate, or {@code null}.
*
* @since 2.7
*/
diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/OrderBuilder.java b/acme4j-client/src/main/java/org/shredzone/acme4j/OrderBuilder.java
index 78a1d1f5..eed445c3 100644
--- a/acme4j-client/src/main/java/org/shredzone/acme4j/OrderBuilder.java
+++ b/acme4j-client/src/main/java/org/shredzone/acme4j/OrderBuilder.java
@@ -31,7 +31,9 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
- * A builder for a new {@link Order} object.
+ * Start a new certificate {@link Order}.
+ *
+ * Use {@link Account#newOrder()} to create a new {@link OrderBuilder} instance.
*/
public class OrderBuilder {
private static final Logger LOG = LoggerFactory.getLogger(OrderBuilder.class);
@@ -155,18 +157,17 @@ public class OrderBuilder {
}
/**
- * Enables short-term automatic renewal of the certificate. Must be supported by the
- * CA.
+ * Enables short-term automatic renewal of the certificate, if supported by the CA.
*
- * Automatic renewals cannot be combined with {@link #notBefore(Instant)} or {@link
- * #notAfter(Instant)}.
+ * Automatic renewals cannot be combined with {@link #notBefore(Instant)} or
+ * {@link #notAfter(Instant)}.
*
* @return itself
* @since 2.3
*/
public OrderBuilder autoRenewal() {
if (notBefore != null || notAfter != null) {
- throw new IllegalArgumentException("cannot combine notBefore/notAfter with autoRenewalOr");
+ throw new IllegalArgumentException("cannot combine notBefore/notAfter with autoRenewal");
}
this.autoRenewal = true;
return this;
@@ -249,7 +250,8 @@ public class OrderBuilder {
* order for this option to work.
*
* This option is only needed if you plan to fetch the STAR certificate via other
- * means than by using acme4j.
+ * means than by using acme4j. acme4j is fetching certificates via POST-as-GET
+ * request.
*
* Implies {@link #autoRenewal()}.
*
diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/Problem.java b/acme4j-client/src/main/java/org/shredzone/acme4j/Problem.java
index e7766ba8..457f79ba 100644
--- a/acme4j-client/src/main/java/org/shredzone/acme4j/Problem.java
+++ b/acme4j-client/src/main/java/org/shredzone/acme4j/Problem.java
@@ -27,7 +27,8 @@ import org.shredzone.acme4j.toolbox.JSON;
import org.shredzone.acme4j.toolbox.JSON.Value;
/**
- * Represents a JSON Problem.
+ * A JSON problem. It contains further, machine- and human-readable details about the
+ * reason of an error or failure.
*
* @see RFC 7807
*/
@@ -89,7 +90,7 @@ public class Problem implements Serializable {
}
/**
- * Returns an URI that identifies the specific occurence of the problem. It is always
+ * Returns a URI that identifies the specific occurence of the problem. It is always
* an absolute URI.
*/
@Nullable
@@ -131,7 +132,7 @@ public class Problem implements Serializable {
}
/**
- * Returns the problem as {@link JSON} object, to access other fields.
+ * Returns the problem as {@link JSON} object, to access other, non-standard fields.
*
* @return Problem as {@link JSON} object
*/
diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/RevocationReason.java b/acme4j-client/src/main/java/org/shredzone/acme4j/RevocationReason.java
index 399c8674..e99ed5cf 100644
--- a/acme4j-client/src/main/java/org/shredzone/acme4j/RevocationReason.java
+++ b/acme4j-client/src/main/java/org/shredzone/acme4j/RevocationReason.java
@@ -18,10 +18,10 @@ import java.util.Arrays;
import edu.umd.cs.findbugs.annotations.Nullable;
/**
- * Enumeration of revocation reasons.
+ * An enumeration of revocation reasons.
*
* @see RFC 5280 Section
- * 5.3.1
+ * 5.3.1
*/
public enum RevocationReason {
diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/Session.java b/acme4j-client/src/main/java/org/shredzone/acme4j/Session.java
index 3ffd51eb..b6a9b039 100644
--- a/acme4j-client/src/main/java/org/shredzone/acme4j/Session.java
+++ b/acme4j-client/src/main/java/org/shredzone/acme4j/Session.java
@@ -37,7 +37,12 @@ import org.shredzone.acme4j.toolbox.JSON;
import org.shredzone.acme4j.toolbox.JSON.Value;
/**
- * A session stores the ACME server URI. It also tracks communication parameters.
+ * A {@link Session} tracks the entire communication with a CA.
+ *
+ * To create a session instance, use its constructor. It requires the URI of the ACME
+ * server to connect to. This can be the location of the CA's directory (via {@code http}
+ * or {@code https} protocol), or a special URI (via {@code acme} protocol). See the
+ * documentation about valid URIs.
*/
public class Session {
@@ -59,7 +64,11 @@ public class Session {
* Creates a new {@link Session}.
*
* @param serverUri
- * URI string of the ACME server
+ * URI string of the ACME server to connect to. This is either the location of
+ * the CA's ACME directory (using {@code http} or {@code https} protocol), or
+ * a special URI (using the {@code acme} protocol).
+ * @throws IllegalArgumentException
+ * if no ACME provider was found for the server URI.
*/
public Session(String serverUri) {
this(URI.create(serverUri));
@@ -69,9 +78,11 @@ public class Session {
* Creates a new {@link Session}.
*
* @param serverUri
- * {@link URI} of the ACME server
+ * {@link URI} of the ACME server to connect to. This is either the location
+ * of the CA's ACME directory (using {@code http} or {@code https} protocol),
+ * or a special URI (using the {@code acme} protocol).
* @throws IllegalArgumentException
- * if no ACME provider was found for the server URI.
+ * if no ACME provider was found for the server URI.
*/
public Session(URI serverUri) {
this.serverUri = Objects.requireNonNull(serverUri, "serverUri");
@@ -96,7 +107,7 @@ public class Session {
/**
* Creates a new {@link Session} using the given {@link AcmeProvider}.
*
- * This constructor should only be used for testing purposes.
+ * This constructor is only to be used for testing purposes.
*
* @param serverUri
* {@link URI} of the ACME server
@@ -134,7 +145,8 @@ 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. This
+ * method is mainly for internal use.
*/
@Nullable
public String getNonce() {
@@ -142,7 +154,8 @@ public class Session {
}
/**
- * Sets the base64 encoded nonce received by the server.
+ * Sets the base64 encoded nonce received by the server. This method is mainly for
+ * internal use.
*/
public void setNonce(@Nullable String nonce) {
this.nonce = nonce;
@@ -160,8 +173,8 @@ public class Session {
/**
* Sets the locale used in this session. The locale is passed to the server as
* Accept-Language header. The server may respond with localized messages.
- * The default is the system's language. If set to {@code null}, no special language
- * is selected.
+ * The default is the system's language. If set to {@code null}, any language will be
+ * accepted.
*/
public void setLocale(@Nullable Locale locale) {
this.locale = locale;
@@ -169,7 +182,8 @@ public class Session {
}
/**
- * Gets an Accept-Language header value that matches the current locale.
+ * Gets an Accept-Language header value that matches the current locale. This method
+ * is mainly for internal use.
*
* @since 3.0.0
*/
@@ -207,7 +221,7 @@ public class Session {
/**
* Gets the {@link URL} of the given {@link Resource}. This may involve connecting to
- * the server and getting a directory. The result is cached.
+ * the server and fetching the directory. The result is cached.
*
* @param resource
* {@link Resource} to get the {@link URL} of
@@ -226,7 +240,7 @@ public class Session {
/**
* Gets the metadata of the provider's directory. This may involve connecting to the
- * server and getting a directory. The result is cached.
+ * server and fetching the directory. The result is cached.
*
* @return {@link Metadata}. May contain no data, but is never {@code null}.
*/
@@ -287,8 +301,8 @@ public class Session {
}
/**
- * Returns {@code true} if a directory is available. Should only be invoked by {@link
- * AcmeProvider} implementations.
+ * Returns {@code true} if a copy of the directory is present in a local cache. It is
+ * not evaluated if the cached copy has expired though.
*
* @return {@code true} if a directory is available.
* @since 2.10
diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/Status.java b/acme4j-client/src/main/java/org/shredzone/acme4j/Status.java
index e1c395b3..86101bde 100644
--- a/acme4j-client/src/main/java/org/shredzone/acme4j/Status.java
+++ b/acme4j-client/src/main/java/org/shredzone/acme4j/Status.java
@@ -16,7 +16,7 @@ package org.shredzone.acme4j;
import java.util.Arrays;
/**
- * Status codes of challenges and authorizations.
+ * An enumeration of status codes of challenges and authorizations.
*/
public enum Status {
diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/challenge/Challenge.java b/acme4j-client/src/main/java/org/shredzone/acme4j/challenge/Challenge.java
index 2641f123..8e3e3475 100644
--- a/acme4j-client/src/main/java/org/shredzone/acme4j/challenge/Challenge.java
+++ b/acme4j-client/src/main/java/org/shredzone/acme4j/challenge/Challenge.java
@@ -33,9 +33,9 @@ import org.slf4j.LoggerFactory;
* implementations, but it is also used if the ACME server offers a proprietary challenge
* that is unknown to acme4j.
*
- * Subclasses must override {@link Challenge#acceptable(String)} so it only accepts the
- * own type. {@link Challenge#prepareResponse(JSONBuilder)} should be overridden to put
- * all required data to the response.
+ * Subclasses must override {@link Challenge#acceptable(String)} so it only accepts its
+ * own type. {@link Challenge#prepareResponse(JSONBuilder)} can be overridden to put all
+ * required data to the challenge response.
*/
public class Challenge extends AcmeJsonResource {
private static final long serialVersionUID = 2338794776848388099L;
@@ -72,6 +72,9 @@ public class Challenge extends AcmeJsonResource {
*
* Possible values are: {@link Status#PENDING}, {@link Status#PROCESSING},
* {@link Status#VALID}, {@link Status#INVALID}.
+ *
+ * A challenge is only completed when it reaches either status {@link Status#VALID} or
+ * {@link Status#INVALID}.
*/
public Status getStatus() {
return getJSON().get(KEY_STATUS).asStatus();
@@ -98,20 +101,25 @@ public class Challenge extends AcmeJsonResource {
}
/**
- * Exports the response state, as preparation for triggering the challenge.
+ * Prepares the response message for triggering the challenge. Subclasses can add
+ * fields to the {@link JSONBuilder} as required by the challenge. Implementations of
+ * subclasses should make sure that {@link #prepareResponse(JSONBuilder)} of the
+ * superclass is invoked.
*
* @param response
- * {@link JSONBuilder} to write the response to
+ * {@link JSONBuilder} to write the response to
*/
protected void prepareResponse(JSONBuilder response) {
// Do nothing here...
}
/**
- * Checks if the type is acceptable to this challenge.
+ * Checks if the type is acceptable to this challenge. This generic class only checks
+ * if the type is not blank. Subclasses should instead check if the given type matches
+ * expected challenge type.
*
* @param type
- * Type to check
+ * Type to check
* @return {@code true} if acceptable, {@code false} if not
*/
protected boolean acceptable(String type) {
@@ -138,6 +146,16 @@ public class Challenge extends AcmeJsonResource {
* Triggers this {@link Challenge}. The ACME server is requested to validate the
* response. Note that the validation is performed asynchronously by the ACME server.
*
+ * After a challenge is triggered, it changes to {@link Status#PENDING}. As soon as
+ * validation takes place, it changes to {@link Status#PROCESSING}. After validation
+ * the status changes to {@link Status#VALID} or {@link Status#INVALID}, depending on
+ * the outcome of the validation.
+ *
+ * If the challenge requires a resource to be set on your side (e.g. a DNS record or
+ * an HTTP file), it must be reachable from public before {@link #trigger()}
+ * is invoked, and must not be taken down until the challenge has reached
+ * {@link Status#VALID} or {@link Status#INVALID}.
+ *
* If this method is invoked a second time, the ACME server is requested to retry the
* validation. This can be useful if the client state has changed, for example after a
* firewall rule has been updated.
diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/challenge/Dns01Challenge.java b/acme4j-client/src/main/java/org/shredzone/acme4j/challenge/Dns01Challenge.java
index c188d309..06ef297c 100644
--- a/acme4j-client/src/main/java/org/shredzone/acme4j/challenge/Dns01Challenge.java
+++ b/acme4j-client/src/main/java/org/shredzone/acme4j/challenge/Dns01Challenge.java
@@ -21,7 +21,8 @@ import org.shredzone.acme4j.Login;
import org.shredzone.acme4j.toolbox.JSON;
/**
- * Implements the {@value TYPE} challenge.
+ * Implements the {@value TYPE} challenge. It requires a specific DNS record for domain
+ * validation. See the acme4j documentation for a detailed explanation.
*/
public class Dns01Challenge extends TokenChallenge {
private static final long serialVersionUID = 6964687027713533075L;
@@ -68,9 +69,9 @@ public class Dns01Challenge extends TokenChallenge {
* Creates a new generic {@link Dns01Challenge} object.
*
* @param login
- * {@link Login} the resource is bound with
+ * {@link Login} the resource is bound with
* @param data
- * {@link JSON} challenge data
+ * {@link JSON} challenge data
*/
public Dns01Challenge(Login login, JSON data) {
super(login, data);
diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/challenge/Http01Challenge.java b/acme4j-client/src/main/java/org/shredzone/acme4j/challenge/Http01Challenge.java
index 675c0a37..b2d2faf6 100644
--- a/acme4j-client/src/main/java/org/shredzone/acme4j/challenge/Http01Challenge.java
+++ b/acme4j-client/src/main/java/org/shredzone/acme4j/challenge/Http01Challenge.java
@@ -17,7 +17,9 @@ import org.shredzone.acme4j.Login;
import org.shredzone.acme4j.toolbox.JSON;
/**
- * Implements the {@value TYPE} challenge.
+ * Implements the {@value TYPE} challenge. For domain validation, it requires a specific
+ * file that can be retrieved from the domain via HTTP. See the acme4j documentation for a
+ * detailed explanation.
*/
public class Http01Challenge extends TokenChallenge {
private static final long serialVersionUID = 3322211185872544605L;
diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/challenge/TlsAlpn01Challenge.java b/acme4j-client/src/main/java/org/shredzone/acme4j/challenge/TlsAlpn01Challenge.java
index 8403164d..b03d8cfe 100644
--- a/acme4j-client/src/main/java/org/shredzone/acme4j/challenge/TlsAlpn01Challenge.java
+++ b/acme4j-client/src/main/java/org/shredzone/acme4j/challenge/TlsAlpn01Challenge.java
@@ -19,7 +19,9 @@ import org.shredzone.acme4j.Login;
import org.shredzone.acme4j.toolbox.JSON;
/**
- * Implements the {@value TYPE} challenge.
+ * Implements the {@value TYPE} challenge. It requires a specific certificate that can be
+ * retrieved from the domain via HTTPS request. See the acme4j documentation for a
+ * detailed explanation.
*
* @since 2.1
*/
diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/challenge/TokenChallenge.java b/acme4j-client/src/main/java/org/shredzone/acme4j/challenge/TokenChallenge.java
index fdfd5b2d..6e66f54b 100644
--- a/acme4j-client/src/main/java/org/shredzone/acme4j/challenge/TokenChallenge.java
+++ b/acme4j-client/src/main/java/org/shredzone/acme4j/challenge/TokenChallenge.java
@@ -22,8 +22,8 @@ import org.shredzone.acme4j.toolbox.JSON;
import org.shredzone.acme4j.toolbox.JoseUtils;
/**
- * An extension of {@link Challenge} that handles challenges with a {@code token} and
- * {@code keyAuthorization}.
+ * A generic extension of {@link Challenge} that handles challenges with a {@code token}
+ * and {@code keyAuthorization}.
*/
public class TokenChallenge extends Challenge {
private static final long serialVersionUID = 1634133407432681800L;
diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/challenge/package-info.java b/acme4j-client/src/main/java/org/shredzone/acme4j/challenge/package-info.java
index 8f4a8540..a081991b 100644
--- a/acme4j-client/src/main/java/org/shredzone/acme4j/challenge/package-info.java
+++ b/acme4j-client/src/main/java/org/shredzone/acme4j/challenge/package-info.java
@@ -12,6 +12,10 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*/
+/**
+ * This package contains all standard challenges, as well as base classes for challenges
+ * that are proprietary to a CA.
+ */
@ReturnValuesAreNonnullByDefault
@DefaultAnnotationForParameters(NonNull.class)
@DefaultAnnotationForFields(NonNull.class)
diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/connector/Connection.java b/acme4j-client/src/main/java/org/shredzone/acme4j/connector/Connection.java
index 93c15875..d6b68ffc 100644
--- a/acme4j-client/src/main/java/org/shredzone/acme4j/connector/Connection.java
+++ b/acme4j-client/src/main/java/org/shredzone/acme4j/connector/Connection.java
@@ -32,6 +32,10 @@ import org.shredzone.acme4j.toolbox.JSONBuilder;
/**
* Connects to the ACME server and offers different methods for invoking the API.
+ *
+ * The actual way of communicating with the ACME server is intentionally left open.
+ * Implementations could use other means than HTTP, or could mock the communication for
+ * unit testing.
*/
public interface Connection extends AutoCloseable {
@@ -132,16 +136,14 @@ public interface Connection extends AutoCloseable {
throws AcmeException;
/**
- * Reads a server response as JSON data.
+ * Reads a server response as JSON object.
*
* @return The JSON response.
- * @throws AcmeProtocolException
- * if the JSON response was empty.
*/
JSON readJsonResponse() throws AcmeException;
/**
- * Reads a certificate and its issuers.
+ * Reads a certificate and its chain of issuers.
*
* @return List of X.509 certificate and chain that was read.
*/
@@ -193,12 +195,13 @@ public interface Connection extends AutoCloseable {
Optional
* Relative links are resolved against the last request's URL.
*
* @param relation
- * Link relation
+ * Link relation
* @return Collection of links. Empty if there was no such relation.
*/
Collection
+ * This constructor is used if there is no actual instance of the resource.
*
* @param type
* {@link AcmeResource} type to be loaded
diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/exception/AcmeNetworkException.java b/acme4j-client/src/main/java/org/shredzone/acme4j/exception/AcmeNetworkException.java
index 4b124cf8..bad5ffdc 100644
--- a/acme4j-client/src/main/java/org/shredzone/acme4j/exception/AcmeNetworkException.java
+++ b/acme4j-client/src/main/java/org/shredzone/acme4j/exception/AcmeNetworkException.java
@@ -16,8 +16,8 @@ package org.shredzone.acme4j.exception;
import java.io.IOException;
/**
- * This exception is thrown when a network error occured while communicating with the
- * server.
+ * A general network error has occured while communicating with the server (e.g. network
+ * timeout).
*/
public class AcmeNetworkException extends AcmeException {
private static final long serialVersionUID = 2054398693543329179L;
diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/exception/AcmeProtocolException.java b/acme4j-client/src/main/java/org/shredzone/acme4j/exception/AcmeProtocolException.java
index d4587104..c507767d 100644
--- a/acme4j-client/src/main/java/org/shredzone/acme4j/exception/AcmeProtocolException.java
+++ b/acme4j-client/src/main/java/org/shredzone/acme4j/exception/AcmeProtocolException.java
@@ -14,8 +14,9 @@
package org.shredzone.acme4j.exception;
/**
- * 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.
+ * A runtime exception that is thrown when the response of the server is violating the
+ * RFC, and could not be handled or parsed for that reason. It is an indicator that the CA
+ * does not fully comply with the RFC, and is usually not expected to be thrown.
*/
public class AcmeProtocolException extends RuntimeException {
private static final long serialVersionUID = 2031203835755725193L;
diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/exception/AcmeRateLimitedException.java b/acme4j-client/src/main/java/org/shredzone/acme4j/exception/AcmeRateLimitedException.java
index 7ea410d4..a79ac321 100644
--- a/acme4j-client/src/main/java/org/shredzone/acme4j/exception/AcmeRateLimitedException.java
+++ b/acme4j-client/src/main/java/org/shredzone/acme4j/exception/AcmeRateLimitedException.java
@@ -22,7 +22,9 @@ import edu.umd.cs.findbugs.annotations.Nullable;
import org.shredzone.acme4j.Problem;
/**
- * An exception that is thrown when a rate limit was exceeded.
+ * A rate limit was exceeded. If provided by the server, it also includes the earliest
+ * time at which a new attempt will be accepted, and a reference to a document that
+ * further explains the rate limit that was exceeded.
*/
public class AcmeRateLimitedException extends AcmeServerException {
private static final long serialVersionUID = 4150484059796413069L;
@@ -34,12 +36,13 @@ public class AcmeRateLimitedException extends AcmeServerException {
* Creates a new {@link AcmeRateLimitedException}.
*
* @param problem
- * {@link Problem} that caused the exception
+ * {@link Problem} that caused the exception
* @param retryAfter
- * The moment the request is expected to succeed again, may be {@code null}
- * if not known
+ * The instant of time that the request is expected to succeed again, may be
+ * {@code null} if not known
* @param documents
- * URLs pointing to documents about the rate limit that was hit
+ * URLs pointing to documents about the rate limit that was hit, may be
+ * {@code null} if not known
*/
public AcmeRateLimitedException(Problem problem, @Nullable Instant retryAfter,
@Nullable Collection
+ * For some special cases, subclasses of this exception are thrown, so they can be handled
+ * individually.
*/
public class AcmeServerException extends AcmeException {
private static final long serialVersionUID = 5971622508467042792L;
diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/exception/AcmeUnauthorizedException.java b/acme4j-client/src/main/java/org/shredzone/acme4j/exception/AcmeUnauthorizedException.java
index 11d8fec8..9221d538 100644
--- a/acme4j-client/src/main/java/org/shredzone/acme4j/exception/AcmeUnauthorizedException.java
+++ b/acme4j-client/src/main/java/org/shredzone/acme4j/exception/AcmeUnauthorizedException.java
@@ -16,8 +16,8 @@ package org.shredzone.acme4j.exception;
import org.shredzone.acme4j.Problem;
/**
- * An exception that is thrown when the client is not authorized. The details will give
- * an explanation for the reasons (e.g. "client not on a whitelist").
+ * The client is not authorized to perform the operation. The {@link Problem} document
+ * will give further details (e.g. "client IP is blocked").
*/
public class AcmeUnauthorizedException extends AcmeServerException {
private static final long serialVersionUID = 9064697508262919366L;
diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/exception/AcmeUserActionRequiredException.java b/acme4j-client/src/main/java/org/shredzone/acme4j/exception/AcmeUserActionRequiredException.java
index 7984cacd..432f5797 100644
--- a/acme4j-client/src/main/java/org/shredzone/acme4j/exception/AcmeUserActionRequiredException.java
+++ b/acme4j-client/src/main/java/org/shredzone/acme4j/exception/AcmeUserActionRequiredException.java
@@ -21,7 +21,7 @@ import edu.umd.cs.findbugs.annotations.Nullable;
import org.shredzone.acme4j.Problem;
/**
- * An exception that is thrown when the user is required to take action as indicated.
+ * The user is required to take manual action as indicated.
*
* Usually this exception is thrown when the terms of service have changed, and the CA
* requires an agreement to the new terms before proceeding.
@@ -35,9 +35,10 @@ public class AcmeUserActionRequiredException extends AcmeServerException {
* Creates a new {@link AcmeUserActionRequiredException}.
*
* @param problem
- * {@link Problem} that caused the exception
+ * {@link Problem} that caused the exception
* @param tosUri
- * {@link URI} of the terms-of-service document to accept
+ * {@link URI} of the terms-of-service document to accept, may be
+ * {@code null}
*/
public AcmeUserActionRequiredException(Problem problem, @Nullable URI tosUri) {
super(problem);
@@ -54,8 +55,8 @@ public class AcmeUserActionRequiredException extends AcmeServerException {
}
/**
- * Returns the {@link URL} of a document that gives instructions on the actions to
- * be taken by a human.
+ * Returns the {@link URL} of a document that gives instructions on the actions to be
+ * taken by a human.
*/
public URL getInstance() {
var instance = getProblem().getInstance();
diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/exception/package-info.java b/acme4j-client/src/main/java/org/shredzone/acme4j/exception/package-info.java
index 24479702..3abcfa54 100644
--- a/acme4j-client/src/main/java/org/shredzone/acme4j/exception/package-info.java
+++ b/acme4j-client/src/main/java/org/shredzone/acme4j/exception/package-info.java
@@ -12,6 +12,16 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*/
+/**
+ * This package contains all exceptions that can be thrown by acme4j.
+ *
+ * {@link org.shredzone.acme4j.exception.AcmeException} is the root exception, and other
+ * exceptions are derived from it.
+ *
+ * Some methods that do lazy-loading of remote resources may throw a runtime
+ * {@link org.shredzone.acme4j.exception.AcmeLazyLoadingException} instead, so the API is
+ * not polluted with checked exceptions on every getter.
+ */
@ReturnValuesAreNonnullByDefault
@DefaultAnnotationForParameters(NonNull.class)
@DefaultAnnotationForFields(NonNull.class)
diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/package-info.java b/acme4j-client/src/main/java/org/shredzone/acme4j/package-info.java
index aac2d503..c9f1037d 100644
--- a/acme4j-client/src/main/java/org/shredzone/acme4j/package-info.java
+++ b/acme4j-client/src/main/java/org/shredzone/acme4j/package-info.java
@@ -12,6 +12,11 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*/
+/**
+ * acme4j is a Java client for the ACME protocol.
+ *
+ * See the documentation and the example for how to use this client in your own projects.
+ */
@ReturnValuesAreNonnullByDefault
@DefaultAnnotationForParameters(NonNull.class)
@DefaultAnnotationForFields(NonNull.class)
diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/provider/AbstractAcmeProvider.java b/acme4j-client/src/main/java/org/shredzone/acme4j/provider/AbstractAcmeProvider.java
index 21af7dce..5e032917 100644
--- a/acme4j-client/src/main/java/org/shredzone/acme4j/provider/AbstractAcmeProvider.java
+++ b/acme4j-client/src/main/java/org/shredzone/acme4j/provider/AbstractAcmeProvider.java
@@ -121,7 +121,7 @@ public abstract class AbstractAcmeProvider implements AcmeProvider {
* generic {@link Challenge} or {@link TokenChallenge} instances are created.
*
* Custom provider implementations may override this method to provide challenges that
- * are unique to the provider.
+ * are proprietary to the provider.
*/
@Override
public Challenge createChallenge(Login login, JSON data) {
diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/provider/letsencrypt/package-info.java b/acme4j-client/src/main/java/org/shredzone/acme4j/provider/letsencrypt/package-info.java
index 3c09a3fc..f96c1f5f 100644
--- a/acme4j-client/src/main/java/org/shredzone/acme4j/provider/letsencrypt/package-info.java
+++ b/acme4j-client/src/main/java/org/shredzone/acme4j/provider/letsencrypt/package-info.java
@@ -12,6 +12,12 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*/
+/**
+ * This package contains the Let's Encrypt
+ * {@link org.shredzone.acme4j.provider.AcmeProvider}.
+ *
+ * @see Let's Encrypt
+ */
@ReturnValuesAreNonnullByDefault
@DefaultAnnotationForParameters(NonNull.class)
@DefaultAnnotationForFields(NonNull.class)
diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/provider/package-info.java b/acme4j-client/src/main/java/org/shredzone/acme4j/provider/package-info.java
index 2e883e96..7d35f4ec 100644
--- a/acme4j-client/src/main/java/org/shredzone/acme4j/provider/package-info.java
+++ b/acme4j-client/src/main/java/org/shredzone/acme4j/provider/package-info.java
@@ -12,6 +12,18 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*/
+/**
+ * Acme Providers are the link between acme4j and the ACME server. They know how to
+ * connect to their server, and how to set up HTTP connections.
+ *
+ * {@link org.shredzone.acme4j.provider.AcmeProvider} is the root interface.
+ * {@link org.shredzone.acme4j.provider.AbstractAcmeProvider} is an abstract
+ * implementation of the most elementary methods. Most HTTP based providers will extend
+ * from {@link org.shredzone.acme4j.provider.GenericAcmeProvider} though.
+ *
+ * Provider implementations must be registered with Java's
+ * {@link java.util.ServiceLoader}.
+ */
@ReturnValuesAreNonnullByDefault
@DefaultAnnotationForParameters(NonNull.class)
@DefaultAnnotationForFields(NonNull.class)
diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/provider/pebble/package-info.java b/acme4j-client/src/main/java/org/shredzone/acme4j/provider/pebble/package-info.java
index 28a876ed..bcada0a3 100644
--- a/acme4j-client/src/main/java/org/shredzone/acme4j/provider/pebble/package-info.java
+++ b/acme4j-client/src/main/java/org/shredzone/acme4j/provider/pebble/package-info.java
@@ -12,6 +12,12 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*/
+/**
+ * This package contains an {@link org.shredzone.acme4j.provider.AcmeProvider} for the
+ * Pebble test server.
+ *
+ * @see Pebble project page
+ */
@ReturnValuesAreNonnullByDefault
@DefaultAnnotationForParameters(NonNull.class)
@DefaultAnnotationForFields(NonNull.class)
diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/toolbox/JoseUtils.java b/acme4j-client/src/main/java/org/shredzone/acme4j/toolbox/JoseUtils.java
index 22fcf411..9fa759c2 100644
--- a/acme4j-client/src/main/java/org/shredzone/acme4j/toolbox/JoseUtils.java
+++ b/acme4j-client/src/main/java/org/shredzone/acme4j/toolbox/JoseUtils.java
@@ -33,6 +33,9 @@ import org.slf4j.LoggerFactory;
/**
* Utility class that takes care of all the JOSE stuff.
+ *
+ * Internal class, do not use in your project! The API may change anytime, in a breaking
+ * manner, and without prior notice.
*
* @since 2.7
*/
diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/toolbox/package-info.java b/acme4j-client/src/main/java/org/shredzone/acme4j/toolbox/package-info.java
index ecc4ebff..01913ad3 100644
--- a/acme4j-client/src/main/java/org/shredzone/acme4j/toolbox/package-info.java
+++ b/acme4j-client/src/main/java/org/shredzone/acme4j/toolbox/package-info.java
@@ -12,6 +12,10 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*/
+/**
+ * Internal toolbox. The API of these classes may change anytime, in a breaking manner,
+ * and without prior notice. It is better not to use them in your project.
+ */
@ReturnValuesAreNonnullByDefault
@DefaultAnnotationForParameters(NonNull.class)
@DefaultAnnotationForFields(NonNull.class)
diff --git a/acme4j-smime/src/main/java/module-info.java b/acme4j-smime/src/main/java/module-info.java
index 9a8b4c4b..df84b263 100644
--- a/acme4j-smime/src/main/java/module-info.java
+++ b/acme4j-smime/src/main/java/module-info.java
@@ -12,6 +12,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*/
+/**
+ * This module is an add-on that provides S/MIME certificate features.
+ */
module org.shredzone.acme4j.smime {
requires org.shredzone.acme4j;
requires org.shredzone.acme4j.utils;
diff --git a/acme4j-smime/src/main/java/org/shredzone/acme4j/smime/challenge/EmailReply00ChallengeProvider.java b/acme4j-smime/src/main/java/org/shredzone/acme4j/smime/challenge/EmailReply00ChallengeProvider.java
index 6750d335..b8a98dc3 100644
--- a/acme4j-smime/src/main/java/org/shredzone/acme4j/smime/challenge/EmailReply00ChallengeProvider.java
+++ b/acme4j-smime/src/main/java/org/shredzone/acme4j/smime/challenge/EmailReply00ChallengeProvider.java
@@ -20,7 +20,8 @@ import org.shredzone.acme4j.provider.ChallengeType;
import org.shredzone.acme4j.toolbox.JSON;
/**
- * Generates {@link EmailReply00Challenge}.
+ * A provider that generates {@link EmailReply00Challenge}. It is registered as Java
+ * service.
*
* @since 2.12
*/
diff --git a/acme4j-smime/src/main/java/org/shredzone/acme4j/smime/challenge/package-info.java b/acme4j-smime/src/main/java/org/shredzone/acme4j/smime/challenge/package-info.java
index 8f24e3c2..48364de6 100644
--- a/acme4j-smime/src/main/java/org/shredzone/acme4j/smime/challenge/package-info.java
+++ b/acme4j-smime/src/main/java/org/shredzone/acme4j/smime/challenge/package-info.java
@@ -12,6 +12,15 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*/
+/**
+ * This package contains the
+ * {@link org.shredzone.acme4j.smime.challenge.EmailReply00Challenge#TYPE} related acme4j
+ * {@link org.shredzone.acme4j.challenge.Challenge} implementation.
+ *
+ * The {@link org.shredzone.acme4j.smime.challenge.EmailReply00ChallengeProvider} is
+ * registered as Java service, so acme4j is able to automatically generate
+ * {@link org.shredzone.acme4j.smime.challenge.EmailReply00Challenge} instances.
+ */
@ReturnValuesAreNonnullByDefault
@DefaultAnnotationForParameters(NonNull.class)
@DefaultAnnotationForFields(NonNull.class)
diff --git a/acme4j-smime/src/main/java/org/shredzone/acme4j/smime/csr/package-info.java b/acme4j-smime/src/main/java/org/shredzone/acme4j/smime/csr/package-info.java
index 250c8e2c..05a63713 100644
--- a/acme4j-smime/src/main/java/org/shredzone/acme4j/smime/csr/package-info.java
+++ b/acme4j-smime/src/main/java/org/shredzone/acme4j/smime/csr/package-info.java
@@ -12,6 +12,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*/
+/**
+ * This package contains S/MIME CSR related utility classes.
+ */
@ReturnValuesAreNonnullByDefault
@DefaultAnnotationForParameters(NonNull.class)
@DefaultAnnotationForFields(NonNull.class)
diff --git a/acme4j-smime/src/main/java/org/shredzone/acme4j/smime/email/package-info.java b/acme4j-smime/src/main/java/org/shredzone/acme4j/smime/email/package-info.java
index e621a343..1423c167 100644
--- a/acme4j-smime/src/main/java/org/shredzone/acme4j/smime/email/package-info.java
+++ b/acme4j-smime/src/main/java/org/shredzone/acme4j/smime/email/package-info.java
@@ -12,6 +12,10 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*/
+/**
+ * This package contains classes for processing incoming validation emails, and for
+ * generating outgoing response emails.
+ */
@ReturnValuesAreNonnullByDefault
@DefaultAnnotationForParameters(NonNull.class)
@DefaultAnnotationForFields(NonNull.class)
diff --git a/acme4j-smime/src/main/java/org/shredzone/acme4j/smime/exception/AcmeInvalidMessageException.java b/acme4j-smime/src/main/java/org/shredzone/acme4j/smime/exception/AcmeInvalidMessageException.java
index 589f049d..843a6659 100644
--- a/acme4j-smime/src/main/java/org/shredzone/acme4j/smime/exception/AcmeInvalidMessageException.java
+++ b/acme4j-smime/src/main/java/org/shredzone/acme4j/smime/exception/AcmeInvalidMessageException.java
@@ -25,12 +25,12 @@ import org.bouncycastle.i18n.LocalizedException;
import org.shredzone.acme4j.exception.AcmeException;
/**
- * This exception is thrown when the challenge message is invalid.
+ * This exception is thrown when the challenge email message is invalid.
*
- * If this exception is thrown, the challenge message does not match the actual challenge,
- * and must be rejected.
+ * If this exception is thrown, the challenge message does not match the actual challenge
+ * or has other issues. It must be rejected.
*
- * Reasons may be:
+ * Reasons may be (for example):
*
- * Requires {@code Bouncy Castle}. The {@link org.bouncycastle.jce.provider.BouncyCastleProvider}
- * must also be added as security provider.
+ * Requires {@code Bouncy Castle}. The
+ * {@link org.bouncycastle.jce.provider.BouncyCastleProvider} must be added as security
+ * provider.
*/
public class CSRBuilder {
private static final String SIGNATURE_ALG = "SHA256withRSA";
diff --git a/acme4j-utils/src/main/java/org/shredzone/acme4j/util/CertificateUtils.java b/acme4j-utils/src/main/java/org/shredzone/acme4j/util/CertificateUtils.java
index a997a150..ba2d7bc2 100644
--- a/acme4j-utils/src/main/java/org/shredzone/acme4j/util/CertificateUtils.java
+++ b/acme4j-utils/src/main/java/org/shredzone/acme4j/util/CertificateUtils.java
@@ -57,7 +57,7 @@ import org.shredzone.acme4j.challenge.TlsAlpn01Challenge;
/**
* Utility class offering convenience methods for certificates.
*
- * Requires {@code Bouncy Castle}. This class is part of the {@code acme4j-utils} module.
+ * Requires {@code Bouncy Castle}.
*/
public final class CertificateUtils {
diff --git a/acme4j-utils/src/main/java/org/shredzone/acme4j/util/KeyPairUtils.java b/acme4j-utils/src/main/java/org/shredzone/acme4j/util/KeyPairUtils.java
index e90fb9dc..f8603646 100644
--- a/acme4j-utils/src/main/java/org/shredzone/acme4j/util/KeyPairUtils.java
+++ b/acme4j-utils/src/main/java/org/shredzone/acme4j/util/KeyPairUtils.java
@@ -33,7 +33,7 @@ import org.bouncycastle.openssl.jcajce.JcaPEMWriter;
/**
* Utility class offering convenience methods for {@link KeyPair}.
*
- * Requires {@code Bouncy Castle}. This class is part of the {@code acme4j-utils} module.
+ * Requires {@code Bouncy Castle}.
*/
public class KeyPairUtils {
diff --git a/acme4j-utils/src/main/java/org/shredzone/acme4j/util/package-info.java b/acme4j-utils/src/main/java/org/shredzone/acme4j/util/package-info.java
index 3b742876..6096f584 100644
--- a/acme4j-utils/src/main/java/org/shredzone/acme4j/util/package-info.java
+++ b/acme4j-utils/src/main/java/org/shredzone/acme4j/util/package-info.java
@@ -12,6 +12,10 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*/
+/**
+ * A collection of utility classes. All of them require Bouncy Castle to be added as
+ * * security provider.
+ */
@ReturnValuesAreNonnullByDefault
@DefaultAnnotationForParameters(NonNull.class)
@DefaultAnnotationForFields(NonNull.class)
+ *
*/
public class AccountBuilder {
private static final Logger LOG = LoggerFactory.getLogger(AccountBuilder.class);
@@ -48,9 +62,12 @@ public class AccountBuilder {
/**
* Add a contact URI to the list of contacts.
+ *
*