mirror of https://github.com/shred/acme4j
Refactor, make AbstractAcmeClientProvider easier to use (and test)
parent
f88bdf7e5f
commit
62ed304f3a
|
@ -16,19 +16,26 @@ package org.shredzone.acme4j.provider;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.HttpURLConnection;
|
import java.net.HttpURLConnection;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.shredzone.acme4j.AcmeClient;
|
||||||
import org.shredzone.acme4j.challenge.Challenge;
|
import org.shredzone.acme4j.challenge.Challenge;
|
||||||
import org.shredzone.acme4j.challenge.DnsChallenge;
|
import org.shredzone.acme4j.challenge.DnsChallenge;
|
||||||
import org.shredzone.acme4j.challenge.GenericChallenge;
|
import org.shredzone.acme4j.challenge.GenericChallenge;
|
||||||
import org.shredzone.acme4j.challenge.HttpChallenge;
|
import org.shredzone.acme4j.challenge.HttpChallenge;
|
||||||
import org.shredzone.acme4j.challenge.ProofOfPossessionChallenge;
|
import org.shredzone.acme4j.challenge.ProofOfPossessionChallenge;
|
||||||
import org.shredzone.acme4j.challenge.TlsSniChallenge;
|
import org.shredzone.acme4j.challenge.TlsSniChallenge;
|
||||||
|
import org.shredzone.acme4j.impl.GenericAcmeClient;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Abstract implementation of {@link AcmeClientProvider}. It consists of a challenge
|
* Abstract implementation of {@link AcmeClientProvider}. It consists of a challenge
|
||||||
* registry and a standard {@link #openConnection(URI)} implementation.
|
* registry and a standard {@link #openConnection(URI)} implementation.
|
||||||
|
* <p>
|
||||||
|
* Implementing classes must implement at least {@link AcmeClientProvider#accepts(URI)}
|
||||||
|
* and {@link AbstractAcmeClientProvider#resolve(URI)}.
|
||||||
*
|
*
|
||||||
* @author Richard "Shred" Körber
|
* @author Richard "Shred" Körber
|
||||||
*/
|
*/
|
||||||
|
@ -42,6 +49,26 @@ public abstract class AbstractAcmeClientProvider implements AcmeClientProvider {
|
||||||
registerBaseChallenges();
|
registerBaseChallenges();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolves the server URI and returns the matching directory URI.
|
||||||
|
*
|
||||||
|
* @param serverUri
|
||||||
|
* Server {@link URI}
|
||||||
|
* @return Resolved directory {@link URI}
|
||||||
|
* @throws IllegalArgumentException
|
||||||
|
* if the server {@link URI} is not accepted
|
||||||
|
*/
|
||||||
|
protected abstract URI resolve(URI serverUri);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AcmeClient connect(URI serverUri) {
|
||||||
|
if (!accepts(serverUri)) {
|
||||||
|
throw new IllegalArgumentException("This provider does not accept " + serverUri);
|
||||||
|
}
|
||||||
|
|
||||||
|
return createAcmeClient(resolve(serverUri));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public <T extends Challenge> T createChallenge(String type) {
|
public <T extends Challenge> T createChallenge(String type) {
|
||||||
|
@ -79,9 +106,26 @@ public abstract class AbstractAcmeClientProvider implements AcmeClientProvider {
|
||||||
* constructor.
|
* constructor.
|
||||||
*/
|
*/
|
||||||
protected void registerChallenge(String type, Class<? extends Challenge> clazz) {
|
protected void registerChallenge(String type, Class<? extends Challenge> clazz) {
|
||||||
|
if (type == null) {
|
||||||
|
throw new NullPointerException("type must not be null");
|
||||||
|
}
|
||||||
|
if (clazz == null) {
|
||||||
|
throw new NullPointerException("Challenge class must not be null");
|
||||||
|
}
|
||||||
|
if (type.trim().isEmpty()) {
|
||||||
|
throw new IllegalArgumentException("type must not be empty");
|
||||||
|
}
|
||||||
|
|
||||||
challenges.put(type, clazz);
|
challenges.put(type, clazz);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns all registered challenge types.
|
||||||
|
*/
|
||||||
|
protected Collection<String> getRegisteredChallengeTypes() {
|
||||||
|
return Collections.unmodifiableCollection(challenges.keySet());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Registers all standard challenges as specified in the ACME specifications.
|
* Registers all standard challenges as specified in the ACME specifications.
|
||||||
* <p>
|
* <p>
|
||||||
|
@ -95,4 +139,15 @@ public abstract class AbstractAcmeClientProvider implements AcmeClientProvider {
|
||||||
registerChallenge(HttpChallenge.TYPE, HttpChallenge.class);
|
registerChallenge(HttpChallenge.TYPE, HttpChallenge.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an {@link AcmeClient} for the given directory URI.
|
||||||
|
*
|
||||||
|
* @param directoryUri
|
||||||
|
* Directory {@link URI}
|
||||||
|
* @return {@link AcmeClient}
|
||||||
|
*/
|
||||||
|
protected AcmeClient createAcmeClient(URI directoryUri) {
|
||||||
|
return new GenericAcmeClient(this, directoryUri);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,9 +15,6 @@ package org.shredzone.acme4j.provider;
|
||||||
|
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
|
|
||||||
import org.shredzone.acme4j.AcmeClient;
|
|
||||||
import org.shredzone.acme4j.impl.GenericAcmeClient;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A generic {@link AcmeClientProvider}. It should be working for all ACME servers
|
* A generic {@link AcmeClientProvider}. It should be working for all ACME servers
|
||||||
* complying to the ACME specifications.
|
* complying to the ACME specifications.
|
||||||
|
@ -35,12 +32,8 @@ public class GenericAcmeClientProvider extends AbstractAcmeClientProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AcmeClient connect(URI serverUri) {
|
protected URI resolve(URI serverUri) {
|
||||||
if (!accepts(serverUri)) {
|
return serverUri;
|
||||||
throw new IllegalArgumentException("This provider does not accept " + serverUri);
|
|
||||||
}
|
|
||||||
|
|
||||||
return new GenericAcmeClient(this, serverUri);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,9 +28,6 @@ import javax.net.ssl.SSLContext;
|
||||||
import javax.net.ssl.SSLSocketFactory;
|
import javax.net.ssl.SSLSocketFactory;
|
||||||
import javax.net.ssl.TrustManagerFactory;
|
import javax.net.ssl.TrustManagerFactory;
|
||||||
|
|
||||||
import org.shredzone.acme4j.AcmeClient;
|
|
||||||
import org.shredzone.acme4j.impl.GenericAcmeClient;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An {@link AcmeClientProvider} for <em>Let's Encrypt</em>.
|
* An {@link AcmeClientProvider} for <em>Let's Encrypt</em>.
|
||||||
* <p>
|
* <p>
|
||||||
|
@ -57,44 +54,7 @@ public class LetsEncryptAcmeClientProvider extends AbstractAcmeClientProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AcmeClient connect(URI serverUri) {
|
|
||||||
return createAcmeClient(resolve(serverUri));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public HttpURLConnection openConnection(URI uri) throws IOException {
|
|
||||||
HttpURLConnection conn = super.openConnection(uri);
|
|
||||||
if (conn instanceof HttpsURLConnection) {
|
|
||||||
((HttpsURLConnection) conn).setSSLSocketFactory(createSocketFactory());
|
|
||||||
}
|
|
||||||
return conn;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates an {@link AcmeClient} for the given directory URI.
|
|
||||||
*
|
|
||||||
* @param directoryUri
|
|
||||||
* Directory {@link URI}
|
|
||||||
* @return {@link AcmeClient}
|
|
||||||
*/
|
|
||||||
protected AcmeClient createAcmeClient(URI directoryUri) {
|
|
||||||
return new GenericAcmeClient(this, directoryUri);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Resolves the server URI and returns the matching directory URI.
|
|
||||||
*
|
|
||||||
* @param serverUri
|
|
||||||
* Server {@link URI} to resolve
|
|
||||||
* @return Directory {@link URI}
|
|
||||||
* @throws IllegalArgumentException
|
|
||||||
* if the server URI cannot be resolved
|
|
||||||
*/
|
|
||||||
protected URI resolve(URI serverUri) {
|
protected URI resolve(URI serverUri) {
|
||||||
if (!accepts(serverUri)) {
|
|
||||||
throw new IllegalArgumentException("Unknown URI " + serverUri);
|
|
||||||
}
|
|
||||||
|
|
||||||
String path = serverUri.getPath();
|
String path = serverUri.getPath();
|
||||||
String directoryUri;
|
String directoryUri;
|
||||||
if (path == null || "".equals(path) || "/".equals(path) || "/v01".equals(path)) {
|
if (path == null || "".equals(path) || "/".equals(path) || "/v01".equals(path)) {
|
||||||
|
@ -112,6 +72,15 @@ public class LetsEncryptAcmeClientProvider extends AbstractAcmeClientProvider {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HttpURLConnection openConnection(URI uri) throws IOException {
|
||||||
|
HttpURLConnection conn = super.openConnection(uri);
|
||||||
|
if (conn instanceof HttpsURLConnection) {
|
||||||
|
((HttpsURLConnection) conn).setSSLSocketFactory(createSocketFactory());
|
||||||
|
}
|
||||||
|
return conn;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Lazily creates an {@link SSLSocketFactory} that exclusively accepts the Let's
|
* Lazily creates an {@link SSLSocketFactory} that exclusively accepts the Let's
|
||||||
* Encrypt certificate.
|
* Encrypt certificate.
|
||||||
|
|
Loading…
Reference in New Issue