diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/connector/DefaultConnection.java b/acme4j-client/src/main/java/org/shredzone/acme4j/connector/DefaultConnection.java index 7a8016eb..dd0daaad 100644 --- a/acme4j-client/src/main/java/org/shredzone/acme4j/connector/DefaultConnection.java +++ b/acme4j-client/src/main/java/org/shredzone/acme4j/connector/DefaultConnection.java @@ -41,6 +41,7 @@ import org.jose4j.jwk.PublicJsonWebKey; import org.jose4j.jws.JsonWebSignature; import org.jose4j.lang.JoseException; import org.shredzone.acme4j.Session; +import org.shredzone.acme4j.exception.AcmeAgreementRequiredException; import org.shredzone.acme4j.exception.AcmeConflictException; import org.shredzone.acme4j.exception.AcmeException; import org.shredzone.acme4j.exception.AcmeProtocolException; @@ -347,6 +348,13 @@ public class DefaultConnection implements Connection { case ACME_ERROR_PREFIX_DEPRECATED + "unauthorized": throw new AcmeUnauthorizedException(type, detail); + case ACME_ERROR_PREFIX + "agreementRequired": + case ACME_ERROR_PREFIX_DEPRECATED + "agreementRequired": + String instance = (String) map.get("instance"); + throw new AcmeAgreementRequiredException( + type, detail, getLink("terms-of-service"), + (instance != null ? resolveRelative(instance) : null)); + case ACME_ERROR_PREFIX + "rateLimited": case ACME_ERROR_PREFIX_DEPRECATED + "rateLimited": throw new AcmeRateLimitExceededException( diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/exception/AcmeAgreementRequiredException.java b/acme4j-client/src/main/java/org/shredzone/acme4j/exception/AcmeAgreementRequiredException.java new file mode 100644 index 00000000..80477c9f --- /dev/null +++ b/acme4j-client/src/main/java/org/shredzone/acme4j/exception/AcmeAgreementRequiredException.java @@ -0,0 +1,64 @@ +/* + * acme4j - Java ACME client + * + * Copyright (C) 2016 Richard "Shred" Körber + * http://acme4j.shredzone.org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + */ +package org.shredzone.acme4j.exception; + +import java.net.URI; + +/** + * An exception that is thrown when the client needs to accept the terms of service in + * order to continue. + */ +public class AcmeAgreementRequiredException extends AcmeServerException { + private static final long serialVersionUID = 7719055447283858352L; + + private final URI agreementUri; + private final URI instance; + + /** + * Creates a new {@link AcmeAgreementRequiredException}. + * + * @param type + * System readable error type (here + * {@code "urn:ietf:params:acme:error:agreementRequired"}) + * @param detail + * Human readable error message + * @param agreementUri + * {@link URI} of the agreement document to accept + * @param instance + * {@link URI} to be visited by a human, showing instructions for how to + * agree to the terms and conditions. + */ + public AcmeAgreementRequiredException(String type, String detail, URI agreementUri, URI instance) { + super(type, detail); + this.agreementUri = agreementUri; + this.instance = instance; + } + + /** + * Returns the {@link URI} of the agreement document to accept, or {@code null} if + * the server did not provide a link to such a document. + */ + public URI getAgreementUri() { + return agreementUri; + } + + /** + * Returns the {@link URI} of a document showing a human how to agree to the terms and + * conditions, or {@code null} if the server did not provide such a link. + */ + public URI getInstance() { + return instance; + } + +}