Review and extend JavaDocs

pull/140/head
Richard Körber 2023-04-29 14:48:56 +02:00
parent 41bc574f75
commit 09a72d606b
No known key found for this signature in database
GPG Key ID: AAB9FD19C78AA3E0
56 changed files with 429 additions and 182 deletions

View File

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

View File

@ -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).
* <p>
* This list is unmodifiable. Use {@link #modify()} to change the contacts.
*/
public List<URI> getContacts() {
return getJSON().get(KEY_CONTACT)
@ -110,20 +112,20 @@ public class Account extends AcmeJsonResource {
}
/**
* Returns an {@link Iterator} of all {@link Order} belonging to this {@link Account}.
* Returns an {@link Iterator} of all {@link Order} belonging to this
* {@link Account}.
* <p>
* 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<Order> getOrders() {
var ordersUrl = getJSON().get(KEY_ORDERS).optional().map(Value::asURL);
if (ordersUrl.isEmpty()) {
// Let's Encrypt does not provide this field at the moment although it's required.
// Let's Encrypt does not provide this field at the moment, although it's required.
// See https://github.com/letsencrypt/boulder/issues/3335
throw new AcmeProtocolException("This ACME server does not support getOrders()");
}
@ -209,11 +211,11 @@ public class Account extends AcmeJsonResource {
/**
* Changes the {@link KeyPair} associated with the account.
* <p>
* 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<URI> editContacts = new ArrayList<>();
@ -279,6 +281,10 @@ public class Account extends AcmeJsonResource {
/**
* Returns the list of all contact URIs for modification. Use the {@link List}
* methods to modify the contact list.
* <p>
* 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<URI> getContacts() {
return editContacts;
@ -314,8 +320,8 @@ public class Account extends AcmeJsonResource {
/**
* Adds a new Contact email to the account.
* <p>
* 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)

View File

@ -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.
* <p>
* 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.
* <p>
* Depending on the CA you register with, you might need to give additional information.
* <ul>
* <li>You might need to agree to the terms of service via
* {@link #agreeToTermsOfService()}.</li>
* <li>You might need to give at least one contact URI.</li>
* <li>You might need to provide a key identifier (e.g. your customer number) and
* a shared secret via {@link #withKeyIdentifier(String, SecretKey)}.</li>
* </ul>
*/
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.
* <p>
* 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.
* <p>
* 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.
* <p>
* 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.
* <p>
* 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.
* <p>
* Only the public key of the pair is sent to the server for registration. acme4j will
* never send the private key part.
* <p>
* 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.
* <p>
* 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.
* <p>
* 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.
* <p>
* 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 {

View File

@ -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) {

View File

@ -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.
* <p>
* 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;

View File

@ -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.
* <p>
* 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.
* <p>
* 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.
* <p>
* 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.
* <p>
* 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 {

View File

@ -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.
* <p>
* CAs may define further, proprietary identifier types.
* CAs, and other acme4j modules, may define further, proprietary identifier types.
*
* @since 2.3
*/

View File

@ -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.
* <p>
* 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.
* <p>
* 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.
* <p>
* 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");

View File

@ -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
*/

View File

@ -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<Authorization> getAuthorizations() {
var login = getLogin();
@ -148,12 +150,12 @@ public class Order extends AcmeJsonResource {
* {@link #getCertificate()}.
* <p>
* 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
*/

View File

@ -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}.
* <p>
* 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.
* <p>
* 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.
* <p>
* 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.
* <p>
* Implies {@link #autoRenewal()}.
*

View File

@ -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 <a href="https://tools.ietf.org/html/rfc7807">RFC 7807</a>
*/
@ -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
*/

View File

@ -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 <a href="https://tools.ietf.org/html/rfc5280#section-5.3.1">RFC 5280 Section
* 5.3.1</a>
* 5.3.1</a>
*/
public enum RevocationReason {

View File

@ -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.
* <p>
* 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}.
* <p>
* 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 <em>may</em> 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

View File

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

View File

@ -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.
* <p>
* 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 {
* <p>
* Possible values are: {@link Status#PENDING}, {@link Status#PROCESSING},
* {@link Status#VALID}, {@link Status#INVALID}.
* <p>
* 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.
* <p>
* 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.
* <p>
* If the challenge requires a resource to be set on your side (e.g. a DNS record or
* an HTTP file), it <em>must</em> be reachable from public before {@link #trigger()}
* is invoked, and <em>must not</em> be taken down until the challenge has reached
* {@link Status#VALID} or {@link Status#INVALID}.
* <p>
* 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.

View File

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

View File

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

View File

@ -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
*/

View File

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

View File

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

View File

@ -32,6 +32,10 @@ import org.shredzone.acme4j.toolbox.JSONBuilder;
/**
* Connects to the ACME server and offers different methods for invoking the API.
* <p>
* 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<ZonedDateTime> getExpiration();
/**
* Gets one or more relation links from the header. The result is expected to be an URL.
* Gets one or more relation links from the header. The result is expected to be a
* URL.
* <p>
* 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<URL> getLinks(String relation);

View File

@ -63,7 +63,8 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Default implementation of {@link Connection}.
* Default implementation of {@link Connection}. It communicates with the ACME server via
* HTTP, with a client that is provided by the given {@link HttpConnector}.
*/
public class DefaultConnection implements Connection {
private static final Logger LOG = LoggerFactory.getLogger(DefaultConnection.class);

View File

@ -14,7 +14,7 @@
package org.shredzone.acme4j.connector;
/**
* Enumeration of resources.
* Enumeration of standard resources, and their key name in the CA's directory.
*/
public enum Resource {
@ -32,9 +32,9 @@ public enum Resource {
}
/**
* Returns the resource path.
* Returns the key name in the directory.
*
* @return resource path
* @return key name
*/
public String path() {
return path;

View File

@ -12,6 +12,10 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*/
/**
* This package contains internal classes for connection to the CA, and for handling the
* requests and responses.
*/
@ReturnValuesAreNonnullByDefault
@DefaultAnnotationForParameters(NonNull.class)
@DefaultAnnotationForFields(NonNull.class)

View File

@ -14,7 +14,7 @@
package org.shredzone.acme4j.exception;
/**
* A generic ACME exception.
* The root class of all checked acme4j exceptions.
*/
public class AcmeException extends Exception {
private static final long serialVersionUID = -2935088954705632025L;

View File

@ -20,8 +20,10 @@ import java.net.URL;
import org.shredzone.acme4j.AcmeResource;
/**
* This runtime exception is thrown when an {@link AcmeException} occured while trying to
* lazy-load a resource from the ACME server.
* A runtime exception that is thrown when an {@link AcmeException} occured while trying
* to lazy-load a resource from the ACME server. It contains the original cause of the
* exception and a reference to the resource that could not be lazy-loaded. It is usually
* thrown by getter methods, so the API is not polluted with checked exceptions.
*/
public class AcmeLazyLoadingException extends RuntimeException {
private static final long serialVersionUID = 1000353433913721901L;
@ -43,6 +45,8 @@ public class AcmeLazyLoadingException extends RuntimeException {
/**
* Creates a new {@link AcmeLazyLoadingException}.
* <p>
* This constructor is used if there is no actual instance of the resource.
*
* @param type
* {@link AcmeResource} type to be loaded

View File

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

View File

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

View File

@ -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<URL> documents) {
@ -50,8 +53,8 @@ public class AcmeRateLimitedException extends AcmeServerException {
}
/**
* Returns the moment the request is expected to succeed again. {@code null} if this
* moment is not known.
* Returns the instant of time the request is expected to succeed again. {@code null}
* if this moment is not known.
*/
@Nullable
public Instant getRetryAfter() {

View File

@ -17,8 +17,8 @@ import java.time.Instant;
import java.util.Objects;
/**
* This exception is thrown when a server side process has not been completed yet, and the
* server returned an estimated retry date.
* A server side process has not been completed yet. The server also provides an estimate
* of when the process is expected to complete.
*/
public class AcmeRetryAfterException extends AcmeException {
private static final long serialVersionUID = 4461979121063649905L;
@ -39,7 +39,8 @@ public class AcmeRetryAfterException extends AcmeException {
}
/**
* Returns the retry-after date returned by the server.
* Returns the retry-after instant returned by the server. This is only an estimate
* of when a retry attempt might succeed.
*/
public Instant getRetryAfter() {
return retryAfter;

View File

@ -19,8 +19,11 @@ import java.util.Objects;
import org.shredzone.acme4j.Problem;
/**
* An exception that is thrown when the ACME server returned an error. It contains
* further details of the cause.
* The ACME server returned an error. The exception contains a {@link Problem} document
* containing the exact cause of the error.
* <p>
* 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;

View File

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

View File

@ -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.
* <p>
* 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();

View File

@ -12,6 +12,16 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*/
/**
* This package contains all exceptions that can be thrown by acme4j.
* <p>
* {@link org.shredzone.acme4j.exception.AcmeException} is the root exception, and other
* exceptions are derived from it.
* <p>
* 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)

View File

@ -12,6 +12,11 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*/
/**
* acme4j is a Java client for the ACME protocol.
* <p>
* See the documentation and the example for how to use this client in your own projects.
*/
@ReturnValuesAreNonnullByDefault
@DefaultAnnotationForParameters(NonNull.class)
@DefaultAnnotationForFields(NonNull.class)

View File

@ -121,7 +121,7 @@ public abstract class AbstractAcmeProvider implements AcmeProvider {
* generic {@link Challenge} or {@link TokenChallenge} instances are created.
* <p>
* 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) {

View File

@ -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 <a href="https://letsencrypt.org/">Let's Encrypt</a>
*/
@ReturnValuesAreNonnullByDefault
@DefaultAnnotationForParameters(NonNull.class)
@DefaultAnnotationForFields(NonNull.class)

View File

@ -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.
* <p>
* {@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.
* <p>
* Provider implementations must be registered with Java's
* {@link java.util.ServiceLoader}.
*/
@ReturnValuesAreNonnullByDefault
@DefaultAnnotationForParameters(NonNull.class)
@DefaultAnnotationForFields(NonNull.class)

View File

@ -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 <a href="https://github.com/letsencrypt/pebble">Pebble project page</a>
*/
@ReturnValuesAreNonnullByDefault
@DefaultAnnotationForParameters(NonNull.class)
@DefaultAnnotationForFields(NonNull.class)

View File

@ -33,6 +33,9 @@ import org.slf4j.LoggerFactory;
/**
* Utility class that takes care of all the JOSE stuff.
* <p>
* Internal class, do not use in your project! The API may change anytime, in a breaking
* manner, and without prior notice.
*
* @since 2.7
*/

View File

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

View File

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

View File

@ -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
*/

View File

@ -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.
* <p>
* 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)

View File

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

View File

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

View File

@ -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.
* <p>
* If this exception is thrown, the challenge message does not match the actual challenge,
* and <em>must</em> be rejected.
* If this exception is thrown, the challenge message does not match the actual challenge
* or has other issues. It <em>must</em> be rejected.
* <p>
* Reasons may be:
* Reasons may be (for example):
* <ul>
* <li>Unexpected sender address</li>
* <li>Bad S/MIME signature</li>

View File

@ -12,6 +12,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*/
/**
* Exceptions that are related to S/MIME signatures.
*/
@ReturnValuesAreNonnullByDefault
@DefaultAnnotationForParameters(NonNull.class)
@DefaultAnnotationForFields(NonNull.class)

View File

@ -12,6 +12,9 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*/
/**
* An acme4j extension that provides S/MIME certificate features.
*/
@ReturnValuesAreNonnullByDefault
@DefaultAnnotationForParameters(NonNull.class)
@DefaultAnnotationForFields(NonNull.class)

View File

@ -12,6 +12,14 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*/
/**
* {@link org.shredzone.acme4j.smime.wrapper.Mail} is a wrapper interface which provides
* access to all relevant headers of the validation email. Usually
* {@link org.shredzone.acme4j.smime.wrapper.SignedMailBuilder} is used for parsing the
* email and validating the signature.
* {@link org.shredzone.acme4j.smime.wrapper.SimpleMail} is a simple implementation that
* should only be used for testing purposes or after an external validation.
*/
@ReturnValuesAreNonnullByDefault
@DefaultAnnotationForParameters(NonNull.class)
@DefaultAnnotationForFields(NonNull.class)

View File

@ -12,6 +12,10 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*/
/**
* This module contains a collection of utility classes. All of them require Bouncy Castle
* to be added as security provider.
*/
module org.shredzone.acme4j.utils {
requires org.shredzone.acme4j;

View File

@ -52,8 +52,9 @@ import org.shredzone.acme4j.Identifier;
/**
* Generator for a CSR (Certificate Signing Request) suitable for ACME servers.
* <p>
* 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";

View File

@ -57,7 +57,7 @@ import org.shredzone.acme4j.challenge.TlsAlpn01Challenge;
/**
* Utility class offering convenience methods for certificates.
* <p>
* Requires {@code Bouncy Castle}. This class is part of the {@code acme4j-utils} module.
* Requires {@code Bouncy Castle}.
*/
public final class CertificateUtils {

View File

@ -33,7 +33,7 @@ import org.bouncycastle.openssl.jcajce.JcaPEMWriter;
/**
* Utility class offering convenience methods for {@link KeyPair}.
* <p>
* Requires {@code Bouncy Castle}. This class is part of the {@code acme4j-utils} module.
* Requires {@code Bouncy Castle}.
*/
public class KeyPairUtils {

View File

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