From f38002ca06b63f190b38d7e4a150461109aa07ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Richard=20K=C3=B6rber?= Date: Tue, 18 Apr 2017 01:17:58 +0200 Subject: [PATCH] Use URL instead of URI for accessible resources --- .../org/shredzone/acme4j/AcmeResource.java | 17 +- .../org/shredzone/acme4j/Authorization.java | 6 +- .../org/shredzone/acme4j/Certificate.java | 38 ++-- .../java/org/shredzone/acme4j/Metadata.java | 7 +- .../org/shredzone/acme4j/Registration.java | 29 +-- .../shredzone/acme4j/RegistrationBuilder.java | 5 +- .../java/org/shredzone/acme4j/Session.java | 19 +- .../shredzone/acme4j/challenge/Challenge.java | 10 +- .../acme4j/connector/Connection.java | 29 +-- .../acme4j/connector/DefaultConnection.java | 61 +++--- .../acme4j/connector/HttpConnector.java | 14 +- .../acme4j/connector/ResourceIterator.java | 56 +++--- .../AcmeAgreementRequiredException.java | 11 +- .../exception/AcmeConflictException.java | 10 +- .../acme4j/provider/AcmeProvider.java | 7 +- .../acme4j/provider/GenericAcmeProvider.java | 10 +- .../letsencrypt/LetsEncryptAcmeProvider.java | 21 +- .../letsencrypt/LetsEncryptHttpConnector.java | 6 +- .../provider/pebble/PebbleAcmeProvider.java | 7 +- .../shredzone/acme4j/AcmeResourceTest.java | 4 +- .../shredzone/acme4j/AuthorizationTest.java | 34 ++-- .../org/shredzone/acme4j/CertificateTest.java | 48 ++--- .../acme4j/RegistrationBuilderTest.java | 24 +-- .../shredzone/acme4j/RegistrationTest.java | 180 ++++++++++-------- .../org/shredzone/acme4j/SessionTest.java | 35 ++-- .../acme4j/challenge/ChallengeTest.java | 43 ++--- .../connector/DefaultConnectionTest.java | 43 +++-- .../acme4j/connector/DummyConnection.java | 11 +- .../acme4j/connector/HttpConnectorTest.java | 6 +- .../connector/ResourceIteratorTest.java | 48 ++--- .../acme4j/connector/SessionProviderTest.java | 5 +- .../AcmeAgreementRequiredExceptionTest.java | 10 +- .../exception/AcmeConflictExceptionTest.java | 11 +- .../shredzone/acme4j/it/AbstractPebbleIT.java | 25 +-- .../shredzone/acme4j/it/RegistrationIT.java | 16 +- .../org/shredzone/acme4j/it/SessionIT.java | 6 +- .../provider/AbstractAcmeProviderTest.java | 18 +- .../provider/GenericAcmeProviderTest.java | 5 +- .../provider/TestableConnectionProvider.java | 9 +- .../LetsEncryptAcmeProviderTest.java | 9 +- .../LetsEncryptHttpConnectorTest.java | 9 +- .../pebble/PebbleAcmeProviderTest.java | 11 +- .../org/shredzone/acme4j/util/JSONTest.java | 6 +- .../org/shredzone/acme4j/util/TestUtils.java | 18 ++ src/site/markdown/ca/index.md | 2 +- src/site/markdown/migration.md | 8 +- src/site/markdown/provider.md | 6 +- src/site/markdown/usage/authorization.md | 10 +- src/site/markdown/usage/certificate.md | 6 +- src/site/markdown/usage/register.md | 8 +- src/site/markdown/usage/session.md | 6 +- 51 files changed, 557 insertions(+), 486 deletions(-) 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 8ec67d2f..52607cf8 100644 --- a/acme4j-client/src/main/java/org/shredzone/acme4j/AcmeResource.java +++ b/acme4j-client/src/main/java/org/shredzone/acme4j/AcmeResource.java @@ -14,9 +14,12 @@ package org.shredzone.acme4j; import java.io.Serializable; -import java.net.URI; +import java.net.URISyntaxException; +import java.net.URL; import java.util.Objects; +import org.shredzone.acme4j.exception.AcmeProtocolException; + /** * A generic ACME resource. */ @@ -24,7 +27,7 @@ public abstract class AcmeResource implements Serializable { private static final long serialVersionUID = -7930580802257379731L; private transient Session session; - private URI location; + private URL location; /** * Create a new {@link AcmeResource}. @@ -57,9 +60,13 @@ public abstract class AcmeResource implements Serializable { /** * Sets the resource's location. */ - protected void setLocation(URI location) { + protected void setLocation(URL location) { this.location = Objects.requireNonNull(location, "location"); - session.setKeyIdentifier(this.location); + try { + session.setKeyIdentifier(this.location.toURI()); + } catch (URISyntaxException ex) { + throw new AcmeProtocolException("Location cannot be used as key identifier", ex); + } } /** @@ -82,7 +89,7 @@ public abstract class AcmeResource implements Serializable { /** * Gets the resource's location. */ - public URI getLocation() { + public URL getLocation() { return location; } diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/Authorization.java b/acme4j-client/src/main/java/org/shredzone/acme4j/Authorization.java index 28634ac3..08ab0d94 100644 --- a/acme4j-client/src/main/java/org/shredzone/acme4j/Authorization.java +++ b/acme4j-client/src/main/java/org/shredzone/acme4j/Authorization.java @@ -17,7 +17,7 @@ import static java.util.stream.Collectors.toList; import static org.shredzone.acme4j.util.AcmeUtils.parseTimestamp; import java.net.HttpURLConnection; -import java.net.URI; +import java.net.URL; import java.time.Instant; import java.util.ArrayList; import java.util.Arrays; @@ -49,7 +49,7 @@ public class Authorization extends AcmeResource { private List> combinations; private boolean loaded = false; - protected Authorization(Session session, URI location) { + protected Authorization(Session session, URL location) { super(session); setLocation(location); } @@ -64,7 +64,7 @@ public class Authorization extends AcmeResource { * Location of the Authorization * @return {@link Authorization} bound to the session and location */ - public static Authorization bind(Session session, URI location) { + public static Authorization bind(Session session, URL location) { return new Authorization(session, location); } 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 ea4b7510..bab2300e 100644 --- a/acme4j-client/src/main/java/org/shredzone/acme4j/Certificate.java +++ b/acme4j-client/src/main/java/org/shredzone/acme4j/Certificate.java @@ -14,7 +14,7 @@ package org.shredzone.acme4j; import java.net.HttpURLConnection; -import java.net.URI; +import java.net.URL; import java.security.cert.CertificateEncodingException; import java.security.cert.X509Certificate; import java.util.ArrayList; @@ -37,19 +37,19 @@ public class Certificate extends AcmeResource { private static final Logger LOG = LoggerFactory.getLogger(Certificate.class); private static final int MAX_CHAIN_LENGTH = 10; - private URI chainCertUri; + private URL chainCertUrl; private X509Certificate cert = null; private X509Certificate[] chain = null; - protected Certificate(Session session, URI certUri) { + protected Certificate(Session session, URL certUrl) { super(session); - setLocation(certUri); + setLocation(certUrl); } - protected Certificate(Session session, URI certUri, URI chainUri, X509Certificate cert) { + protected Certificate(Session session, URL certUrl, URL chainUrl, X509Certificate cert) { super(session); - setLocation(certUri); - this.chainCertUri = chainUri; + setLocation(certUrl); + this.chainCertUrl = chainUrl; this.cert = cert; } @@ -62,16 +62,16 @@ public class Certificate extends AcmeResource { * Location of the Certificate * @return {@link Certificate} bound to the session and location */ - public static Certificate bind(Session session, URI location) { + public static Certificate bind(Session session, URL location) { return new Certificate(session, location); } /** - * Returns the URI of the certificate chain. {@code null} if not known or not + * Returns the URL of the certificate chain. {@code null} if not known or not * available. */ - public URI getChainLocation() { - return chainCertUri; + public URL getChainLocation() { + return chainCertUrl; } /** @@ -92,7 +92,7 @@ public class Certificate extends AcmeResource { conn.accept(HttpURLConnection.HTTP_OK, HttpURLConnection.HTTP_ACCEPTED); conn.handleRetryAfter("certificate is not available for download yet"); - chainCertUri = conn.getLink("up"); + chainCertUrl = conn.getLink("up"); cert = conn.readCertificate(); } } @@ -111,21 +111,21 @@ public class Certificate extends AcmeResource { */ public X509Certificate[] downloadChain() throws AcmeException { if (chain == null) { - if (chainCertUri == null) { + if (chainCertUrl == null) { download(); } - if (chainCertUri == null) { + if (chainCertUrl == null) { throw new AcmeProtocolException("No certificate chain provided"); } LOG.debug("downloadChain"); List certChain = new ArrayList<>(); - URI link = chainCertUri; + URL link = chainCertUrl; while (link != null && certChain.size() < MAX_CHAIN_LENGTH) { try (Connection conn = getSession().provider().connect()) { - conn.sendRequest(chainCertUri, getSession()); + conn.sendRequest(chainCertUrl, getSession()); conn.accept(HttpURLConnection.HTTP_OK); certChain.add(conn.readCertificate()); @@ -159,8 +159,8 @@ public class Certificate extends AcmeResource { */ public void revoke(RevocationReason reason) throws AcmeException { LOG.debug("revoke"); - URI resUri = getSession().resourceUri(Resource.REVOKE_CERT); - if (resUri == null) { + URL resUrl = getSession().resourceUrl(Resource.REVOKE_CERT); + if (resUrl == null) { throw new AcmeProtocolException("CA does not support certificate revocation"); } @@ -176,7 +176,7 @@ public class Certificate extends AcmeResource { claims.put("reason", reason.getReasonCode()); } - conn.sendSignedRequest(resUri, claims, getSession()); + conn.sendSignedRequest(resUrl, claims, getSession()); conn.accept(HttpURLConnection.HTTP_OK); } catch (CertificateEncodingException ex) { throw new AcmeProtocolException("Invalid certificate", ex); 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 f3d25105..46bc2cd1 100644 --- a/acme4j-client/src/main/java/org/shredzone/acme4j/Metadata.java +++ b/acme4j-client/src/main/java/org/shredzone/acme4j/Metadata.java @@ -16,6 +16,7 @@ package org.shredzone.acme4j; import static java.util.stream.Collectors.toList; import java.net.URI; +import java.net.URL; import java.util.Collection; import org.shredzone.acme4j.util.JSON; @@ -47,11 +48,11 @@ public class Metadata { } /** - * Returns an {@link URI} to a website providing more information about the ACME + * Returns an {@link URL} to a website providing more information about the ACME * server. {@code null} if not available. */ - public URI getWebsite() { - return meta.get("website").asURI(); + public URL getWebsite() { + return meta.get("website").asURL(); } /** diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/Registration.java b/acme4j-client/src/main/java/org/shredzone/acme4j/Registration.java index e6ad3342..4ebc5901 100644 --- a/acme4j-client/src/main/java/org/shredzone/acme4j/Registration.java +++ b/acme4j-client/src/main/java/org/shredzone/acme4j/Registration.java @@ -17,6 +17,7 @@ import static org.shredzone.acme4j.util.AcmeUtils.*; import java.net.HttpURLConnection; import java.net.URI; +import java.net.URL; import java.security.KeyPair; import java.security.cert.X509Certificate; import java.time.Instant; @@ -57,11 +58,11 @@ public class Registration extends AcmeResource { private final List contacts = new ArrayList<>(); private Status status; private Boolean termsOfServiceAgreed; - private URI authorizations; - private URI certificates; + private URL authorizations; + private URL certificates; private boolean loaded = false; - protected Registration(Session session, URI location) { + protected Registration(Session session, URL location) { super(session); setLocation(location); } @@ -75,7 +76,7 @@ public class Registration extends AcmeResource { * Location URI of the registration * @return {@link Registration} bound to the session and location */ - public static Registration bind(Session session, URI location) { + public static Registration bind(Session session, URL location) { return new Registration(session, location); } @@ -180,7 +181,7 @@ public class Registration extends AcmeResource { .put("type", "dns") .put("value", toAce(domain)); - conn.sendSignedRequest(getSession().resourceUri(Resource.NEW_AUTHZ), claims, getSession()); + conn.sendSignedRequest(getSession().resourceUrl(Resource.NEW_AUTHZ), claims, getSession()); conn.accept(HttpURLConnection.HTTP_CREATED); JSON json = conn.readJsonResponse(); @@ -235,7 +236,7 @@ public class Registration extends AcmeResource { claims.put("notAfter", notAfter); } - conn.sendSignedRequest(getSession().resourceUri(Resource.NEW_CERT), claims, getSession()); + conn.sendSignedRequest(getSession().resourceUrl(Resource.NEW_CERT), claims, getSession()); int rc = conn.accept(HttpURLConnection.HTTP_CREATED, HttpURLConnection.HTTP_ACCEPTED); X509Certificate cert = null; @@ -247,9 +248,9 @@ public class Registration extends AcmeResource { } } - URI chainCertUri = conn.getLink("up"); + URL chainCertUrl = conn.getLink("up"); - return new Certificate(getSession(), conn.getLocation(), chainCertUri, cert); + return new Certificate(getSession(), conn.getLocation(), chainCertUrl, cert); } } @@ -272,7 +273,7 @@ public class Registration extends AcmeResource { LOG.debug("key-change"); try (Connection conn = getSession().provider().connect()) { - URI keyChangeUri = getSession().resourceUri(Resource.KEY_CHANGE); + URL keyChangeUrl = getSession().resourceUrl(Resource.KEY_CHANGE); PublicJsonWebKey newKeyJwk = PublicJsonWebKey.Factory.newPublicJwk(newKeyPair.getPublic()); JSONBuilder payloadClaim = new JSONBuilder(); @@ -281,7 +282,7 @@ public class Registration extends AcmeResource { JsonWebSignature innerJws = new JsonWebSignature(); innerJws.setPayload(payloadClaim.toString()); - innerJws.getHeaders().setObjectHeaderValue("url", keyChangeUri); + innerJws.getHeaders().setObjectHeaderValue("url", keyChangeUrl); innerJws.getHeaders().setJwkHeaderValue("jwk", newKeyJwk); innerJws.setAlgorithmHeaderValue(keyAlgorithm(newKeyJwk)); innerJws.setKey(newKeyPair.getPrivate()); @@ -293,7 +294,7 @@ public class Registration extends AcmeResource { outerClaim.put("signature", innerJws.getEncodedSignature()); outerClaim.put("payload", innerJws.getEncodedPayload()); - conn.sendSignedRequest(keyChangeUri, outerClaim, getSession()); + conn.sendSignedRequest(keyChangeUrl, outerClaim, getSession()); conn.accept(HttpURLConnection.HTTP_OK); getSession().setKeyPair(newKeyPair); @@ -356,14 +357,14 @@ public class Registration extends AcmeResource { .forEach(contacts::add); } - this.authorizations = json.get(KEY_AUTHORIZATIONS).asURI(); - this.certificates = json.get(KEY_CERTIFICATES).asURI(); + this.authorizations = json.get(KEY_AUTHORIZATIONS).asURL(); + this.certificates = json.get(KEY_CERTIFICATES).asURL(); if (json.contains(KEY_STATUS)) { this.status = Status.parse(json.get(KEY_STATUS).asString()); } - URI location = conn.getLocation(); + URL location = conn.getLocation(); if (location != null) { setLocation(location); } diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/RegistrationBuilder.java b/acme4j-client/src/main/java/org/shredzone/acme4j/RegistrationBuilder.java index 5b562723..c470496a 100644 --- a/acme4j-client/src/main/java/org/shredzone/acme4j/RegistrationBuilder.java +++ b/acme4j-client/src/main/java/org/shredzone/acme4j/RegistrationBuilder.java @@ -15,6 +15,7 @@ package org.shredzone.acme4j; import java.net.HttpURLConnection; import java.net.URI; +import java.net.URL; import java.util.ArrayList; import java.util.List; @@ -101,10 +102,10 @@ public class RegistrationBuilder { claims.put("terms-of-service-agreed", termsOfServiceAgreed); } - conn.sendJwkSignedRequest(session.resourceUri(Resource.NEW_REG), claims, session); + conn.sendJwkSignedRequest(session.resourceUrl(Resource.NEW_REG), claims, session); conn.accept(HttpURLConnection.HTTP_CREATED); - URI location = conn.getLocation(); + URL location = conn.getLocation(); return new Registration(session, location); } 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 54d3a10a..d689f7a9 100644 --- a/acme4j-client/src/main/java/org/shredzone/acme4j/Session.java +++ b/acme4j-client/src/main/java/org/shredzone/acme4j/Session.java @@ -14,6 +14,7 @@ package org.shredzone.acme4j; import java.net.URI; +import java.net.URL; import java.security.KeyPair; import java.time.Duration; import java.time.Instant; @@ -40,7 +41,7 @@ import org.shredzone.acme4j.util.JSON; * volatile data. */ public class Session { - private final AtomicReference> resourceMap = new AtomicReference<>(); + private final AtomicReference> resourceMap = new AtomicReference<>(); private final AtomicReference metadata = new AtomicReference<>(); private final URI serverUri; private final AcmeProvider provider; @@ -190,14 +191,14 @@ public class Session { } /** - * Gets the {@link URI} of the given {@link Resource}. This may involve connecting to + * Gets the {@link URL} of the given {@link Resource}. This may involve connecting to * the server and getting a directory. The result is cached. * * @param resource - * {@link Resource} to get the {@link URI} of - * @return {@link URI}, or {@code null} if the server does not offer that resource + * {@link Resource} to get the {@link URL} of + * @return {@link URL}, or {@code null} if the server does not offer that resource */ - public URI resourceUri(Resource resource) throws AcmeException { + public URL resourceUrl(Resource resource) throws AcmeException { readDirectory(); return resourceMap.get().get(Objects.requireNonNull(resource, "resource")); } @@ -234,11 +235,11 @@ public class Session { metadata.set(new Metadata(JSON.empty())); } - Map map = new EnumMap<>(Resource.class); + Map map = new EnumMap<>(Resource.class); for (Resource res : Resource.values()) { - URI uri = directoryJson.get(res.path()).asURI(); - if (uri != null) { - map.put(res, uri); + URL url = directoryJson.get(res.path()).asURL(); + if (url != null) { + map.put(res, url); } } resourceMap.set(map); 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 37cb9356..b0d2409a 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 @@ -14,7 +14,7 @@ package org.shredzone.acme4j.challenge; import java.net.HttpURLConnection; -import java.net.URI; +import java.net.URL; import java.time.Instant; import java.util.Objects; @@ -70,7 +70,7 @@ public class Challenge extends AcmeResource { * @return {@link Challenge} bound to this session and location */ @SuppressWarnings("unchecked") - public static T bind(Session session, URI location) throws AcmeException { + public static T bind(Session session, URL location) throws AcmeException { Objects.requireNonNull(session, "session"); Objects.requireNonNull(location, "location"); @@ -103,11 +103,11 @@ public class Challenge extends AcmeResource { } /** - * Returns the location {@link URI} of the challenge. + * Returns the location {@link URL} of the challenge. */ @Override - public URI getLocation() { - return data.get(KEY_URI).asURI(); + public URL getLocation() { + return data.get(KEY_URI).asURL(); } /** 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 2b112bbb..70aea9ab 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 @@ -14,6 +14,7 @@ package org.shredzone.acme4j.connector; import java.net.URI; +import java.net.URL; import java.security.cert.X509Certificate; import java.util.Collection; @@ -39,38 +40,38 @@ public interface Connection extends AutoCloseable { /** * Sends a simple GET request. * - * @param uri - * {@link URI} to send the request to. + * @param url + * {@link URL} to send the request to. * @param session * {@link Session} instance to be used for tracking */ - void sendRequest(URI uri, Session session) throws AcmeException; + void sendRequest(URL url, Session session) throws AcmeException; /** * Sends a signed POST request. Ensures that the session has a KeyIdentifier set that * is used in the "kid" protected header. * - * @param uri - * {@link URI} to send the request to. + * @param url + * {@link URL} to send the request to. * @param claims * {@link JSONBuilder} containing claims. Must not be {@code null}. * @param session * {@link Session} instance to be used for signing and tracking */ - void sendSignedRequest(URI uri, JSONBuilder claims, Session session) throws AcmeException; + void sendSignedRequest(URL url, JSONBuilder claims, Session session) throws AcmeException; /** * Sends a signed POST request. If the session's KeyIdentifier is set, a "kid" * protected header is sent. If not, a "jwk" protected header is sent. * - * @param uri - * {@link URI} to send the request to. + * @param url + * {@link URL} to send the request to. * @param claims * {@link JSONBuilder} containing claims. Must not be {@code null}. * @param session * {@link Session} instance to be used for signing and tracking */ - void sendJwkSignedRequest(URI uri, JSONBuilder claims, Session session) throws AcmeException; + void sendJwkSignedRequest(URL url, JSONBuilder claims, Session session) throws AcmeException; /** * Checks if the HTTP response status is in the given list of acceptable HTTP states, @@ -118,12 +119,12 @@ public interface Connection extends AutoCloseable { *

* Relative links are resolved against the last request's URL. * - * @return Location {@link URI}, or {@code null} if no Location header was set + * @return Location {@link URL}, or {@code null} if no Location header was set */ - URI getLocation(); + URL getLocation(); /** - * Gets a relation link from the header. + * Gets a relation link from the header. The result is expected to be an URL. *

* Relative links are resolved against the last request's URL. If there is more than * one relation, the first one is returned. @@ -132,10 +133,10 @@ public interface Connection extends AutoCloseable { * Link relation * @return Link, or {@code null} if there was no such relation link */ - URI getLink(String relation); + URL getLink(String relation); /** - * Gets one or more relation link from the header. + * Gets one or more relation links from the header. *

* Relative links are resolved against the last request's URL. * 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 81b3c7b1..5cf33e98 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 @@ -97,9 +97,9 @@ public class DefaultConnection implements Connection { try { session.setNonce(null); - URI newNonceUri = session.resourceUri(Resource.NEW_NONCE); + URL newNonceUrl = session.resourceUrl(Resource.NEW_NONCE); - conn = httpConnector.openConnection(newNonceUri); + conn = httpConnector.openConnection(newNonceUrl); conn.setRequestMethod("HEAD"); conn.setRequestProperty(ACCEPT_LANGUAGE_HEADER, session.getLocale().toLanguageTag()); conn.connect(); @@ -123,15 +123,15 @@ public class DefaultConnection implements Connection { } @Override - public void sendRequest(URI uri, Session session) throws AcmeException { - Objects.requireNonNull(uri, "uri"); + public void sendRequest(URL url, Session session) throws AcmeException { + Objects.requireNonNull(url, "url"); Objects.requireNonNull(session, "session"); assertConnectionIsClosed(); - LOG.debug("GET {}", uri); + LOG.debug("GET {}", url); try { - conn = httpConnector.openConnection(uri); + conn = httpConnector.openConnection(url); conn.setRequestMethod("GET"); conn.setRequestProperty(ACCEPT_CHARSET_HEADER, DEFAULT_CHARSET); conn.setRequestProperty(ACCEPT_LANGUAGE_HEADER, session.getLocale().toLanguageTag()); @@ -146,17 +146,17 @@ public class DefaultConnection implements Connection { } @Override - public void sendSignedRequest(URI uri, JSONBuilder claims, Session session) throws AcmeException { + public void sendSignedRequest(URL url, JSONBuilder claims, Session session) throws AcmeException { if (session.getKeyIdentifier() == null) { throw new IllegalStateException("session has no KeyIdentifier set"); } - sendJwkSignedRequest(uri, claims, session); + sendJwkSignedRequest(url, claims, session); } @Override - public void sendJwkSignedRequest(URI uri, JSONBuilder claims, Session session) throws AcmeException { - Objects.requireNonNull(uri, "uri"); + public void sendJwkSignedRequest(URL url, JSONBuilder claims, Session session) throws AcmeException { + Objects.requireNonNull(url, "url"); Objects.requireNonNull(claims, "claims"); Objects.requireNonNull(session, "session"); assertConnectionIsClosed(); @@ -168,9 +168,9 @@ public class DefaultConnection implements Connection { resetNonce(session); } - LOG.debug("POST {} with claims: {}", uri, claims); + LOG.debug("POST {} with claims: {}", url, claims); - conn = httpConnector.openConnection(uri); + conn = httpConnector.openConnection(url); conn.setRequestMethod("POST"); conn.setRequestProperty(ACCEPT_HEADER, "application/json"); conn.setRequestProperty(ACCEPT_CHARSET_HEADER, DEFAULT_CHARSET); @@ -182,7 +182,7 @@ public class DefaultConnection implements Connection { JsonWebSignature jws = new JsonWebSignature(); jws.setPayload(claims.toString()); jws.getHeaders().setObjectHeaderValue("nonce", Base64Url.encode(session.getNonce())); - jws.getHeaders().setObjectHeaderValue("url", uri); + jws.getHeaders().setObjectHeaderValue("url", url); if (session.getKeyIdentifier() != null) { jws.getHeaders().setObjectHeaderValue("kid", session.getKeyIdentifier()); } else { @@ -317,7 +317,7 @@ public class DefaultConnection implements Connection { } @Override - public URI getLocation() { + public URL getLocation() { assertConnectionIsOpen(); String location = conn.getHeaderField(LOCATION_HEADER); @@ -326,11 +326,11 @@ public class DefaultConnection implements Connection { } LOG.debug("Location: {}", location); - return resolveRelative(location); + return toURL(resolveRelative(location)); } @Override - public URI getLink(String relation) { + public URL getLink(String relation) { Collection links = getLinks(relation); if (links == null) { return null; @@ -340,7 +340,7 @@ public class DefaultConnection implements Connection { LOG.debug("Link: {} - using the first of {}", relation, links.size()); } - return links.iterator().next(); + return toURL(links.iterator().next()); } @Override @@ -418,8 +418,8 @@ public class DefaultConnection implements Connection { if ("agreementRequired".equals(error)) { URI instance = resolveRelative(json.get("instance").asString()); - URI tos = getLink("terms-of-service"); - return new AcmeAgreementRequiredException(type, detail, tos, instance); + URI tos = getLinks("terms-of-service").stream().findFirst().orElse(null); + return new AcmeAgreementRequiredException(type, detail, tos, toURL(instance)); } if ("rateLimited".equals(error)) { @@ -465,7 +465,7 @@ public class DefaultConnection implements Connection { } /** - * Resolves a relative link against the connection's last URI. + * Resolves a relative link against the connection's last URL. * * @param link * Link to resolve. Absolute links are just converted to an URI. May be @@ -480,10 +480,27 @@ public class DefaultConnection implements Connection { assertConnectionIsOpen(); try { - return new URL(conn.getURL(), link).toURI(); - } catch (MalformedURLException | URISyntaxException ex) { + return conn.getURL().toURI().resolve(link); + } catch (URISyntaxException ex) { throw new AcmeProtocolException("Cannot resolve relative link: " + link, ex); } } + /** + * Converts {@link URI} to {@link URL}. + * + * @param uri + * {@link URI} to convert + * @return {@link URL} + * @throws AcmeProtocolException + * if the URI could not be converted to URL + */ + private static URL toURL(URI uri) { + try { + return uri.toURL(); + } catch (MalformedURLException ex) { + throw new AcmeProtocolException("Invalid URL: " + uri, ex); + } + } + } diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/connector/HttpConnector.java b/acme4j-client/src/main/java/org/shredzone/acme4j/connector/HttpConnector.java index 5e543176..ecfe6fea 100644 --- a/acme4j-client/src/main/java/org/shredzone/acme4j/connector/HttpConnector.java +++ b/acme4j-client/src/main/java/org/shredzone/acme4j/connector/HttpConnector.java @@ -16,7 +16,7 @@ package org.shredzone.acme4j.connector; import java.io.IOException; import java.io.InputStream; import java.net.HttpURLConnection; -import java.net.URI; +import java.net.URL; import java.util.Properties; import org.slf4j.LoggerFactory; @@ -59,14 +59,14 @@ public class HttpConnector { } /** - * Opens a {@link HttpURLConnection} to the given {@link URI}. + * Opens a {@link HttpURLConnection} to the given {@link URL}. * - * @param uri - * {@link URI} to connect to - * @return {@link HttpURLConnection} connected to the {@link URI} + * @param url + * {@link URL} to connect to + * @return {@link HttpURLConnection} connected to the {@link URL} */ - public HttpURLConnection openConnection(URI uri) throws IOException { - HttpURLConnection conn = (HttpURLConnection) uri.toURL().openConnection(); + public HttpURLConnection openConnection(URL url) throws IOException { + HttpURLConnection conn = (HttpURLConnection) url.openConnection(); configure(conn); return conn; } diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/connector/ResourceIterator.java b/acme4j-client/src/main/java/org/shredzone/acme4j/connector/ResourceIterator.java index 5bf80717..a7a69694 100644 --- a/acme4j-client/src/main/java/org/shredzone/acme4j/connector/ResourceIterator.java +++ b/acme4j-client/src/main/java/org/shredzone/acme4j/connector/ResourceIterator.java @@ -14,7 +14,7 @@ package org.shredzone.acme4j.connector; import java.net.HttpURLConnection; -import java.net.URI; +import java.net.URL; import java.util.ArrayDeque; import java.util.Deque; import java.util.Iterator; @@ -29,7 +29,7 @@ import org.shredzone.acme4j.exception.AcmeProtocolException; import org.shredzone.acme4j.util.JSON; /** - * An {@link Iterator} that fetches a batch of URIs from the ACME server, and generates + * An {@link Iterator} that fetches a batch of URLs from the ACME server, and generates * {@link AcmeResource} instances. * * @param @@ -39,10 +39,10 @@ public class ResourceIterator implements Iterator { private final Session session; private final String field; - private final Deque uriList = new ArrayDeque<>(); - private final BiFunction creator; + private final Deque urlList = new ArrayDeque<>(); + private final BiFunction creator; private boolean eol = false; - private URI nextUri; + private URL nextUrl; /** * Creates a new {@link ResourceIterator}. @@ -52,15 +52,15 @@ public class ResourceIterator implements Iterator { * @param field * Field name to be used in the JSON response * @param start - * URI of the first JSON array, may be {@code null} for an empty iterator + * URL of the first JSON array, may be {@code null} for an empty iterator * @param creator * Creator for an {@link AcmeResource} that is bound to the given - * {@link Session} and {@link URI}. + * {@link Session} and {@link URL}. */ - public ResourceIterator(Session session, String field, URI start, BiFunction creator) { + public ResourceIterator(Session session, String field, URL start, BiFunction creator) { this.session = Objects.requireNonNull(session, "session"); this.field = Objects.requireNonNull(field, "field"); - this.nextUri = start; + this.nextUrl = start; this.creator = Objects.requireNonNull(creator, "creator"); } @@ -68,7 +68,7 @@ public class ResourceIterator implements Iterator { * Checks if there is another object in the result. * * @throws AcmeProtocolException - * if the next batch of URIs could not be fetched from the server + * if the next batch of URLs could not be fetched from the server */ @Override public boolean hasNext() { @@ -76,32 +76,32 @@ public class ResourceIterator implements Iterator { return false; } - if (uriList.isEmpty()) { + if (urlList.isEmpty()) { fetch(); } - if (uriList.isEmpty()) { + if (urlList.isEmpty()) { eol = true; } - return !uriList.isEmpty(); + return !urlList.isEmpty(); } /** * Returns the next object of the result. * * @throws AcmeProtocolException - * if the next batch of URIs could not be fetched from the server + * if the next batch of URLs could not be fetched from the server * @throws NoSuchElementException * if there are no more entries */ @Override public T next() { - if (!eol && uriList.isEmpty()) { + if (!eol && urlList.isEmpty()) { fetch(); } - URI next = uriList.poll(); + URL next = urlList.poll(); if (next == null) { eol = true; throw new NoSuchElementException("no more " + field); @@ -119,11 +119,11 @@ public class ResourceIterator implements Iterator { } /** - * Fetches the next batch of URIs. Handles exceptions. Does nothing if there is no - * URI of the next batch. + * Fetches the next batch of URLs. Handles exceptions. Does nothing if there is no + * URL of the next batch. */ private void fetch() { - if (nextUri == null) { + if (nextUrl == null) { return; } @@ -135,31 +135,31 @@ public class ResourceIterator implements Iterator { } /** - * Reads the next batch of URIs from the server, and fills the queue with the URIs. If - * there is a "next" header, it is used for the next batch of URIs. + * Reads the next batch of URLs from the server, and fills the queue with the URLs. If + * there is a "next" header, it is used for the next batch of URLs. */ private void readAndQueue() throws AcmeException { try (Connection conn = session.provider().connect()) { - conn.sendRequest(nextUri, session); + conn.sendRequest(nextUrl, session); conn.accept(HttpURLConnection.HTTP_OK); JSON json = conn.readJsonResponse(); - fillUriList(json); + fillUrlList(json); - nextUri = conn.getLink("next"); + nextUrl = conn.getLink("next"); } } /** - * Fills the uri list with the URIs found in the desired field. + * Fills the url list with the URLs found in the desired field. * * @param json * JSON map to read from */ - private void fillUriList(JSON json) { + private void fillUrlList(JSON json) { json.get(field).asArray().stream() - .map(JSON.Value::asURI) - .forEach(uriList::add); + .map(JSON.Value::asURL) + .forEach(urlList::add); } } 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 index 80477c9f..3d7d9fe8 100644 --- a/acme4j-client/src/main/java/org/shredzone/acme4j/exception/AcmeAgreementRequiredException.java +++ b/acme4j-client/src/main/java/org/shredzone/acme4j/exception/AcmeAgreementRequiredException.java @@ -14,6 +14,7 @@ package org.shredzone.acme4j.exception; import java.net.URI; +import java.net.URL; /** * An exception that is thrown when the client needs to accept the terms of service in @@ -23,7 +24,7 @@ public class AcmeAgreementRequiredException extends AcmeServerException { private static final long serialVersionUID = 7719055447283858352L; private final URI agreementUri; - private final URI instance; + private final URL instance; /** * Creates a new {@link AcmeAgreementRequiredException}. @@ -36,10 +37,10 @@ public class AcmeAgreementRequiredException extends AcmeServerException { * @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 + * {@link URL} 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) { + public AcmeAgreementRequiredException(String type, String detail, URI agreementUri, URL instance) { super(type, detail); this.agreementUri = agreementUri; this.instance = instance; @@ -54,10 +55,10 @@ public class AcmeAgreementRequiredException extends AcmeServerException { } /** - * Returns the {@link URI} of a document showing a human how to agree to the terms and + * Returns the {@link URL} 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() { + public URL getInstance() { return instance; } diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/exception/AcmeConflictException.java b/acme4j-client/src/main/java/org/shredzone/acme4j/exception/AcmeConflictException.java index 7926bead..b276441d 100644 --- a/acme4j-client/src/main/java/org/shredzone/acme4j/exception/AcmeConflictException.java +++ b/acme4j-client/src/main/java/org/shredzone/acme4j/exception/AcmeConflictException.java @@ -13,7 +13,7 @@ */ package org.shredzone.acme4j.exception; -import java.net.URI; +import java.net.URL; import java.util.Objects; /** @@ -23,7 +23,7 @@ import java.util.Objects; public class AcmeConflictException extends AcmeException { private static final long serialVersionUID = 7454201988845449591L; - private final URI location; + private final URL location; /** * Creates a new {@link AcmeConflictException}. @@ -31,9 +31,9 @@ public class AcmeConflictException extends AcmeException { * @param msg * Details about the conflicting resource * @param location - * {@link URI} of the conflicting resource + * {@link URL} of the conflicting resource */ - public AcmeConflictException(String msg, URI location) { + public AcmeConflictException(String msg, URL location) { super(msg); this.location = Objects.requireNonNull(location, "location"); } @@ -41,7 +41,7 @@ public class AcmeConflictException extends AcmeException { /** * Location of the conflicting resource. */ - public URI getLocation() { + public URL getLocation() { return location; } diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/provider/AcmeProvider.java b/acme4j-client/src/main/java/org/shredzone/acme4j/provider/AcmeProvider.java index 529de286..78938573 100644 --- a/acme4j-client/src/main/java/org/shredzone/acme4j/provider/AcmeProvider.java +++ b/acme4j-client/src/main/java/org/shredzone/acme4j/provider/AcmeProvider.java @@ -14,6 +14,7 @@ package org.shredzone.acme4j.provider; import java.net.URI; +import java.net.URL; import java.util.ServiceLoader; import org.shredzone.acme4j.Session; @@ -41,15 +42,15 @@ public interface AcmeProvider { boolean accepts(URI serverUri); /** - * Resolves the server URI and returns the matching directory URI. + * Resolves the server URI and returns the matching directory URL. * * @param serverUri * Server {@link URI} - * @return Resolved directory {@link URI} + * @return Resolved directory {@link URL} * @throws IllegalArgumentException * if the server {@link URI} is not accepted */ - URI resolve(URI serverUri); + URL resolve(URI serverUri); /** * Creates a {@link Connection} for communication with the ACME server. diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/provider/GenericAcmeProvider.java b/acme4j-client/src/main/java/org/shredzone/acme4j/provider/GenericAcmeProvider.java index 0ce2990d..2609e639 100644 --- a/acme4j-client/src/main/java/org/shredzone/acme4j/provider/GenericAcmeProvider.java +++ b/acme4j-client/src/main/java/org/shredzone/acme4j/provider/GenericAcmeProvider.java @@ -13,7 +13,9 @@ */ package org.shredzone.acme4j.provider; +import java.net.MalformedURLException; import java.net.URI; +import java.net.URL; /** * A generic {@link AcmeProvider}. It should be working for all ACME servers complying to @@ -30,8 +32,12 @@ public class GenericAcmeProvider extends AbstractAcmeProvider { } @Override - public URI resolve(URI serverUri) { - return serverUri; + public URL resolve(URI serverUri) { + try { + return serverUri.toURL(); + } catch (MalformedURLException ex) { + throw new IllegalArgumentException("Bad generic server URI", ex); + } } } diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/provider/letsencrypt/LetsEncryptAcmeProvider.java b/acme4j-client/src/main/java/org/shredzone/acme4j/provider/letsencrypt/LetsEncryptAcmeProvider.java index 98bdeb50..7d064b00 100644 --- a/acme4j-client/src/main/java/org/shredzone/acme4j/provider/letsencrypt/LetsEncryptAcmeProvider.java +++ b/acme4j-client/src/main/java/org/shredzone/acme4j/provider/letsencrypt/LetsEncryptAcmeProvider.java @@ -13,8 +13,9 @@ */ package org.shredzone.acme4j.provider.letsencrypt; +import java.net.MalformedURLException; import java.net.URI; -import java.net.URISyntaxException; +import java.net.URL; import org.shredzone.acme4j.connector.HttpConnector; import org.shredzone.acme4j.exception.AcmeProtocolException; @@ -34,8 +35,8 @@ import org.shredzone.acme4j.provider.AcmeProvider; */ public class LetsEncryptAcmeProvider extends AbstractAcmeProvider { - private static final String V01_DIRECTORY_URI = "https://acme-v01.api.letsencrypt.org/directory"; - private static final String STAGING_DIRECTORY_URI = "https://acme-staging.api.letsencrypt.org/directory"; + private static final String V01_DIRECTORY_URL = "https://acme-v01.api.letsencrypt.org/directory"; + private static final String STAGING_DIRECTORY_URL = "https://acme-staging.api.letsencrypt.org/directory"; @Override public boolean accepts(URI serverUri) { @@ -44,21 +45,21 @@ public class LetsEncryptAcmeProvider extends AbstractAcmeProvider { } @Override - public URI resolve(URI serverUri) { + public URL resolve(URI serverUri) { String path = serverUri.getPath(); - String directoryUri; + String directoryUrl; if (path == null || "".equals(path) || "/".equals(path) || "/v01".equals(path)) { - directoryUri = V01_DIRECTORY_URI; + directoryUrl = V01_DIRECTORY_URL; } else if ("/staging".equals(path)) { - directoryUri = STAGING_DIRECTORY_URI; + directoryUrl = STAGING_DIRECTORY_URL; } else { throw new IllegalArgumentException("Unknown URI " + serverUri); } try { - return new URI(directoryUri); - } catch (URISyntaxException ex) { - throw new AcmeProtocolException(directoryUri, ex); + return new URL(directoryUrl); + } catch (MalformedURLException ex) { + throw new AcmeProtocolException(directoryUrl, ex); } } diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/provider/letsencrypt/LetsEncryptHttpConnector.java b/acme4j-client/src/main/java/org/shredzone/acme4j/provider/letsencrypt/LetsEncryptHttpConnector.java index a8972a51..262638c5 100644 --- a/acme4j-client/src/main/java/org/shredzone/acme4j/provider/letsencrypt/LetsEncryptHttpConnector.java +++ b/acme4j-client/src/main/java/org/shredzone/acme4j/provider/letsencrypt/LetsEncryptHttpConnector.java @@ -15,7 +15,7 @@ package org.shredzone.acme4j.provider.letsencrypt; import java.io.IOException; import java.net.HttpURLConnection; -import java.net.URI; +import java.net.URL; import java.security.KeyManagementException; import java.security.KeyStore; import java.security.KeyStoreException; @@ -38,8 +38,8 @@ public class LetsEncryptHttpConnector extends HttpConnector { private static SSLSocketFactory sslSocketFactory; @Override - public HttpURLConnection openConnection(URI uri) throws IOException { - HttpURLConnection conn = super.openConnection(uri); + public HttpURLConnection openConnection(URL url) throws IOException { + HttpURLConnection conn = super.openConnection(url); if (conn instanceof HttpsURLConnection) { ((HttpsURLConnection) conn).setSSLSocketFactory(createSocketFactory()); } diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/provider/pebble/PebbleAcmeProvider.java b/acme4j-client/src/main/java/org/shredzone/acme4j/provider/pebble/PebbleAcmeProvider.java index 99336d3f..b7af199d 100644 --- a/acme4j-client/src/main/java/org/shredzone/acme4j/provider/pebble/PebbleAcmeProvider.java +++ b/acme4j-client/src/main/java/org/shredzone/acme4j/provider/pebble/PebbleAcmeProvider.java @@ -15,7 +15,6 @@ package org.shredzone.acme4j.provider.pebble; import java.net.MalformedURLException; import java.net.URI; -import java.net.URISyntaxException; import java.net.URL; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -44,7 +43,7 @@ public class PebbleAcmeProvider extends AbstractAcmeProvider { } @Override - public URI resolve(URI serverUri) { + public URL resolve(URI serverUri) { try { String path = serverUri.getPath(); @@ -64,8 +63,8 @@ public class PebbleAcmeProvider extends AbstractAcmeProvider { } } - return baseUrl.toURI(); - } catch (MalformedURLException | URISyntaxException ex) { + return baseUrl; + } catch (MalformedURLException ex) { throw new IllegalArgumentException("Bad server URI " + serverUri, ex); } } diff --git a/acme4j-client/src/test/java/org/shredzone/acme4j/AcmeResourceTest.java b/acme4j-client/src/test/java/org/shredzone/acme4j/AcmeResourceTest.java index fa4155a9..dec17baf 100644 --- a/acme4j-client/src/test/java/org/shredzone/acme4j/AcmeResourceTest.java +++ b/acme4j-client/src/test/java/org/shredzone/acme4j/AcmeResourceTest.java @@ -20,7 +20,7 @@ import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; -import java.net.URI; +import java.net.URL; import org.junit.Test; import org.shredzone.acme4j.util.TestUtils; @@ -36,7 +36,7 @@ public class AcmeResourceTest { @Test public void testConstructor() throws Exception { Session session = TestUtils.session(); - URI location = new URI("http://example.com/acme/resource"); + URL location = new URL("http://example.com/acme/resource"); try { new DummyResource(null); diff --git a/acme4j-client/src/test/java/org/shredzone/acme4j/AuthorizationTest.java b/acme4j-client/src/test/java/org/shredzone/acme4j/AuthorizationTest.java index 09db84b7..b6306ab9 100644 --- a/acme4j-client/src/test/java/org/shredzone/acme4j/AuthorizationTest.java +++ b/acme4j-client/src/test/java/org/shredzone/acme4j/AuthorizationTest.java @@ -20,7 +20,7 @@ import static org.shredzone.acme4j.util.TestUtils.*; import java.io.IOException; import java.net.HttpURLConnection; -import java.net.URI; +import java.net.URL; import java.time.Duration; import java.time.Instant; import java.util.Collection; @@ -44,7 +44,7 @@ public class AuthorizationTest { private static final String SNAILMAIL_TYPE = "snail-01"; // a non-existent challenge - private URI locationUri = URI.create("http://example.com/acme/registration");; + private URL locationUrl = url("http://example.com/acme/registration"); /** * Test that {@link Authorization#findChallenge(String)} does only find standalone @@ -121,8 +121,8 @@ public class AuthorizationTest { public void testUpdate() throws Exception { TestableConnectionProvider provider = new TestableConnectionProvider() { @Override - public void sendRequest(URI uri, Session session) { - assertThat(uri, is(locationUri)); + public void sendRequest(URL url, Session session) { + assertThat(url, is(locationUrl)); } @Override @@ -150,13 +150,13 @@ public class AuthorizationTest { provider.putTestChallenge("http-01", httpChallenge); provider.putTestChallenge("dns-01", dnsChallenge); - Authorization auth = new Authorization(session, locationUri); + Authorization auth = new Authorization(session, locationUrl); auth.update(); assertThat(auth.getDomain(), is("example.org")); assertThat(auth.getStatus(), is(Status.VALID)); assertThat(auth.getExpires(), is(parseTimestamp("2016-01-02T17:12:40Z"))); - assertThat(auth.getLocation(), is(locationUri)); + assertThat(auth.getLocation(), is(locationUrl)); assertThat(auth.getChallenges(), containsInAnyOrder( (Challenge) httpChallenge, (Challenge) dnsChallenge)); @@ -179,9 +179,9 @@ public class AuthorizationTest { TestableConnectionProvider provider = new TestableConnectionProvider() { @Override - public void sendRequest(URI uri, Session session) { + public void sendRequest(URL url, Session session) { requestWasSent.set(true); - assertThat(uri, is(locationUri)); + assertThat(url, is(locationUrl)); } @Override @@ -207,7 +207,7 @@ public class AuthorizationTest { provider.putTestChallenge("http-01", new Http01Challenge(session)); provider.putTestChallenge("dns-01", new Dns01Challenge(session)); - Authorization auth = new Authorization(session, locationUri); + Authorization auth = new Authorization(session, locationUrl); // Lazy loading assertThat(requestWasSent.get(), is(false)); @@ -233,8 +233,8 @@ public class AuthorizationTest { TestableConnectionProvider provider = new TestableConnectionProvider() { @Override - public void sendRequest(URI uri, Session session) { - assertThat(uri, is(locationUri)); + public void sendRequest(URL url, Session session) { + assertThat(url, is(locationUrl)); } @Override @@ -262,7 +262,7 @@ public class AuthorizationTest { provider.putTestChallenge("http-01", httpChallenge); provider.putTestChallenge("dns-01", dnsChallenge); - Authorization auth = new Authorization(session, locationUri); + Authorization auth = new Authorization(session, locationUrl); try { auth.update(); @@ -274,7 +274,7 @@ public class AuthorizationTest { assertThat(auth.getDomain(), is("example.org")); assertThat(auth.getStatus(), is(Status.VALID)); assertThat(auth.getExpires(), is(parseTimestamp("2016-01-02T17:12:40Z"))); - assertThat(auth.getLocation(), is(locationUri)); + assertThat(auth.getLocation(), is(locationUrl)); assertThat(auth.getChallenges(), containsInAnyOrder( (Challenge) httpChallenge, (Challenge) dnsChallenge)); @@ -295,11 +295,11 @@ public class AuthorizationTest { public void testDeactivate() throws Exception { TestableConnectionProvider provider = new TestableConnectionProvider() { @Override - public void sendSignedRequest(URI uri, JSONBuilder claims, Session session) { + public void sendSignedRequest(URL url, JSONBuilder claims, Session session) { JSON json = claims.toJSON(); assertThat(json.get("resource").asString(), is("authz")); assertThat(json.get("status").asString(), is("deactivated")); - assertThat(uri, is(locationUri)); + assertThat(url, is(locationUrl)); assertThat(session, is(notNullValue())); } @@ -311,7 +311,7 @@ public class AuthorizationTest { } }; - Authorization auth = new Authorization(provider.createSession(), locationUri); + Authorization auth = new Authorization(provider.createSession(), locationUrl); auth.deactivate(); provider.close(); @@ -328,7 +328,7 @@ public class AuthorizationTest { provider.putTestChallenge(Dns01Challenge.TYPE, new Dns01Challenge(session)); provider.putTestChallenge(TlsSni02Challenge.TYPE, new TlsSni02Challenge(session)); - Authorization authorization = new Authorization(session, locationUri); + Authorization authorization = new Authorization(session, locationUrl); authorization.unmarshalAuthorization(getJsonAsObject("authorizationChallenges")); return authorization; } diff --git a/acme4j-client/src/test/java/org/shredzone/acme4j/CertificateTest.java b/acme4j-client/src/test/java/org/shredzone/acme4j/CertificateTest.java index 49e4b4a7..492a2790 100644 --- a/acme4j-client/src/test/java/org/shredzone/acme4j/CertificateTest.java +++ b/acme4j-client/src/test/java/org/shredzone/acme4j/CertificateTest.java @@ -20,7 +20,7 @@ import static uk.co.datumedge.hamcrest.json.SameJSONAs.sameJSONAs; import java.io.IOException; import java.net.HttpURLConnection; -import java.net.URI; +import java.net.URL; import java.security.cert.X509Certificate; import java.time.Duration; import java.time.Instant; @@ -38,9 +38,9 @@ import org.shredzone.acme4j.util.TestUtils; */ public class CertificateTest { - private URI resourceUri = URI.create("http://example.com/acme/resource"); - private URI locationUri = URI.create("http://example.com/acme/certificate"); - private URI chainUri = URI.create("http://example.com/acme/chain"); + private URL resourceUrl = url("http://example.com/acme/resource"); + private URL locationUrl = url("http://example.com/acme/certificate"); + private URL chainUrl = url("http://example.com/acme/chain"); /** * Test that a certificate can be downloaded. @@ -50,17 +50,17 @@ public class CertificateTest { final X509Certificate originalCert = TestUtils.createCertificate(); TestableConnectionProvider provider = new TestableConnectionProvider() { - private boolean isLocationUri; + private boolean isLocationUrl; @Override - public void sendRequest(URI uri, Session session) { - assertThat(uri, isOneOf(locationUri, chainUri)); - isLocationUri = uri.equals(locationUri); + public void sendRequest(URL url, Session session) { + assertThat(url, isOneOf(locationUrl, chainUrl)); + isLocationUrl = url.equals(locationUrl); } @Override public int accept(int... httpStatus) throws AcmeException { - if (isLocationUri) { + if (isLocationUrl) { // The leaf certificate, might be asynchronous assertThat(httpStatus, isIntArrayContainingInAnyOrder( HttpURLConnection.HTTP_OK, HttpURLConnection.HTTP_ACCEPTED)); @@ -83,18 +83,18 @@ public class CertificateTest { } @Override - public URI getLink(String relation) { + public URL getLink(String relation) { switch(relation) { - case "up": return (isLocationUri ? chainUri : null); + case "up": return (isLocationUrl ? chainUrl : null); default: return null; } } }; - Certificate cert = new Certificate(provider.createSession(), locationUri); + Certificate cert = new Certificate(provider.createSession(), locationUrl); X509Certificate downloadedCert = cert.download(); assertThat(downloadedCert, is(sameInstance(originalCert))); - assertThat(cert.getChainLocation(), is(chainUri)); + assertThat(cert.getChainLocation(), is(chainUrl)); X509Certificate[] downloadedChain = cert.downloadChain(); assertThat(downloadedChain.length, is(1)); @@ -112,8 +112,8 @@ public class CertificateTest { TestableConnectionProvider provider = new TestableConnectionProvider() { @Override - public void sendRequest(URI uri, Session session) { - assertThat(uri, is(locationUri)); + public void sendRequest(URL url, Session session) { + assertThat(url, is(locationUrl)); } @Override @@ -130,7 +130,7 @@ public class CertificateTest { } }; - Certificate cert = new Certificate(provider.createSession(), locationUri); + Certificate cert = new Certificate(provider.createSession(), locationUrl); try { cert.download(); @@ -151,8 +151,8 @@ public class CertificateTest { TestableConnectionProvider provider = new TestableConnectionProvider() { @Override - public void sendSignedRequest(URI uri, JSONBuilder claims, Session session) { - assertThat(uri, is(resourceUri)); + public void sendSignedRequest(URL url, JSONBuilder claims, Session session) { + assertThat(url, is(resourceUrl)); assertThat(claims.toString(), sameJSONAs(getJson("revokeCertificateRequest"))); assertThat(session, is(notNullValue())); } @@ -164,9 +164,9 @@ public class CertificateTest { } }; - provider.putTestResource(Resource.REVOKE_CERT, resourceUri); + provider.putTestResource(Resource.REVOKE_CERT, resourceUrl); - Certificate cert = new Certificate(provider.createSession(), locationUri, null, originalCert); + Certificate cert = new Certificate(provider.createSession(), locationUrl, null, originalCert); cert.revoke(); provider.close(); @@ -181,8 +181,8 @@ public class CertificateTest { TestableConnectionProvider provider = new TestableConnectionProvider() { @Override - public void sendSignedRequest(URI uri, JSONBuilder claims, Session session) { - assertThat(uri, is(resourceUri)); + public void sendSignedRequest(URL url, JSONBuilder claims, Session session) { + assertThat(url, is(resourceUrl)); assertThat(claims.toString(), sameJSONAs(getJson("revokeCertificateWithReasonRequest"))); assertThat(session, is(notNullValue())); } @@ -194,9 +194,9 @@ public class CertificateTest { } }; - provider.putTestResource(Resource.REVOKE_CERT, resourceUri); + provider.putTestResource(Resource.REVOKE_CERT, resourceUrl); - Certificate cert = new Certificate(provider.createSession(), locationUri, null, originalCert); + Certificate cert = new Certificate(provider.createSession(), locationUrl, null, originalCert); cert.revoke(RevocationReason.KEY_COMPROMISE); provider.close(); diff --git a/acme4j-client/src/test/java/org/shredzone/acme4j/RegistrationBuilderTest.java b/acme4j-client/src/test/java/org/shredzone/acme4j/RegistrationBuilderTest.java index 14e101d3..811e0c67 100644 --- a/acme4j-client/src/test/java/org/shredzone/acme4j/RegistrationBuilderTest.java +++ b/acme4j-client/src/test/java/org/shredzone/acme4j/RegistrationBuilderTest.java @@ -19,7 +19,7 @@ import static org.shredzone.acme4j.util.TestUtils.*; import static uk.co.datumedge.hamcrest.json.SameJSONAs.sameJSONAs; import java.net.HttpURLConnection; -import java.net.URI; +import java.net.URL; import org.junit.Test; import org.shredzone.acme4j.connector.Resource; @@ -33,8 +33,8 @@ import org.shredzone.acme4j.util.JSONBuilder; */ public class RegistrationBuilderTest { - private URI resourceUri = URI.create("http://example.com/acme/resource");; - private URI locationUri = URI.create("http://example.com/acme/registration");; + private URL resourceUrl = url("http://example.com/acme/resource"); + private URL locationUrl = url("http://example.com/acme/registration");; /** * Test if a new registration can be created. @@ -45,17 +45,17 @@ public class RegistrationBuilderTest { private boolean isUpdate; @Override - public void sendSignedRequest(URI uri, JSONBuilder claims, Session session) { + public void sendSignedRequest(URL url, JSONBuilder claims, Session session) { assertThat(session, is(notNullValue())); - assertThat(uri, is(locationUri)); + assertThat(url, is(locationUrl)); assertThat(isUpdate, is(false)); isUpdate = true; } @Override - public void sendJwkSignedRequest(URI uri, JSONBuilder claims, Session session) { + public void sendJwkSignedRequest(URL url, JSONBuilder claims, Session session) { assertThat(session, is(notNullValue())); - assertThat(uri, is(resourceUri)); + assertThat(url, is(resourceUrl)); assertThat(claims.toString(), sameJSONAs(getJson("newRegistration"))); isUpdate = false; } @@ -72,8 +72,8 @@ public class RegistrationBuilderTest { } @Override - public URI getLocation() { - return locationUri; + public URL getLocation() { + return locationUrl; } @Override @@ -83,7 +83,7 @@ public class RegistrationBuilderTest { } }; - provider.putTestResource(Resource.NEW_REG, resourceUri); + provider.putTestResource(Resource.NEW_REG, resourceUrl); RegistrationBuilder builder = new RegistrationBuilder(); builder.addContact("mailto:foo@example.com"); @@ -92,9 +92,9 @@ public class RegistrationBuilderTest { Session session = provider.createSession(); Registration registration = builder.create(session); - assertThat(registration.getLocation(), is(locationUri)); + assertThat(registration.getLocation(), is(locationUrl)); assertThat(registration.getTermsOfServiceAgreed(), is(true)); - assertThat(session.getKeyIdentifier(), is(locationUri)); + assertThat(session.getKeyIdentifier(), is(locationUrl.toURI())); try { RegistrationBuilder builder2 = new RegistrationBuilder(); diff --git a/acme4j-client/src/test/java/org/shredzone/acme4j/RegistrationTest.java b/acme4j-client/src/test/java/org/shredzone/acme4j/RegistrationTest.java index 11effc4b..b3a7e424 100644 --- a/acme4j-client/src/test/java/org/shredzone/acme4j/RegistrationTest.java +++ b/acme4j-client/src/test/java/org/shredzone/acme4j/RegistrationTest.java @@ -21,11 +21,15 @@ import static uk.co.datumedge.hamcrest.json.SameJSONAs.sameJSONAs; import java.io.IOException; import java.net.HttpURLConnection; import java.net.URI; +import java.net.URISyntaxException; +import java.net.URL; import java.security.KeyPair; import java.security.cert.X509Certificate; import java.time.Instant; import java.time.LocalDate; import java.time.ZoneId; +import java.util.Arrays; +import java.util.Collection; import java.util.Iterator; import java.util.concurrent.atomic.AtomicBoolean; @@ -51,23 +55,24 @@ import org.shredzone.acme4j.util.TestUtils; */ public class RegistrationTest { - private URI resourceUri = URI.create("http://example.com/acme/resource"); - private URI locationUri = URI.create("http://example.com/acme/registration"); + private URL resourceUrl = url("http://example.com/acme/resource"); + private URL locationUrl = url("http://example.com/acme/registration"); private URI agreementUri = URI.create("http://example.com/agreement.pdf"); - private URI chainUri = URI.create("http://example.com/acme/chain"); + private URL chainUrl = url("http://example.com/acme/chain"); /** * Test that a registration can be updated. + * @throws URISyntaxException */ @Test - public void testUpdateRegistration() throws AcmeException, IOException { + public void testUpdateRegistration() throws AcmeException, IOException, URISyntaxException { TestableConnectionProvider provider = new TestableConnectionProvider() { private JSON jsonResponse; private Integer response; @Override - public void sendSignedRequest(URI uri, JSONBuilder claims, Session session) { - assertThat(uri, is(locationUri)); + public void sendSignedRequest(URL url, JSONBuilder claims, Session session) { + assertThat(url, is(locationUrl)); assertThat(claims.toString(), sameJSONAs(getJson("updateRegistration"))); assertThat(session, is(notNullValue())); jsonResponse = getJsonAsObject("updateRegistrationResponse"); @@ -75,8 +80,8 @@ public class RegistrationTest { } @Override - public void sendRequest(URI uri, Session session) { - if (URI.create("https://example.com/acme/reg/1/authz").equals(uri)) { + public void sendRequest(URL url, Session session) { + if (url("https://example.com/acme/reg/1/authz").equals(url)) { jsonResponse = new JSONBuilder() .array("authorizations", "https://example.com/acme/auth/1") .toJSON(); @@ -84,7 +89,7 @@ public class RegistrationTest { return; } - if (URI.create("https://example.com/acme/reg/1/cert").equals(uri)) { + if (url("https://example.com/acme/reg/1/cert").equals(url)) { jsonResponse = new JSONBuilder() .array("certificates", "https://example.com/acme/cert/1") .toJSON(); @@ -107,26 +112,30 @@ public class RegistrationTest { } @Override - public URI getLocation() { - return locationUri; + public URL getLocation() { + return locationUrl; } @Override - public URI getLink(String relation) { + public URL getLink(String relation) { + return null; + } + + @Override + public Collection getLinks(String relation) { switch(relation) { - case "terms-of-service": return agreementUri; - case "next": return null; + case "terms-of-service": return Arrays.asList(agreementUri); default: return null; } } }; Session session = provider.createSession(); - Registration registration = new Registration(session, locationUri); + Registration registration = new Registration(session, locationUrl); registration.update(); - assertThat(session.getKeyIdentifier(), is(locationUri)); - assertThat(registration.getLocation(), is(locationUri)); + assertThat(session.getKeyIdentifier(), is(locationUrl.toURI())); + assertThat(registration.getLocation(), is(locationUrl)); assertThat(registration.getTermsOfServiceAgreed(), is(true)); assertThat(registration.getContacts(), hasSize(1)); assertThat(registration.getContacts().get(0), is(URI.create("mailto:foo2@example.com"))); @@ -134,14 +143,12 @@ public class RegistrationTest { Iterator authIt = registration.getAuthorizations(); assertThat(authIt, not(nullValue())); - assertThat(authIt.next().getLocation(), - is(URI.create("https://example.com/acme/auth/1"))); + assertThat(authIt.next().getLocation(), is(url("https://example.com/acme/auth/1"))); assertThat(authIt.hasNext(), is(false)); Iterator certIt = registration.getCertificates(); assertThat(certIt, not(nullValue())); - assertThat(certIt.next().getLocation(), - is(URI.create("https://example.com/acme/cert/1"))); + assertThat(certIt.next().getLocation(), is(url("https://example.com/acme/cert/1"))); assertThat(certIt.hasNext(), is(false)); provider.close(); @@ -156,9 +163,9 @@ public class RegistrationTest { TestableConnectionProvider provider = new TestableConnectionProvider() { @Override - public void sendSignedRequest(URI uri, JSONBuilder claims, Session session) { + public void sendSignedRequest(URL url, JSONBuilder claims, Session session) { requestWasSent.set(true); - assertThat(uri, is(locationUri)); + assertThat(url, is(locationUrl)); } @Override @@ -174,20 +181,25 @@ public class RegistrationTest { } @Override - public URI getLocation() { - return locationUri; + public URL getLocation() { + return locationUrl; } @Override - public URI getLink(String relation) { + public URL getLink(String relation) { + return null; + } + + @Override + public Collection getLinks(String relation) { switch(relation) { - case "terms-of-service": return agreementUri; + case "terms-of-service": return Arrays.asList(agreementUri); default: return null; } } }; - Registration registration = new Registration(provider.createSession(), locationUri); + Registration registration = new Registration(provider.createSession(), locationUrl); // Lazy loading assertThat(requestWasSent.get(), is(false)); @@ -210,8 +222,8 @@ public class RegistrationTest { public void testAuthorizeDomain() throws Exception { TestableConnectionProvider provider = new TestableConnectionProvider() { @Override - public void sendSignedRequest(URI uri, JSONBuilder claims, Session session) { - assertThat(uri, is(resourceUri)); + public void sendSignedRequest(URL url, JSONBuilder claims, Session session) { + assertThat(url, is(resourceUrl)); assertThat(claims.toString(), sameJSONAs(getJson("newAuthorizationRequest"))); assertThat(session, is(notNullValue())); } @@ -228,8 +240,8 @@ public class RegistrationTest { } @Override - public URI getLocation() { - return locationUri; + public URL getLocation() { + return locationUrl; } }; @@ -238,19 +250,19 @@ public class RegistrationTest { Http01Challenge httpChallenge = new Http01Challenge(session); Dns01Challenge dnsChallenge = new Dns01Challenge(session); - provider.putTestResource(Resource.NEW_AUTHZ, resourceUri); + provider.putTestResource(Resource.NEW_AUTHZ, resourceUrl); provider.putTestChallenge(Http01Challenge.TYPE, httpChallenge); provider.putTestChallenge(Dns01Challenge.TYPE, dnsChallenge); String domainName = "example.org"; - Registration registration = new Registration(session, locationUri); + Registration registration = new Registration(session, locationUrl); Authorization auth = registration.authorizeDomain(domainName); assertThat(auth.getDomain(), is(domainName)); assertThat(auth.getStatus(), is(Status.PENDING)); assertThat(auth.getExpires(), is(nullValue())); - assertThat(auth.getLocation(), is(locationUri)); + assertThat(auth.getLocation(), is(locationUrl)); assertThat(auth.getChallenges(), containsInAnyOrder( (Challenge) httpChallenge, (Challenge) dnsChallenge)); @@ -271,7 +283,7 @@ public class RegistrationTest { public void testAuthorizeBadDomain() throws Exception { TestableConnectionProvider provider = new TestableConnectionProvider(); Session session = provider.createSession(); - Registration registration = Registration.bind(session, locationUri); + Registration registration = Registration.bind(session, locationUrl); try { registration.authorizeDomain(null); @@ -299,13 +311,13 @@ public class RegistrationTest { TestableConnectionProvider provider = new TestableConnectionProvider() { @Override - public void sendRequest(URI uri, Session session) { + public void sendRequest(URL url, Session session) { fail("Attempted to download the certificate. Should be downloaded already!"); } @Override - public void sendSignedRequest(URI uri, JSONBuilder claims, Session session) { - assertThat(uri, is(resourceUri)); + public void sendSignedRequest(URL url, JSONBuilder claims, Session session) { + assertThat(url, is(resourceUrl)); assertThat(claims.toString(), sameJSONAs(getJson("requestCertificateRequestWithDate"))); assertThat(session, is(notNullValue())); } @@ -323,32 +335,32 @@ public class RegistrationTest { } @Override - public URI getLocation() { - return locationUri; + public URL getLocation() { + return locationUrl; } @Override - public URI getLink(String relation) { + public URL getLink(String relation) { switch(relation) { - case "up": return chainUri; + case "up": return chainUrl; default: return null; } } }; - provider.putTestResource(Resource.NEW_CERT, resourceUri); + provider.putTestResource(Resource.NEW_CERT, resourceUrl); byte[] csr = TestUtils.getResourceAsByteArray("/csr.der"); ZoneId utc = ZoneId.of("UTC"); Instant notBefore = LocalDate.of(2016, 1, 1).atStartOfDay(utc).toInstant(); Instant notAfter = LocalDate.of(2016, 1, 8).atStartOfDay(utc).toInstant(); - Registration registration = new Registration(provider.createSession(), locationUri); + Registration registration = new Registration(provider.createSession(), locationUrl); Certificate cert = registration.requestCertificate(csr, notBefore, notAfter); assertThat(cert.download(), is(originalCert)); - assertThat(cert.getLocation(), is(locationUri)); - assertThat(cert.getChainLocation(), is(chainUri)); + assertThat(cert.getLocation(), is(locationUrl)); + assertThat(cert.getChainLocation(), is(chainUrl)); provider.close(); } @@ -360,8 +372,8 @@ public class RegistrationTest { public void testRequestCertificateAsync() throws AcmeException, IOException { TestableConnectionProvider provider = new TestableConnectionProvider() { @Override - public void sendSignedRequest(URI uri, JSONBuilder claims, Session session) { - assertThat(uri, is(resourceUri)); + public void sendSignedRequest(URL url, JSONBuilder claims, Session session) { + assertThat(url, is(resourceUrl)); assertThat(claims.toString(), sameJSONAs(getJson("requestCertificateRequest"))); assertThat(session, is(notNullValue())); } @@ -374,28 +386,28 @@ public class RegistrationTest { } @Override - public URI getLink(String relation) { + public URL getLink(String relation) { switch(relation) { - case "up": return chainUri; + case "up": return chainUrl; default: return null; } } @Override - public URI getLocation() { - return locationUri; + public URL getLocation() { + return locationUrl; } }; - provider.putTestResource(Resource.NEW_CERT, resourceUri); + provider.putTestResource(Resource.NEW_CERT, resourceUrl); byte[] csr = TestUtils.getResourceAsByteArray("/csr.der"); - Registration registration = new Registration(provider.createSession(), locationUri); + Registration registration = new Registration(provider.createSession(), locationUrl); Certificate cert = registration.requestCertificate(csr); - assertThat(cert.getLocation(), is(locationUri)); - assertThat(cert.getChainLocation(), is(chainUri)); + assertThat(cert.getLocation(), is(locationUrl)); + assertThat(cert.getChainLocation(), is(chainUrl)); provider.close(); } @@ -408,8 +420,8 @@ public class RegistrationTest { public void testRequestCertificateBrokenSync() throws AcmeException, IOException { TestableConnectionProvider provider = new TestableConnectionProvider() { @Override - public void sendSignedRequest(URI uri, JSONBuilder claims, Session session) { - assertThat(uri, is(resourceUri)); + public void sendSignedRequest(URL url, JSONBuilder claims, Session session) { + assertThat(url, is(resourceUrl)); assertThat(claims.toString(), sameJSONAs(getJson("requestCertificateRequestWithDate"))); assertThat(session, is(notNullValue())); } @@ -427,31 +439,31 @@ public class RegistrationTest { } @Override - public URI getLink(String relation) { + public URL getLink(String relation) { switch(relation) { - case "up": return chainUri; + case "up": return chainUrl; default: return null; } } @Override - public URI getLocation() { - return locationUri; + public URL getLocation() { + return locationUrl; } }; - provider.putTestResource(Resource.NEW_CERT, resourceUri); + provider.putTestResource(Resource.NEW_CERT, resourceUrl); byte[] csr = TestUtils.getResourceAsByteArray("/csr.der"); ZoneId utc = ZoneId.of("UTC"); Instant notBefore = LocalDate.of(2016, 1, 1).atStartOfDay(utc).toInstant(); Instant notAfter = LocalDate.of(2016, 1, 8).atStartOfDay(utc).toInstant(); - Registration registration = new Registration(provider.createSession(), locationUri); + Registration registration = new Registration(provider.createSession(), locationUrl); Certificate cert = registration.requestCertificate(csr, notBefore, notAfter); - assertThat(cert.getLocation(), is(locationUri)); - assertThat(cert.getChainLocation(), is(chainUri)); + assertThat(cert.getLocation(), is(locationUrl)); + assertThat(cert.getChainLocation(), is(chainUrl)); provider.close(); } @@ -466,9 +478,9 @@ public class RegistrationTest { final TestableConnectionProvider provider = new TestableConnectionProvider() { @Override - public void sendSignedRequest(URI uri, JSONBuilder payload, Session session) { + public void sendSignedRequest(URL url, JSONBuilder payload, Session session) { try { - assertThat(uri, is(locationUri)); + assertThat(url, is(locationUrl)); assertThat(session, is(notNullValue())); assertThat(session.getKeyPair(), is(sameInstance(oldKeyPair))); @@ -489,7 +501,7 @@ public class RegistrationTest { StringBuilder expectedPayload = new StringBuilder(); expectedPayload.append('{'); - expectedPayload.append("\"account\":\"").append(resourceUri).append("\","); + expectedPayload.append("\"account\":\"").append(resourceUrl).append("\","); expectedPayload.append("\"newKey\":{"); expectedPayload.append("\"kty\":\"").append(TestUtils.D_KTY).append("\","); expectedPayload.append("\"e\":\"").append(TestUtils.D_E).append("\","); @@ -508,12 +520,12 @@ public class RegistrationTest { } @Override - public URI getLocation() { - return resourceUri; + public URL getLocation() { + return resourceUrl; } }; - provider.putTestResource(Resource.KEY_CHANGE, locationUri); + provider.putTestResource(Resource.KEY_CHANGE, locationUrl); Session session = new Session(new URI(TestUtils.ACME_SERVER_URI), oldKeyPair) { @Override @@ -524,7 +536,7 @@ public class RegistrationTest { assertThat(session.getKeyPair(), is(sameInstance(oldKeyPair))); - Registration registration = new Registration(session, resourceUri); + Registration registration = new Registration(session, resourceUrl); registration.changeKey(newKeyPair); assertThat(session.getKeyPair(), is(sameInstance(newKeyPair))); @@ -538,7 +550,7 @@ public class RegistrationTest { TestableConnectionProvider provider = new TestableConnectionProvider(); Session session = provider.createSession(); - Registration registration = new Registration(session, locationUri); + Registration registration = new Registration(session, locationUrl); registration.changeKey(session.getKeyPair()); provider.close(); @@ -551,11 +563,11 @@ public class RegistrationTest { public void testDeactivate() throws Exception { TestableConnectionProvider provider = new TestableConnectionProvider() { @Override - public void sendSignedRequest(URI uri, JSONBuilder claims, Session session) { + public void sendSignedRequest(URL url, JSONBuilder claims, Session session) { JSON json = claims.toJSON(); assertThat(json.get("resource").asString(), is("reg")); assertThat(json.get("status").asString(), is("deactivated")); - assertThat(uri, is(locationUri)); + assertThat(url, is(locationUrl)); assertThat(session, is(notNullValue())); } @@ -567,7 +579,7 @@ public class RegistrationTest { } }; - Registration registration = new Registration(provider.createSession(), locationUri); + Registration registration = new Registration(provider.createSession(), locationUrl); registration.deactivate(); provider.close(); @@ -580,8 +592,8 @@ public class RegistrationTest { public void testModify() throws Exception { TestableConnectionProvider provider = new TestableConnectionProvider() { @Override - public void sendSignedRequest(URI uri, JSONBuilder claims, Session session) { - assertThat(uri, is(locationUri)); + public void sendSignedRequest(URL url, JSONBuilder claims, Session session) { + assertThat(url, is(locationUrl)); assertThat(claims.toString(), sameJSONAs(getJson("modifyRegistration"))); assertThat(session, is(notNullValue())); } @@ -598,12 +610,12 @@ public class RegistrationTest { } @Override - public URI getLocation() { - return locationUri; + public URL getLocation() { + return locationUrl; } }; - Registration registration = new Registration(provider.createSession(), locationUri); + Registration registration = new Registration(provider.createSession(), locationUrl); EditableRegistration editable = registration.modify(); assertThat(editable, notNullValue()); @@ -612,7 +624,7 @@ public class RegistrationTest { editable.getContacts().add(URI.create("mailto:foo3@example.com")); editable.commit(); - assertThat(registration.getLocation(), is(locationUri)); + assertThat(registration.getLocation(), is(locationUrl)); assertThat(registration.getContacts().size(), is(2)); assertThat(registration.getContacts().get(0), is(URI.create("mailto:foo2@example.com"))); assertThat(registration.getContacts().get(1), is(URI.create("mailto:foo3@example.com"))); diff --git a/acme4j-client/src/test/java/org/shredzone/acme4j/SessionTest.java b/acme4j-client/src/test/java/org/shredzone/acme4j/SessionTest.java index 8974e40f..e5f69fa3 100644 --- a/acme4j-client/src/test/java/org/shredzone/acme4j/SessionTest.java +++ b/acme4j-client/src/test/java/org/shredzone/acme4j/SessionTest.java @@ -16,10 +16,11 @@ package org.shredzone.acme4j; import static org.hamcrest.Matchers.*; import static org.junit.Assert.*; import static org.mockito.Mockito.*; -import static org.shredzone.acme4j.util.TestUtils.getJsonAsObject; +import static org.shredzone.acme4j.util.TestUtils.*; import java.io.IOException; import java.net.URI; +import java.net.URL; import java.security.KeyPair; import java.time.Instant; @@ -210,13 +211,13 @@ public class SessionTest { }; }; - assertThat(session.resourceUri(Resource.NEW_REG), - is(URI.create("https://example.com/acme/new-reg"))); - assertThat(session.resourceUri(Resource.NEW_AUTHZ), - is(URI.create("https://example.com/acme/new-authz"))); - assertThat(session.resourceUri(Resource.NEW_CERT), - is(URI.create("https://example.com/acme/new-cert"))); - assertThat(session.resourceUri(Resource.REVOKE_CERT), + assertThat(session.resourceUrl(Resource.NEW_REG), + is(new URL("https://example.com/acme/new-reg"))); + assertThat(session.resourceUrl(Resource.NEW_AUTHZ), + is(new URL("https://example.com/acme/new-authz"))); + assertThat(session.resourceUrl(Resource.NEW_CERT), + is(new URL("https://example.com/acme/new-cert"))); + assertThat(session.resourceUrl(Resource.REVOKE_CERT), is(nullValue())); Metadata meta = session.getMetadata(); @@ -233,20 +234,20 @@ public class SessionTest { * @param session * {@link Session} to assert */ - private void assertSession(Session session) throws AcmeException { - assertThat(session.resourceUri(Resource.NEW_REG), - is(URI.create("https://example.com/acme/new-reg"))); - assertThat(session.resourceUri(Resource.NEW_AUTHZ), - is(URI.create("https://example.com/acme/new-authz"))); - assertThat(session.resourceUri(Resource.NEW_CERT), - is(URI.create("https://example.com/acme/new-cert"))); - assertThat(session.resourceUri(Resource.REVOKE_CERT), + private void assertSession(Session session) throws AcmeException, IOException { + assertThat(session.resourceUrl(Resource.NEW_REG), + is(new URL("https://example.com/acme/new-reg"))); + assertThat(session.resourceUrl(Resource.NEW_AUTHZ), + is(new URL("https://example.com/acme/new-authz"))); + assertThat(session.resourceUrl(Resource.NEW_CERT), + is(new URL("https://example.com/acme/new-cert"))); + assertThat(session.resourceUrl(Resource.REVOKE_CERT), is(nullValue())); Metadata meta = session.getMetadata(); assertThat(meta, not(nullValue())); assertThat(meta.getTermsOfService(), is(URI.create("https://example.com/acme/terms"))); - assertThat(meta.getWebsite(), is(URI.create("https://www.example.com/"))); + assertThat(meta.getWebsite(), is(url("https://www.example.com/"))); assertThat(meta.getCaaIdentities(), containsInAnyOrder("example.com")); assertThat(meta.getJSON(), is(notNullValue())); } diff --git a/acme4j-client/src/test/java/org/shredzone/acme4j/challenge/ChallengeTest.java b/acme4j-client/src/test/java/org/shredzone/acme4j/challenge/ChallengeTest.java index 68ffe4ae..e305db30 100644 --- a/acme4j-client/src/test/java/org/shredzone/acme4j/challenge/ChallengeTest.java +++ b/acme4j-client/src/test/java/org/shredzone/acme4j/challenge/ChallengeTest.java @@ -22,7 +22,6 @@ import static uk.co.datumedge.hamcrest.json.SameJSONAs.sameJSONAs; import java.io.IOException; import java.net.HttpURLConnection; import java.net.MalformedURLException; -import java.net.URI; import java.net.URISyntaxException; import java.net.URL; import java.time.Duration; @@ -46,8 +45,8 @@ import org.shredzone.acme4j.util.TestUtils; */ public class ChallengeTest { private Session session; - private URI resourceUri = URI.create("https://example.com/acme/some-resource"); - private URI locationUri = URI.create("https://example.com/acme/some-location"); + private URL resourceUrl = url("https://example.com/acme/some-resource"); + private URL locationUrl = url("https://example.com/acme/some-location"); @Before public void setup() throws IOException { @@ -61,8 +60,8 @@ public class ChallengeTest { public void testChallenge() throws Exception { TestableConnectionProvider provider = new TestableConnectionProvider() { @Override - public void sendRequest(URI uri, Session session) { - assertThat(uri, is(locationUri)); + public void sendRequest(URL url, Session session) { + assertThat(url, is(locationUrl)); } @Override @@ -82,11 +81,11 @@ public class ChallengeTest { provider.putTestChallenge(Http01Challenge.TYPE, new Http01Challenge(session)); - Http01Challenge challenge = Challenge.bind(session, locationUri); + Http01Challenge challenge = Challenge.bind(session, locationUrl); assertThat(challenge.getType(), is(Http01Challenge.TYPE)); assertThat(challenge.getStatus(), is(Status.VALID)); - assertThat(challenge.getLocation(), is(locationUri)); + assertThat(challenge.getLocation(), is(locationUrl)); assertThat(challenge.getToken(), is("IlirfxKKXAsHtmzK29Pj8A")); provider.close(); @@ -111,7 +110,7 @@ public class ChallengeTest { // Test unmarshalled values assertThat(challenge.getType(), is("generic-01")); assertThat(challenge.getStatus(), is(Status.VALID)); - assertThat(challenge.getLocation(), is(new URI("http://example.com/challenge/123"))); + assertThat(challenge.getLocation(), is(url("http://example.com/challenge/123"))); assertThat(challenge.getValidated(), is(parseTimestamp("2015-12-12T17:19:36.336785823Z"))); assertThat(challenge.getJSON().get("type").asString(), is("generic-01")); assertThat(challenge.getJSON().get("uri").asURL(), is(new URL("http://example.com/challenge/123"))); @@ -151,8 +150,8 @@ public class ChallengeTest { public void testTrigger() throws Exception { TestableConnectionProvider provider = new TestableConnectionProvider() { @Override - public void sendSignedRequest(URI uri, JSONBuilder claims, Session session) { - assertThat(uri, is(resourceUri)); + public void sendSignedRequest(URL url, JSONBuilder claims, Session session) { + assertThat(url, is(resourceUrl)); assertThat(claims.toString(), sameJSONAs(getJson("triggerHttpChallengeRequest"))); assertThat(session, is(notNullValue())); } @@ -178,7 +177,7 @@ public class ChallengeTest { challenge.trigger(); assertThat(challenge.getStatus(), is(Status.PENDING)); - assertThat(challenge.getLocation(), is(locationUri)); + assertThat(challenge.getLocation(), is(locationUrl)); provider.close(); } @@ -190,8 +189,8 @@ public class ChallengeTest { public void testUpdate() throws Exception { TestableConnectionProvider provider = new TestableConnectionProvider() { @Override - public void sendRequest(URI uri, Session session) { - assertThat(uri, is(locationUri)); + public void sendRequest(URL url, Session session) { + assertThat(url, is(locationUrl)); } @Override @@ -220,7 +219,7 @@ public class ChallengeTest { challenge.update(); assertThat(challenge.getStatus(), is(Status.VALID)); - assertThat(challenge.getLocation(), is(locationUri)); + assertThat(challenge.getLocation(), is(locationUrl)); provider.close(); } @@ -234,8 +233,8 @@ public class ChallengeTest { TestableConnectionProvider provider = new TestableConnectionProvider() { @Override - public void sendRequest(URI uri, Session session) { - assertThat(uri, is(locationUri)); + public void sendRequest(URL url, Session session) { + assertThat(url, is(locationUrl)); } @Override @@ -270,7 +269,7 @@ public class ChallengeTest { } assertThat(challenge.getStatus(), is(Status.VALID)); - assertThat(challenge.getLocation(), is(locationUri)); + assertThat(challenge.getLocation(), is(locationUrl)); provider.close(); } @@ -288,7 +287,7 @@ public class ChallengeTest { } try { - Challenge.bind(null, locationUri); + Challenge.bind(null, locationUrl); fail("session accepts null"); } catch (NullPointerException ex) { // expected @@ -296,14 +295,14 @@ public class ChallengeTest { } /** - * Test that an exception is thrown on a bad location URI. + * Test that an exception is thrown on a bad location URL. */ @Test(expected = IllegalArgumentException.class) public void testBadBind() throws Exception { TestableConnectionProvider provider = new TestableConnectionProvider() { @Override - public void sendRequest(URI uri, Session session) { - assertThat(uri, is(locationUri)); + public void sendRequest(URL url, Session session) { + assertThat(url, is(locationUrl)); } @Override @@ -320,7 +319,7 @@ public class ChallengeTest { }; Session session = provider.createSession(); - Challenge.bind(session, locationUri); + Challenge.bind(session, locationUrl); provider.close(); } diff --git a/acme4j-client/src/test/java/org/shredzone/acme4j/connector/DefaultConnectionTest.java b/acme4j-client/src/test/java/org/shredzone/acme4j/connector/DefaultConnectionTest.java index 2981a4bd..78d60b6d 100644 --- a/acme4j-client/src/test/java/org/shredzone/acme4j/connector/DefaultConnectionTest.java +++ b/acme4j-client/src/test/java/org/shredzone/acme4j/connector/DefaultConnectionTest.java @@ -56,7 +56,7 @@ import org.shredzone.acme4j.util.TestUtils; */ public class DefaultConnectionTest { - private URI requestUri = URI.create("http://example.com/acme/"); + private URL requestUrl = TestUtils.url("http://example.com/acme/"); private URI keyIdentifierUri = URI.create(TestUtils.ACME_SERVER_URI + "/acct/1"); private HttpURLConnection mockUrlConnection; private HttpConnector mockHttpConnection; @@ -67,7 +67,7 @@ public class DefaultConnectionTest { mockUrlConnection = mock(HttpURLConnection.class); mockHttpConnection = mock(HttpConnector.class); - when(mockHttpConnection.openConnection(requestUri)).thenReturn(mockUrlConnection); + when(mockHttpConnection.openConnection(requestUrl)).thenReturn(mockUrlConnection); final AcmeProvider mockProvider = mock(AcmeProvider.class); when(mockProvider.directory( @@ -149,7 +149,7 @@ public class DefaultConnectionTest { public void testResetNonce() throws AcmeException, IOException { byte[] nonce = "foo-nonce-foo".getBytes(); - when(mockHttpConnection.openConnection(URI.create("https://example.com/acme/new-nonce"))) + when(mockHttpConnection.openConnection(new URL("https://example.com/acme/new-nonce"))) .thenReturn(mockUrlConnection); when(mockUrlConnection.getResponseCode()) .thenReturn(HttpURLConnection.HTTP_NO_CONTENT); @@ -192,8 +192,8 @@ public class DefaultConnectionTest { try (DefaultConnection conn = new DefaultConnection(mockHttpConnection)) { conn.conn = mockUrlConnection; - URI location = conn.getLocation(); - assertThat(location, is(new URI("https://example.com/otherlocation"))); + URL location = conn.getLocation(); + assertThat(location, is(new URL("https://example.com/otherlocation"))); } verify(mockUrlConnection).getHeaderField("Location"); @@ -211,8 +211,8 @@ public class DefaultConnectionTest { try (DefaultConnection conn = new DefaultConnection(mockHttpConnection)) { conn.conn = mockUrlConnection; - URI location = conn.getLocation(); - assertThat(location, is(new URI("https://example.org/otherlocation"))); + URL location = conn.getLocation(); + assertThat(location, is(new URL("https://example.org/otherlocation"))); } verify(mockUrlConnection).getHeaderField("Location"); @@ -239,9 +239,9 @@ public class DefaultConnectionTest { try (DefaultConnection conn = new DefaultConnection(mockHttpConnection)) { conn.conn = mockUrlConnection; - assertThat(conn.getLink("next"), is(new URI("https://example.com/acme/new-authz"))); - assertThat(conn.getLink("recover"), is(new URI("https://example.org/recover-reg"))); - assertThat(conn.getLink("terms-of-service"), is(new URI("https://example.com/acme/terms"))); + assertThat(conn.getLink("next"), is(new URL("https://example.com/acme/new-authz"))); + assertThat(conn.getLink("recover"), is(new URL("https://example.org/recover-reg"))); + assertThat(conn.getLink("terms-of-service"), is(new URL("https://example.com/acme/terms"))); assertThat(conn.getLink("secret-stuff"), is(nullValue())); } } @@ -251,14 +251,17 @@ public class DefaultConnectionTest { */ @Test public void testGetMultiLink() { + URL baseUrl = TestUtils.url("https://example.com/acme/request/1234"); + Map> headers = new HashMap<>(); headers.put("Link", Arrays.asList( "; rel=\"terms-of-service\"", "; rel=\"terms-of-service\"", - "; rel=\"terms-of-service\"" + "<../terms3>; rel=\"terms-of-service\"" )); when(mockUrlConnection.getHeaderFields()).thenReturn(headers); + when(mockUrlConnection.getURL()).thenReturn(baseUrl); try (DefaultConnection conn = new DefaultConnection(mockHttpConnection)) { conn.conn = mockUrlConnection; @@ -291,7 +294,7 @@ public class DefaultConnectionTest { public void testNoLocation() throws Exception { try (DefaultConnection conn = new DefaultConnection(mockHttpConnection)) { conn.conn = mockUrlConnection; - URI location = conn.getLocation(); + URL location = conn.getLocation(); assertThat(location, is(nullValue())); } @@ -536,7 +539,7 @@ public class DefaultConnectionTest { @Test public void testSendRequest() throws Exception { try (DefaultConnection conn = new DefaultConnection(mockHttpConnection)) { - conn.sendRequest(requestUri, session); + conn.sendRequest(requestUrl, session); } verify(mockUrlConnection).setRequestMethod("GET"); @@ -583,7 +586,7 @@ public class DefaultConnectionTest { JSONBuilder cb = new JSONBuilder(); cb.put("foo", 123).put("bar", "a-string"); session.setKeyIdentifier(keyIdentifierUri); - conn.sendSignedRequest(requestUri, cb, session); + conn.sendSignedRequest(requestUrl, cb, session); } verify(mockUrlConnection).setRequestMethod("POST"); @@ -607,7 +610,7 @@ public class DefaultConnectionTest { StringBuilder expectedHeader = new StringBuilder(); expectedHeader.append('{'); expectedHeader.append("\"nonce\":\"").append(Base64Url.encode(nonce1)).append("\","); - expectedHeader.append("\"url\":\"").append(requestUri).append("\","); + expectedHeader.append("\"url\":\"").append(requestUrl).append("\","); expectedHeader.append("\"alg\":\"RS256\","); expectedHeader.append("\"kid\":\"").append(keyIdentifierUri).append('"'); expectedHeader.append('}'); @@ -656,7 +659,7 @@ public class DefaultConnectionTest { }) { JSONBuilder cb = new JSONBuilder(); cb.put("foo", 123).put("bar", "a-string"); - conn.sendJwkSignedRequest(requestUri, cb, session); + conn.sendJwkSignedRequest(requestUrl, cb, session); } verify(mockUrlConnection).setRequestMethod("POST"); @@ -680,7 +683,7 @@ public class DefaultConnectionTest { StringBuilder expectedHeader = new StringBuilder(); expectedHeader.append('{'); expectedHeader.append("\"nonce\":\"").append(Base64Url.encode(nonce1)).append("\","); - expectedHeader.append("\"url\":\"").append(requestUri).append("\","); + expectedHeader.append("\"url\":\"").append(requestUrl).append("\","); expectedHeader.append("\"alg\":\"RS256\","); expectedHeader.append("\"jwk\":{"); expectedHeader.append("\"kty\":\"").append(TestUtils.KTY).append("\","); @@ -705,7 +708,7 @@ public class DefaultConnectionTest { public void testSendSignedRequestNoKidFailed() throws Exception { try (DefaultConnection conn = new DefaultConnection(mockHttpConnection)) { JSONBuilder cb = new JSONBuilder(); - conn.sendSignedRequest(requestUri, cb, session); + conn.sendSignedRequest(requestUrl, cb, session); } } @@ -714,14 +717,14 @@ public class DefaultConnectionTest { */ @Test(expected = AcmeProtocolException.class) public void testSendSignedRequestNoNonce() throws Exception { - when(mockHttpConnection.openConnection(URI.create("https://example.com/acme/new-nonce"))) + when(mockHttpConnection.openConnection(new URL("https://example.com/acme/new-nonce"))) .thenReturn(mockUrlConnection); when(mockUrlConnection.getResponseCode()) .thenReturn(HttpURLConnection.HTTP_NOT_FOUND); try (DefaultConnection conn = new DefaultConnection(mockHttpConnection)) { JSONBuilder cb = new JSONBuilder(); - conn.sendJwkSignedRequest(requestUri, cb, DefaultConnectionTest.this.session); + conn.sendJwkSignedRequest(requestUrl, cb, DefaultConnectionTest.this.session); } } diff --git a/acme4j-client/src/test/java/org/shredzone/acme4j/connector/DummyConnection.java b/acme4j-client/src/test/java/org/shredzone/acme4j/connector/DummyConnection.java index 9ea6e33c..a384d7e7 100644 --- a/acme4j-client/src/test/java/org/shredzone/acme4j/connector/DummyConnection.java +++ b/acme4j-client/src/test/java/org/shredzone/acme4j/connector/DummyConnection.java @@ -14,6 +14,7 @@ package org.shredzone.acme4j.connector; import java.net.URI; +import java.net.URL; import java.security.cert.X509Certificate; import java.util.Collection; @@ -34,17 +35,17 @@ public class DummyConnection implements Connection { } @Override - public void sendRequest(URI uri, Session session) { + public void sendRequest(URL url, Session session) { throw new UnsupportedOperationException(); } @Override - public void sendSignedRequest(URI uri, JSONBuilder claims, Session session) { + public void sendSignedRequest(URL url, JSONBuilder claims, Session session) { throw new UnsupportedOperationException(); } @Override - public void sendJwkSignedRequest(URI uri, JSONBuilder claims, Session session) { + public void sendJwkSignedRequest(URL url, JSONBuilder claims, Session session) { throw new UnsupportedOperationException(); } @@ -74,12 +75,12 @@ public class DummyConnection implements Connection { } @Override - public URI getLocation() { + public URL getLocation() { throw new UnsupportedOperationException(); } @Override - public URI getLink(String relation) { + public URL getLink(String relation) { throw new UnsupportedOperationException(); } diff --git a/acme4j-client/src/test/java/org/shredzone/acme4j/connector/HttpConnectorTest.java b/acme4j-client/src/test/java/org/shredzone/acme4j/connector/HttpConnectorTest.java index 990a8fdc..48c0b145 100644 --- a/acme4j-client/src/test/java/org/shredzone/acme4j/connector/HttpConnectorTest.java +++ b/acme4j-client/src/test/java/org/shredzone/acme4j/connector/HttpConnectorTest.java @@ -20,8 +20,8 @@ import static org.mockito.Mockito.*; import java.io.IOException; import java.net.HttpURLConnection; -import java.net.URI; import java.net.URISyntaxException; +import java.net.URL; import org.junit.Test; import org.junit.experimental.categories.Category; @@ -57,9 +57,9 @@ public class HttpConnectorTest { */ @Test @Category(HttpURLConnection.class) - public void testOpenConnection() throws IOException, URISyntaxException { + public void testOpenConnection() throws IOException { HttpConnector connector = new HttpConnector(); - HttpURLConnection conn = connector.openConnection(new URI("http://example.com")); + HttpURLConnection conn = connector.openConnection(new URL("http://example.com")); assertThat(conn, not(nullValue())); conn.connect(); assertThat(conn.getResponseCode(), is(HttpURLConnection.HTTP_OK)); diff --git a/acme4j-client/src/test/java/org/shredzone/acme4j/connector/ResourceIteratorTest.java b/acme4j-client/src/test/java/org/shredzone/acme4j/connector/ResourceIteratorTest.java index 8a87b193..2e512f07 100644 --- a/acme4j-client/src/test/java/org/shredzone/acme4j/connector/ResourceIteratorTest.java +++ b/acme4j-client/src/test/java/org/shredzone/acme4j/connector/ResourceIteratorTest.java @@ -15,11 +15,11 @@ package org.shredzone.acme4j.connector; import static org.hamcrest.Matchers.*; import static org.junit.Assert.assertThat; -import static org.shredzone.acme4j.util.TestUtils.isIntArrayContainingInAnyOrder; +import static org.shredzone.acme4j.util.TestUtils.*; import java.io.IOException; import java.net.HttpURLConnection; -import java.net.URI; +import java.net.URL; import java.util.ArrayList; import java.util.Iterator; import java.util.List; @@ -43,24 +43,24 @@ public class ResourceIteratorTest { private final int RESOURCES_PER_PAGE = 5; private final String TYPE = "authorizations"; - private List resourceURIs = new ArrayList<>(PAGES * RESOURCES_PER_PAGE); - private List pageURIs = new ArrayList<>(PAGES); + private List resourceURLs = new ArrayList<>(PAGES * RESOURCES_PER_PAGE); + private List pageURLs = new ArrayList<>(PAGES); @Before public void setup() { - resourceURIs.clear(); + resourceURLs.clear(); for (int ix = 0; ix < RESOURCES_PER_PAGE * PAGES; ix++) { - resourceURIs.add(URI.create("https://example.com/acme/auth/" + ix)); + resourceURLs.add(url("https://example.com/acme/auth/" + ix)); } - pageURIs.clear(); + pageURLs.clear(); for (int ix = 0; ix < PAGES; ix++) { - pageURIs.add(URI.create("https://example.com/acme/batch/" + ix)); + pageURLs.add(url("https://example.com/acme/batch/" + ix)); } } /** - * Test if the {@link ResourceIterator} handles a {@code null} start URI. + * Test if the {@link ResourceIterator} handles a {@code null} start URL. */ @Test(expected = NoSuchElementException.class) public void nullTest() throws IOException { @@ -76,14 +76,14 @@ public class ResourceIteratorTest { */ @Test public void iteratorTest() throws IOException { - List result = new ArrayList<>(); + List result = new ArrayList<>(); - Iterator it = createIterator(pageURIs.get(0)); + Iterator it = createIterator(pageURLs.get(0)); while (it.hasNext()) { result.add(it.next().getLocation()); } - assertThat(result, is(equalTo(resourceURIs))); + assertThat(result, is(equalTo(resourceURLs))); } /** @@ -91,9 +91,9 @@ public class ResourceIteratorTest { */ @Test public void nextHasNextTest() throws IOException { - List result = new ArrayList<>(); + List result = new ArrayList<>(); - Iterator it = createIterator(pageURIs.get(0)); + Iterator it = createIterator(pageURLs.get(0)); assertThat(it.hasNext(), is(true)); assertThat(it.hasNext(), is(true)); @@ -107,7 +107,7 @@ public class ResourceIteratorTest { assertThat(it.hasNext(), is(false)); } - assertThat(result, is(equalTo(resourceURIs))); + assertThat(result, is(equalTo(resourceURLs))); } /** @@ -115,7 +115,7 @@ public class ResourceIteratorTest { */ @Test(expected = UnsupportedOperationException.class) public void removeTest() throws IOException { - Iterator it = createIterator(pageURIs.get(0)); + Iterator it = createIterator(pageURLs.get(0)); it.next(); it.remove(); // throws UnsupportedOperationException } @@ -124,16 +124,16 @@ public class ResourceIteratorTest { * Creates a new {@link Iterator} of {@link Authorization} objects. * * @param first - * URI of the first page + * URL of the first page * @return Created {@link Iterator} */ - private Iterator createIterator(URI first) throws IOException { + private Iterator createIterator(URL first) throws IOException { TestableConnectionProvider provider = new TestableConnectionProvider() { private int ix; @Override - public void sendRequest(URI uri, Session session) { - ix = pageURIs.indexOf(uri); + public void sendRequest(URL url, Session session) { + ix = pageURLs.indexOf(url); assertThat(ix, is(greaterThanOrEqualTo(0))); } @@ -149,15 +149,15 @@ public class ResourceIteratorTest { int end = (ix + 1) * RESOURCES_PER_PAGE; JSONBuilder cb = new JSONBuilder(); - cb.array(TYPE, resourceURIs.subList(start, end).toArray()); + cb.array(TYPE, resourceURLs.subList(start, end).toArray()); return JSON.parse(cb.toString()); } @Override - public URI getLink(String relation) { - if ("next".equals(relation) && (ix + 1 < pageURIs.size())) { - return pageURIs.get(ix + 1); + public URL getLink(String relation) { + if ("next".equals(relation) && (ix + 1 < pageURLs.size())) { + return pageURLs.get(ix + 1); } return null; } diff --git a/acme4j-client/src/test/java/org/shredzone/acme4j/connector/SessionProviderTest.java b/acme4j-client/src/test/java/org/shredzone/acme4j/connector/SessionProviderTest.java index ae66b5d2..52435122 100644 --- a/acme4j-client/src/test/java/org/shredzone/acme4j/connector/SessionProviderTest.java +++ b/acme4j-client/src/test/java/org/shredzone/acme4j/connector/SessionProviderTest.java @@ -18,6 +18,7 @@ import static org.junit.Assert.assertThat; import java.io.IOException; import java.net.URI; +import java.net.URL; import java.security.KeyPair; import java.util.ServiceLoader; @@ -92,7 +93,7 @@ public class SessionProviderTest { } @Override - public URI resolve(URI serverUri) { + public URL resolve(URI serverUri) { throw new UnsupportedOperationException(); } @@ -120,7 +121,7 @@ public class SessionProviderTest { } @Override - public URI resolve(URI serverUri) { + public URL resolve(URI serverUri) { throw new UnsupportedOperationException(); } diff --git a/acme4j-client/src/test/java/org/shredzone/acme4j/exception/AcmeAgreementRequiredExceptionTest.java b/acme4j-client/src/test/java/org/shredzone/acme4j/exception/AcmeAgreementRequiredExceptionTest.java index b9216de7..4e91d538 100644 --- a/acme4j-client/src/test/java/org/shredzone/acme4j/exception/AcmeAgreementRequiredExceptionTest.java +++ b/acme4j-client/src/test/java/org/shredzone/acme4j/exception/AcmeAgreementRequiredExceptionTest.java @@ -16,7 +16,9 @@ package org.shredzone.acme4j.exception; import static org.hamcrest.Matchers.*; import static org.junit.Assert.assertThat; +import java.net.MalformedURLException; import java.net.URI; +import java.net.URL; import org.junit.Test; @@ -29,19 +31,19 @@ public class AcmeAgreementRequiredExceptionTest { * Test that parameters are correctly returned. */ @Test - public void testAcmeAgreementRequiredException() { + public void testAcmeAgreementRequiredException() throws MalformedURLException { String type = "urn:ietf:params:acme:error:agreementRequired"; String detail = "Agreement is required"; URI agreementUri = URI.create("http://example.com/agreement.pdf"); - URI instanceUri = URI.create("http://example.com/howToAgree.html"); + URL instanceUrl = new URL("http://example.com/howToAgree.html"); AcmeAgreementRequiredException ex - = new AcmeAgreementRequiredException(type, detail, agreementUri, instanceUri); + = new AcmeAgreementRequiredException(type, detail, agreementUri, instanceUrl); assertThat(ex.getType(), is(type)); assertThat(ex.getMessage(), is(detail)); assertThat(ex.getAgreementUri(), is(agreementUri)); - assertThat(ex.getInstance(), is(instanceUri)); + assertThat(ex.getInstance(), is(instanceUrl)); } /** diff --git a/acme4j-client/src/test/java/org/shredzone/acme4j/exception/AcmeConflictExceptionTest.java b/acme4j-client/src/test/java/org/shredzone/acme4j/exception/AcmeConflictExceptionTest.java index dd8ec815..6e647b27 100644 --- a/acme4j-client/src/test/java/org/shredzone/acme4j/exception/AcmeConflictExceptionTest.java +++ b/acme4j-client/src/test/java/org/shredzone/acme4j/exception/AcmeConflictExceptionTest.java @@ -16,7 +16,8 @@ package org.shredzone.acme4j.exception; import static org.hamcrest.Matchers.is; import static org.junit.Assert.assertThat; -import java.net.URI; +import java.net.MalformedURLException; +import java.net.URL; import org.junit.Test; @@ -26,15 +27,15 @@ import org.junit.Test; public class AcmeConflictExceptionTest { @Test - public void testAcmeConflictException() { + public void testAcmeConflictException() throws MalformedURLException { String msg = "Account already exists"; - URI locationUri = URI.create("http://example.com/location/123"); + URL locationUrl = new URL("http://example.com/location/123"); AcmeConflictException ex - = new AcmeConflictException(msg, locationUri); + = new AcmeConflictException(msg, locationUrl); assertThat(ex.getMessage(), is(msg)); - assertThat(ex.getLocation(), is(locationUri)); + assertThat(ex.getLocation(), is(locationUrl)); } } diff --git a/acme4j-client/src/test/java/org/shredzone/acme4j/it/AbstractPebbleIT.java b/acme4j-client/src/test/java/org/shredzone/acme4j/it/AbstractPebbleIT.java index 203f62a2..bf4fb1ca 100644 --- a/acme4j-client/src/test/java/org/shredzone/acme4j/it/AbstractPebbleIT.java +++ b/acme4j-client/src/test/java/org/shredzone/acme4j/it/AbstractPebbleIT.java @@ -16,7 +16,6 @@ package org.shredzone.acme4j.it; import static org.hamcrest.Matchers.*; import static org.junit.Assert.assertThat; -import java.net.MalformedURLException; import java.net.URI; import java.net.URL; import java.security.KeyPair; @@ -58,24 +57,18 @@ public abstract class AbstractPebbleIT { } /** - * Asserts that the given {@link URI} is not {@code null} and refers to the Pebble + * Asserts that the given {@link URL} is not {@code null} and refers to the Pebble * server. * - * @param uri - * {@link URI} to assert + * @param url + * {@link URL} to assert */ - protected void assertIsPebbleUri(URI uri) { - assertThat(uri, not(nullValue())); - - try { - URL url = uri.toURL(); - assertThat(url.getProtocol(), is("http")); - assertThat(url.getHost(), is(pebbleHost)); - assertThat(url.getPort(), is(pebblePort)); - assertThat(url.getPath(), not(isEmptyOrNullString())); - } catch (MalformedURLException ex) { - throw new IllegalArgumentException(ex); - } + protected void assertIsPebbleUrl(URL url) { + assertThat(url, not(nullValue())); + assertThat(url.getProtocol(), is("http")); + assertThat(url.getHost(), is(pebbleHost)); + assertThat(url.getPort(), is(pebblePort)); + assertThat(url.getPath(), not(isEmptyOrNullString())); } } diff --git a/acme4j-client/src/test/java/org/shredzone/acme4j/it/RegistrationIT.java b/acme4j-client/src/test/java/org/shredzone/acme4j/it/RegistrationIT.java index 2a6dd5c3..124040ac 100644 --- a/acme4j-client/src/test/java/org/shredzone/acme4j/it/RegistrationIT.java +++ b/acme4j-client/src/test/java/org/shredzone/acme4j/it/RegistrationIT.java @@ -17,6 +17,7 @@ import static org.hamcrest.Matchers.*; import static org.junit.Assert.assertThat; import java.net.URI; +import java.net.URL; import java.security.KeyPair; import org.junit.Ignore; @@ -44,11 +45,10 @@ public class RegistrationIT extends AbstractPebbleIT { rb.agreeToTermsOfService(); Registration reg = rb.create(session); - URI location = reg.getLocation(); - assertIsPebbleUri(location); + URL location = reg.getLocation(); + assertIsPebbleUrl(location); URI keyIdentifier = session.getKeyIdentifier(); - assertIsPebbleUri(keyIdentifier); - assertThat(keyIdentifier, is(location)); + assertThat(keyIdentifier.toString(), is(location.toString())); // TODO: Not yet supported by Pebble /* @@ -81,8 +81,8 @@ public class RegistrationIT extends AbstractPebbleIT { rb.agreeToTermsOfService(); Registration reg = rb.create(session); - URI location = reg.getLocation(); - assertIsPebbleUri(location); + URL location = reg.getLocation(); + assertIsPebbleUrl(location); reg.modify().addContact("mailto:acme2@example.com").commit(); @@ -104,7 +104,7 @@ public class RegistrationIT extends AbstractPebbleIT { Session session = new Session(pebbleURI(), keyPair); Registration reg = new RegistrationBuilder().agreeToTermsOfService().create(session); - URI location = reg.getLocation(); + URL location = reg.getLocation(); KeyPair newKeyPair = createKeyPair(); reg.changeKey(newKeyPair); @@ -129,7 +129,7 @@ public class RegistrationIT extends AbstractPebbleIT { Session session = new Session(pebbleURI(), keyPair); Registration reg = new RegistrationBuilder().agreeToTermsOfService().create(session); - URI location = reg.getLocation(); + URL location = reg.getLocation(); reg.deactivate(); diff --git a/acme4j-client/src/test/java/org/shredzone/acme4j/it/SessionIT.java b/acme4j-client/src/test/java/org/shredzone/acme4j/it/SessionIT.java index 34732e12..d0f1acbf 100644 --- a/acme4j-client/src/test/java/org/shredzone/acme4j/it/SessionIT.java +++ b/acme4j-client/src/test/java/org/shredzone/acme4j/it/SessionIT.java @@ -53,10 +53,10 @@ public class SessionIT extends AbstractPebbleIT { Session session = new Session(pebbleURI(), keyPair); // TODO: Not yet supported by Pebble - // assertIsPebbleUri(session.resourceUri(Resource.KEY_CHANGE)); + // assertIsPebbleUrl(session.resourceUrl(Resource.KEY_CHANGE)); - assertIsPebbleUri(session.resourceUri(Resource.NEW_NONCE)); - assertIsPebbleUri(session.resourceUri(Resource.NEW_REG)); + assertIsPebbleUrl(session.resourceUrl(Resource.NEW_NONCE)); + assertIsPebbleUrl(session.resourceUrl(Resource.NEW_REG)); } @Test diff --git a/acme4j-client/src/test/java/org/shredzone/acme4j/provider/AbstractAcmeProviderTest.java b/acme4j-client/src/test/java/org/shredzone/acme4j/provider/AbstractAcmeProviderTest.java index b46b9d30..2a7c73bf 100644 --- a/acme4j-client/src/test/java/org/shredzone/acme4j/provider/AbstractAcmeProviderTest.java +++ b/acme4j-client/src/test/java/org/shredzone/acme4j/provider/AbstractAcmeProviderTest.java @@ -22,6 +22,7 @@ import static uk.co.datumedge.hamcrest.json.SameJSONAs.sameJSONAs; import java.net.HttpURLConnection; import java.net.URI; +import java.net.URL; import java.util.concurrent.atomic.AtomicBoolean; import org.junit.Test; @@ -34,6 +35,7 @@ import org.shredzone.acme4j.challenge.TlsSni02Challenge; import org.shredzone.acme4j.connector.Connection; import org.shredzone.acme4j.connector.DefaultConnection; import org.shredzone.acme4j.connector.HttpConnector; +import org.shredzone.acme4j.exception.AcmeException; import org.shredzone.acme4j.util.JSON; import org.shredzone.acme4j.util.TestUtils; @@ -56,7 +58,7 @@ public class AbstractAcmeProviderTest { } @Override - public URI resolve(URI serverUri) { + public URL resolve(URI serverUri) { throw new UnsupportedOperationException(); } @@ -77,9 +79,9 @@ public class AbstractAcmeProviderTest { * Verify that the resources directory is read. */ @Test - public void testResources() throws Exception { - final URI testServerUri = new URI("http://example.com/acme"); - final URI testResolvedUri = new URI("http://example.com/acme/directory"); + public void testResources() throws AcmeException { + final URI testServerUri = URI.create("http://example.com/acme"); + final URL testResolvedUrl = TestUtils.url("http://example.com/acme/directory"); final Connection connection = mock(Connection.class); final Session session = mock(Session.class); @@ -99,16 +101,16 @@ public class AbstractAcmeProviderTest { } @Override - public URI resolve(URI serverUri) { + public URL resolve(URI serverUri) { assertThat(serverUri, is(testServerUri)); - return testResolvedUri; + return testResolvedUrl; } }; JSON map = provider.directory(session, testServerUri); assertThat(map.toString(), sameJSONAs(TestUtils.getJson("directory"))); - verify(connection).sendRequest(testResolvedUri, session); + verify(connection).sendRequest(testResolvedUrl, session); verify(connection).accept(any(Integer.class)); verify(connection).updateSession(any(Session.class)); verify(connection).readJsonResponse(); @@ -130,7 +132,7 @@ public class AbstractAcmeProviderTest { } @Override - public URI resolve(URI serverUri) { + public URL resolve(URI serverUri) { throw new UnsupportedOperationException(); } }; diff --git a/acme4j-client/src/test/java/org/shredzone/acme4j/provider/GenericAcmeProviderTest.java b/acme4j-client/src/test/java/org/shredzone/acme4j/provider/GenericAcmeProviderTest.java index 257b1e58..ff1e6e34 100644 --- a/acme4j-client/src/test/java/org/shredzone/acme4j/provider/GenericAcmeProviderTest.java +++ b/acme4j-client/src/test/java/org/shredzone/acme4j/provider/GenericAcmeProviderTest.java @@ -18,6 +18,7 @@ import static org.junit.Assert.assertThat; import java.net.URI; import java.net.URISyntaxException; +import java.net.URL; import org.junit.Test; @@ -47,8 +48,8 @@ public class GenericAcmeProviderTest { GenericAcmeProvider provider = new GenericAcmeProvider(); - URI resolvedUri = provider.resolve(serverUri); - assertThat(resolvedUri, is(equalTo(serverUri))); + URL resolvedUrl = provider.resolve(serverUri); + assertThat(resolvedUrl.toString(), is(equalTo(serverUri.toString()))); } } diff --git a/acme4j-client/src/test/java/org/shredzone/acme4j/provider/TestableConnectionProvider.java b/acme4j-client/src/test/java/org/shredzone/acme4j/provider/TestableConnectionProvider.java index 590d71a6..ab0688f0 100644 --- a/acme4j-client/src/test/java/org/shredzone/acme4j/provider/TestableConnectionProvider.java +++ b/acme4j-client/src/test/java/org/shredzone/acme4j/provider/TestableConnectionProvider.java @@ -15,6 +15,7 @@ package org.shredzone.acme4j.provider; import java.io.IOException; import java.net.URI; +import java.net.URL; import java.util.HashMap; import java.util.Map; @@ -24,8 +25,8 @@ import org.shredzone.acme4j.connector.Connection; import org.shredzone.acme4j.connector.DummyConnection; import org.shredzone.acme4j.connector.Resource; import org.shredzone.acme4j.exception.AcmeException; -import org.shredzone.acme4j.util.JSONBuilder; import org.shredzone.acme4j.util.JSON; +import org.shredzone.acme4j.util.JSONBuilder; import org.shredzone.acme4j.util.TestUtils; /** @@ -42,9 +43,9 @@ public class TestableConnectionProvider extends DummyConnection implements AcmeP * @param r * {@link Resource} to be mapped * @param u - * {@link URI} to be returned + * {@link URL} to be returned */ - public void putTestResource(Resource r, URI u) { + public void putTestResource(Resource r, URL u) { directory.put(r.path(), u); } @@ -75,7 +76,7 @@ public class TestableConnectionProvider extends DummyConnection implements AcmeP } @Override - public URI resolve(URI serverUri) { + public URL resolve(URI serverUri) { throw new UnsupportedOperationException(); } diff --git a/acme4j-client/src/test/java/org/shredzone/acme4j/provider/letsencrypt/LetsEncryptAcmeProviderTest.java b/acme4j-client/src/test/java/org/shredzone/acme4j/provider/letsencrypt/LetsEncryptAcmeProviderTest.java index 3454b5d2..63c76fab 100644 --- a/acme4j-client/src/test/java/org/shredzone/acme4j/provider/letsencrypt/LetsEncryptAcmeProviderTest.java +++ b/acme4j-client/src/test/java/org/shredzone/acme4j/provider/letsencrypt/LetsEncryptAcmeProviderTest.java @@ -15,6 +15,7 @@ package org.shredzone.acme4j.provider.letsencrypt; import static org.hamcrest.Matchers.is; import static org.junit.Assert.*; +import static org.shredzone.acme4j.util.TestUtils.url; import java.net.URI; import java.net.URISyntaxException; @@ -52,10 +53,10 @@ public class LetsEncryptAcmeProviderTest { public void testResolve() throws URISyntaxException { LetsEncryptAcmeProvider provider = new LetsEncryptAcmeProvider(); - assertThat(provider.resolve(new URI("acme://letsencrypt.org")), is(new URI(V01_DIRECTORY_URI))); - assertThat(provider.resolve(new URI("acme://letsencrypt.org/")), is(new URI(V01_DIRECTORY_URI))); - assertThat(provider.resolve(new URI("acme://letsencrypt.org/v01")), is(new URI(V01_DIRECTORY_URI))); - assertThat(provider.resolve(new URI("acme://letsencrypt.org/staging")), is(new URI(STAGING_DIRECTORY_URI))); + assertThat(provider.resolve(new URI("acme://letsencrypt.org")), is(url(V01_DIRECTORY_URI))); + assertThat(provider.resolve(new URI("acme://letsencrypt.org/")), is(url(V01_DIRECTORY_URI))); + assertThat(provider.resolve(new URI("acme://letsencrypt.org/v01")), is(url(V01_DIRECTORY_URI))); + assertThat(provider.resolve(new URI("acme://letsencrypt.org/staging")), is(url(STAGING_DIRECTORY_URI))); try { provider.resolve(new URI("acme://letsencrypt.org/v99")); diff --git a/acme4j-client/src/test/java/org/shredzone/acme4j/provider/letsencrypt/LetsEncryptHttpConnectorTest.java b/acme4j-client/src/test/java/org/shredzone/acme4j/provider/letsencrypt/LetsEncryptHttpConnectorTest.java index 09a17288..c8396c82 100644 --- a/acme4j-client/src/test/java/org/shredzone/acme4j/provider/letsencrypt/LetsEncryptHttpConnectorTest.java +++ b/acme4j-client/src/test/java/org/shredzone/acme4j/provider/letsencrypt/LetsEncryptHttpConnectorTest.java @@ -18,8 +18,7 @@ import static org.junit.Assert.*; import java.io.IOException; import java.net.HttpURLConnection; -import java.net.URI; -import java.net.URISyntaxException; +import java.net.URL; import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.SSLHandshakeException; @@ -41,12 +40,12 @@ public class LetsEncryptHttpConnectorTest { */ @Test @Category(HttpURLConnection.class) - public void testCertificate() throws IOException, URISyntaxException { + public void testCertificate() throws IOException { LetsEncryptHttpConnector connector = new LetsEncryptHttpConnector(); try { HttpURLConnection goodConn = connector.openConnection( - new URI("https://acme-staging.api.letsencrypt.org/directory")); + new URL("https://acme-staging.api.letsencrypt.org/directory")); assertThat(goodConn, is(instanceOf(HttpsURLConnection.class))); goodConn.connect(); } catch (SSLHandshakeException ex) { @@ -55,7 +54,7 @@ public class LetsEncryptHttpConnectorTest { try { HttpURLConnection badConn = connector.openConnection( - new URI("https://www.google.com")); + new URL("https://www.google.com")); assertThat(badConn, is(instanceOf(HttpsURLConnection.class))); badConn.connect(); fail("Connection accepts foreign certificate"); diff --git a/acme4j-client/src/test/java/org/shredzone/acme4j/provider/pebble/PebbleAcmeProviderTest.java b/acme4j-client/src/test/java/org/shredzone/acme4j/provider/pebble/PebbleAcmeProviderTest.java index d7d837d0..9d2b69fd 100644 --- a/acme4j-client/src/test/java/org/shredzone/acme4j/provider/pebble/PebbleAcmeProviderTest.java +++ b/acme4j-client/src/test/java/org/shredzone/acme4j/provider/pebble/PebbleAcmeProviderTest.java @@ -15,6 +15,7 @@ package org.shredzone.acme4j.provider.pebble; import static org.hamcrest.Matchers.is; import static org.junit.Assert.*; +import static org.shredzone.acme4j.util.TestUtils.url; import java.net.URI; import java.net.URISyntaxException; @@ -50,15 +51,15 @@ public class PebbleAcmeProviderTest { PebbleAcmeProvider provider = new PebbleAcmeProvider(); assertThat(provider.resolve(new URI("acme://pebble")), - is(new URI("http://localhost:14000/dir"))); + is(url("http://localhost:14000/dir"))); assertThat(provider.resolve(new URI("acme://pebble/")), - is(new URI("http://localhost:14000/dir"))); + is(url("http://localhost:14000/dir"))); assertThat(provider.resolve(new URI("acme://pebble/pebble.example.com")), - is(new URI("http://pebble.example.com:14000/dir"))); + is(url("http://pebble.example.com:14000/dir"))); assertThat(provider.resolve(new URI("acme://pebble/pebble.example.com:12345")), - is(new URI("http://pebble.example.com:12345/dir"))); + is(url("http://pebble.example.com:12345/dir"))); assertThat(provider.resolve(new URI("acme://pebble/pebble.example.com:12345/")), - is(new URI("http://pebble.example.com:12345/dir"))); + is(url("http://pebble.example.com:12345/dir"))); try { provider.resolve(new URI("acme://pebble/bad.example.com:port")); diff --git a/acme4j-client/src/test/java/org/shredzone/acme4j/util/JSONTest.java b/acme4j-client/src/test/java/org/shredzone/acme4j/util/JSONTest.java index b30f0d46..1c8b43d1 100644 --- a/acme4j-client/src/test/java/org/shredzone/acme4j/util/JSONTest.java +++ b/acme4j-client/src/test/java/org/shredzone/acme4j/util/JSONTest.java @@ -15,6 +15,7 @@ package org.shredzone.acme4j.util; import static org.hamcrest.Matchers.*; import static org.junit.Assert.*; +import static org.shredzone.acme4j.util.TestUtils.url; import static uk.co.datumedge.hamcrest.json.SameJSONAs.sameJSONAs; import java.io.ByteArrayInputStream; @@ -25,7 +26,6 @@ import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.net.MalformedURLException; import java.net.URI; -import java.net.URL; import java.time.Instant; import java.time.LocalDate; import java.time.ZoneId; @@ -183,7 +183,7 @@ public class JSONTest { * Test all getters on existing values. */ @Test - public void testGetter() throws MalformedURLException { + public void testGetter() { Instant date = LocalDate.of(2016, 1, 8).atStartOfDay(ZoneId.of("UTC")).toInstant(); JSON json = TestUtils.getJsonAsObject("json"); @@ -192,7 +192,7 @@ public class JSONTest { assertThat(json.get("number").asInt(), is(123)); assertThat(json.get("boolean").asBoolean(), is(true)); assertThat(json.get("uri").asURI(), is(URI.create("mailto:foo@example.com"))); - assertThat(json.get("url").asURL(), is(new URL("http://example.com"))); + assertThat(json.get("url").asURL(), is(url("http://example.com"))); assertThat(json.get("date").asInstant(), is(date)); assertThat(json.get("status").asStatusOrElse(Status.INVALID), is(Status.VALID)); assertThat(json.get("binary").asBinary(), is("Chainsaw".getBytes())); diff --git a/acme4j-client/src/test/java/org/shredzone/acme4j/util/TestUtils.java b/acme4j-client/src/test/java/org/shredzone/acme4j/util/TestUtils.java index 1a36e977..8a735d07 100644 --- a/acme4j-client/src/test/java/org/shredzone/acme4j/util/TestUtils.java +++ b/acme4j-client/src/test/java/org/shredzone/acme4j/util/TestUtils.java @@ -17,7 +17,9 @@ import java.io.ByteArrayOutputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; +import java.net.MalformedURLException; import java.net.URI; +import java.net.URL; import java.security.InvalidAlgorithmParameterException; import java.security.KeyFactory; import java.security.KeyPair; @@ -120,6 +122,22 @@ public final class TestUtils { return new Session(URI.create(ACME_SERVER_URI), keyPair); } + /** + * Creates an {@link URL} from a String. Only throws a runtime exception if the URL is + * malformed. + * + * @param url + * URL to use + * @return {@link URL} object + */ + public static URL url(String url) { + try { + return new URL(url); + } catch (MalformedURLException ex) { + throw new IllegalArgumentException(url, ex); + } + } + /** * Creates a {@link Session} instance. It uses {@link #ACME_SERVER_URI} as server URI. * diff --git a/src/site/markdown/ca/index.md b/src/site/markdown/ca/index.md index 5d9376e9..be13555b 100644 --- a/src/site/markdown/ca/index.md +++ b/src/site/markdown/ca/index.md @@ -24,7 +24,7 @@ Some CAs provide metadata related to their ACME server. This information can be ```java Metadata meta = session.getMetadata(); -URI website = meta.getWebsite(); +URL website = meta.getWebsite(); ``` `meta` is never `null`, even if the server did not provide any metadata. All of the `Metadata` getters are optional though, and may return `null` if the respective information was not provided by the server. diff --git a/src/site/markdown/migration.md b/src/site/markdown/migration.md index ea06ee79..69383250 100644 --- a/src/site/markdown/migration.md +++ b/src/site/markdown/migration.md @@ -32,11 +32,11 @@ Session session = new Session("acme://letsencrypt.org/staging", keyPair); Instead of creating a plain `Registration` object, you now bind it to the session. ```java -URI accountLocationUri = ... // your account's URI -Registration registration = Registration.bind(session, accountLocationUri); +URL accountLocationUrl = ... // your account's URL +Registration registration = Registration.bind(session, accountLocationUrl); ``` -You must know your account's location URI. Use a `RegistrationBuilder` if you do not know it, or if you want to register a new account: +You must know your account's location URL. Use a `RegistrationBuilder` if you do not know it, or if you want to register a new account: ```java Registration registration; @@ -45,7 +45,7 @@ try { registration = new RegistrationBuilder().create(session); } catch (AcmeConflictException ex) { // It failed because your key was already registered. - // Retrieve the registration location URI from the exception. + // Retrieve the registration location URL from the exception. registration = Registration.bind(session, ex.getLocation()); } ``` diff --git a/src/site/markdown/provider.md b/src/site/markdown/provider.md index b813d21d..05837840 100644 --- a/src/site/markdown/provider.md +++ b/src/site/markdown/provider.md @@ -21,11 +21,11 @@ However, it is also possible to adapt the behavior of wide parts of _acme4j_ to A client provider implements the [`AcmeProvider`](./apidocs/org/shredzone/acme4j/provider/AcmeProvider.html) interface, but usually it is easier to extend [`AbstractAcmeProvider`](./apidocs/org/shredzone/acme4j/provider/AbstractAcmeProvider.html) and implement only these two methods: * `accepts(URI)` checks if the client provider is accepting the provided URI. Usually it would be an URI like `acme://example.com`. Note that the `http` and `https` schemes are reserved for the generic provider and cannot be used by other providers. -* `resolve(URI)` parses that URI and returns the corresponding URI of the directory service. +* `resolve(URI)` parses that URI and returns the corresponding URL of the directory service. The `AcmeProvider` implementation needs to be registered with Java's `ServiceLoader`. In the `META-INF/services` path of your project, create a file `org.shredzone.acme4j.provider.AcmeProvider` and write the fully qualified class name of your implementation into that file. -When _acme4j_ tries to connect to an acme URI, it first invokes the `accepts(URI)` method of all registered `AcmeProvider`s. Only one of the providers must return `true` for a successful connection. _acme4j_ then invokes the `resolve(URI)` method of that provider, and connects to the directory URI that is returned. +When _acme4j_ tries to connect to an acme URI, it first invokes the `accepts(URI)` method of all registered `AcmeProvider`s. Only one of the providers must return `true` for a successful connection. _acme4j_ then invokes the `resolve(URI)` method of that provider, and connects to the directory URL that is returned. The connection fails if none or more than one `AcmeProvider` implementations `accept` the acme URI. @@ -45,4 +45,4 @@ In your `AcmeProvider` implementation, override the `createChallenge(Session, St An ACME server may not provide a directory service, for example when fixed URIs are to be used. -In this case, override the `resources(Session, URI)` method, and return a `Map` of all available resources and their respective URI. +In this case, override the `directory(Session, URI)` method, and return a `JSON` of all available resources and their respective URI. diff --git a/src/site/markdown/usage/authorization.md b/src/site/markdown/usage/authorization.md index da5f9c3a..cd7c7144 100644 --- a/src/site/markdown/usage/authorization.md +++ b/src/site/markdown/usage/authorization.md @@ -56,12 +56,12 @@ If your final certificate will contain further domains or subdomains, repeat the ## Update an Authorization -The server also provides an authorization URI. It can be retrieved from `Authorization.getLocation()`. You can recreate the `Authorization` object at a later time just by binding it to your `Session`: +The server also provides an authorization URL. It can be retrieved from `Authorization.getLocation()`. You can recreate the `Authorization` object at a later time just by binding it to your `Session`: ```java -URI authUri = ... // Authorization URI +URL authUrl = ... // Authorization URL -Authorization auth = Authorization.bind(session, authUri); +Authorization auth = Authorization.bind(session, authUrl); ``` As soon as you invoke a getter, the `Authorization` object lazily loads the current server state of your authorization, including the domain name, the overall status, and an expiry date. @@ -84,13 +84,13 @@ To recreate a `Challenge` object at a later time, all you need is to store the o ```java Challenge originalChallenge = ... // some Challenge instance -URI challengeUri = originalChallenge.getLocation(); +URL challengeUrl = originalChallenge.getLocation(); ``` Later, you restore the `Challenge` object by invoking `Challenge.bind()`. ```java -URI challengeUri = ... // challenge URI +URL challengeUrl = ... // challenge URL Challenge restoredChallenge = Challenge.bind(session, challengeUri); ``` diff --git a/src/site/markdown/usage/certificate.md b/src/site/markdown/usage/certificate.md index 1ca17fe0..9bd4b5aa 100644 --- a/src/site/markdown/usage/certificate.md +++ b/src/site/markdown/usage/certificate.md @@ -34,7 +34,7 @@ Now all you need to do is to pass in a binary representation of the CSR and requ Certificate cert = registration.requestCertificate(csr); ``` -`cert.getLocation()` returns an URI where the signed certificate can be downloaded from. Optionally (if delivered by the ACME server) `cert.getChainLocation()` returns the URI of the first part of the CA chain. +`cert.getLocation()` returns an URL where the signed certificate can be downloaded from. Optionally (if delivered by the ACME server) `cert.getChainLocation()` returns the URL of the first part of the CA chain. The `Certificate` object offers methods to download the certificate and the certificate chain. @@ -50,8 +50,8 @@ Congratulations! You have just created your first certificate via _acme4j_. To recreate a `Certificate` object from the location, just bind it: ```java -URI locationUri = ... // location URI from cert.getLocation() -Certificate cert = Certificate.bind(session, locationUri); +URL locationUrl = ... // location URL from cert.getLocation() +Certificate cert = Certificate.bind(session, locationUrl); ``` ### Saving Certificates diff --git a/src/site/markdown/usage/register.md b/src/site/markdown/usage/register.md index ec4affc9..6cf2d5e7 100644 --- a/src/site/markdown/usage/register.md +++ b/src/site/markdown/usage/register.md @@ -2,7 +2,7 @@ If it is the first time you connect to the ACME server, you need to register your account key. -To do so, create a `RegistrationBuilder`, optionally add some contact information, agree to the terms of service, then invoke `create()`. If the account was successfully created, you will get a `Registration` object in return. Invoking its `getLocation()` method will return the location URI of your account. You should store it somewhere, because you will need it later. Unlike your key pair, the location is a public information that does not need security precautions. +To do so, create a `RegistrationBuilder`, optionally add some contact information, agree to the terms of service, then invoke `create()`. If the account was successfully created, you will get a `Registration` object in return. Invoking its `getLocation()` method will return the location URL of your account. You should store it somewhere, because you will need it later. Unlike your key pair, the location is a public information that does not need security precautions. ```java RegistrationBuilder builder = new RegistrationBuilder(); @@ -11,10 +11,10 @@ builder.agreeToTermsOfService(); Registration registration = builder.create(session); -URI accountLocationUri = registration.getLocation(); +URL accountLocationUrl = registration.getLocation(); ``` -`create()` will fail and throw an `AcmeConflictException` if your key was already registered with the CA. The `AcmeConflictException` contains the location of the registration. This may be helpful if you forgot your account URI and need to recover it. +`create()` will fail and throw an `AcmeConflictException` if your key was already registered with the CA. The `AcmeConflictException` contains the location of the registration. This may be helpful if you forgot your account URL and need to recover it. The following example will create a new `Registration` and restore an existing `Registration`. @@ -34,8 +34,6 @@ At some point, you may want to update your registration. For example your contac The following example adds another email address. ```java -URI agreementUri = ... // TAC link provided by the CA - registration.modify() .addContact("mailto:acme2@example.com") .commit(); diff --git a/src/site/markdown/usage/session.md b/src/site/markdown/usage/session.md index db415b35..39cce1b7 100644 --- a/src/site/markdown/usage/session.md +++ b/src/site/markdown/usage/session.md @@ -31,12 +31,12 @@ Instead of a generic provider, this call uses a special _Let's Encrypt_ provider Now that you have a `Session` object, you can use it to bind ACME resource objects. For example, this is the way to get a `Registration` object to an existing registration: ```java -URI accountLocationUri = ... // your account's URI, as returned by Registration.getLocation() +URL accountLocationUrl = ... // your account's URL, as returned by Registration.getLocation() -Registration registration = Registration.bind(session, accountLocationUri); +Registration registration = Registration.bind(session, accountLocationUrl); ``` -You can create any of the resource objects `Registration`, `Authorization`, `Challenge` and `Certificate` like that, as long as you know the corresponding resource URI. To get the resource URI, use the `getLocation()` method. +You can create any of the resource objects `Registration`, `Authorization`, `Challenge` and `Certificate` like that, as long as you know the corresponding resource URL. To get the resource URL, use the `getLocation()` method. ## Serialization