No need to lazy-load provider in session

pull/32/head
Richard Körber 2017-04-14 12:03:41 +02:00
parent e50c5797d4
commit 08eaa61f75
2 changed files with 19 additions and 27 deletions

View File

@ -17,13 +17,12 @@ import java.net.URI;
import java.security.KeyPair; import java.security.KeyPair;
import java.time.Duration; import java.time.Duration;
import java.time.Instant; import java.time.Instant;
import java.util.ArrayList;
import java.util.EnumMap; import java.util.EnumMap;
import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.Objects; import java.util.Objects;
import java.util.ServiceLoader; import java.util.ServiceLoader;
import java.util.stream.StreamSupport;
import org.shredzone.acme4j.challenge.Challenge; import org.shredzone.acme4j.challenge.Challenge;
import org.shredzone.acme4j.challenge.TokenChallenge; import org.shredzone.acme4j.challenge.TokenChallenge;
@ -42,9 +41,9 @@ import org.shredzone.acme4j.util.JSON;
public class Session { public class Session {
private final Map<Resource, URI> resourceMap = new EnumMap<>(Resource.class); private final Map<Resource, URI> resourceMap = new EnumMap<>(Resource.class);
private final URI serverUri; private final URI serverUri;
private final AcmeProvider provider;
private KeyPair keyPair; private KeyPair keyPair;
private AcmeProvider provider;
private byte[] nonce; private byte[] nonce;
private JSON directoryJson; private JSON directoryJson;
private Metadata metadata; private Metadata metadata;
@ -70,10 +69,25 @@ public class Session {
* {@link URI} of the ACME server * {@link URI} of the ACME server
* @param keyPair * @param keyPair
* {@link KeyPair} of the ACME account * {@link KeyPair} of the ACME account
* @throws IllegalArgumentException
* if no ACME provider was found for the server URI.
*/ */
public Session(URI serverUri, KeyPair keyPair) { public Session(URI serverUri, KeyPair keyPair) {
this.serverUri = Objects.requireNonNull(serverUri, "serverUri"); this.serverUri = Objects.requireNonNull(serverUri, "serverUri");
this.keyPair = Objects.requireNonNull(keyPair, "keyPair"); this.keyPair = Objects.requireNonNull(keyPair, "keyPair");
final URI localServerUri = serverUri;
Iterable<AcmeProvider> providers = ServiceLoader.load(AcmeProvider.class);
provider = StreamSupport.stream(providers.spliterator(), false)
.filter(p -> p.accepts(localServerUri))
.reduce((a, b) -> {
throw new IllegalArgumentException("Both ACME providers "
+ a.getClass().getSimpleName() + " and "
+ b.getClass().getSimpleName() + " accept "
+ localServerUri + ". Please check your classpath.");
})
.orElseThrow(() -> new IllegalArgumentException("No ACME provider found for " + localServerUri));
} }
/** /**
@ -128,32 +142,10 @@ public class Session {
/** /**
* Returns the {@link AcmeProvider} that is used for this session. * Returns the {@link AcmeProvider} that is used for this session.
* <p>
* The {@link AcmeProvider} instance is lazily created and cached.
* *
* @return {@link AcmeProvider} * @return {@link AcmeProvider}
*/ */
public AcmeProvider provider() { public AcmeProvider provider() {
synchronized (this) {
if (provider == null) {
List<AcmeProvider> candidates = new ArrayList<>();
for (AcmeProvider acp : ServiceLoader.load(AcmeProvider.class)) {
if (acp.accepts(serverUri)) {
candidates.add(acp);
}
}
if (candidates.isEmpty()) {
throw new IllegalArgumentException("No ACME provider found for " + serverUri);
} else if (candidates.size() > 1) {
throw new IllegalStateException("There are " + candidates.size() + " "
+ AcmeProvider.class.getSimpleName() + " accepting " + serverUri
+ ". Please check your classpath.");
} else {
provider = candidates.get(0);
}
}
}
return provider; return provider;
} }

View File

@ -71,9 +71,9 @@ public class SessionProviderTest {
/** /**
* There are two testing providers accepting {@code acme://example.net}. Test that * There are two testing providers accepting {@code acme://example.net}. Test that
* connecting to this URI will result in an {@link IllegalStateException}. * connecting to this URI will result in an {@link IllegalArgumentException}.
*/ */
@Test(expected = IllegalStateException.class) @Test(expected = IllegalArgumentException.class)
public void testDuplicate() throws Exception { public void testDuplicate() throws Exception {
new Session(new URI("acme://example.net"), keyPair).provider(); new Session(new URI("acme://example.net"), keyPair).provider();
} }