Throw AcmeLazyLoadingException when lazy loading of a resource failed

pull/55/head
Richard Körber 2017-04-27 22:42:38 +02:00
parent 4478228c5e
commit 34f17a7e6f
6 changed files with 130 additions and 13 deletions

View File

@ -25,6 +25,7 @@ import java.util.List;
import org.shredzone.acme4j.challenge.Challenge; import org.shredzone.acme4j.challenge.Challenge;
import org.shredzone.acme4j.connector.Connection; import org.shredzone.acme4j.connector.Connection;
import org.shredzone.acme4j.exception.AcmeException; import org.shredzone.acme4j.exception.AcmeException;
import org.shredzone.acme4j.exception.AcmeLazyLoadingException;
import org.shredzone.acme4j.exception.AcmeProtocolException; import org.shredzone.acme4j.exception.AcmeProtocolException;
import org.shredzone.acme4j.exception.AcmeRetryAfterException; import org.shredzone.acme4j.exception.AcmeRetryAfterException;
import org.shredzone.acme4j.util.JSON; import org.shredzone.acme4j.util.JSON;
@ -164,7 +165,7 @@ public class Authorization extends AcmeResource {
// ignore... The object was still updated. // ignore... The object was still updated.
LOG.debug("Retry-After", ex); LOG.debug("Retry-After", ex);
} catch (AcmeException ex) { } catch (AcmeException ex) {
throw new AcmeProtocolException("Could not load lazily", ex); throw new AcmeLazyLoadingException(this, ex);
} }
} }
} }

View File

@ -27,6 +27,7 @@ import java.util.List;
import org.shredzone.acme4j.connector.Connection; import org.shredzone.acme4j.connector.Connection;
import org.shredzone.acme4j.connector.Resource; import org.shredzone.acme4j.connector.Resource;
import org.shredzone.acme4j.exception.AcmeException; import org.shredzone.acme4j.exception.AcmeException;
import org.shredzone.acme4j.exception.AcmeLazyLoadingException;
import org.shredzone.acme4j.exception.AcmeProtocolException; import org.shredzone.acme4j.exception.AcmeProtocolException;
import org.shredzone.acme4j.util.AcmeUtils; import org.shredzone.acme4j.util.AcmeUtils;
import org.shredzone.acme4j.util.JSONBuilder; import org.shredzone.acme4j.util.JSONBuilder;
@ -81,8 +82,6 @@ public class Certificate extends AcmeResource {
* Returns the created certificate. * Returns the created certificate.
* *
* @return The created end-entity {@link X509Certificate} without issuer chain. * @return The created end-entity {@link X509Certificate} without issuer chain.
* @throws AcmeProtocolException
* if lazy downloading failed
*/ */
public X509Certificate getCertificate() { public X509Certificate getCertificate() {
lazyDownload(); lazyDownload();
@ -95,8 +94,6 @@ public class Certificate extends AcmeResource {
* @return The created end-entity {@link X509Certificate} and issuer chain. The first * @return The created end-entity {@link X509Certificate} and issuer chain. The first
* certificate is always the end-entity certificate, followed by the * certificate is always the end-entity certificate, followed by the
* intermediate certificates required to build a path to a trusted root. * intermediate certificates required to build a path to a trusted root.
* @throws AcmeProtocolException
* if lazy downloading failed
*/ */
public List<X509Certificate> getCertificateChain() { public List<X509Certificate> getCertificateChain() {
lazyDownload(); lazyDownload();
@ -109,8 +106,6 @@ public class Certificate extends AcmeResource {
* *
* @param out * @param out
* {@link Writer} to write to. The writer is not closed after use. * {@link Writer} to write to. The writer is not closed after use.
* @throws AcmeProtocolException
* if lazy downloading failed
*/ */
public void writeCertificate(Writer out) throws IOException { public void writeCertificate(Writer out) throws IOException {
try { try {
@ -160,14 +155,14 @@ public class Certificate extends AcmeResource {
} }
/** /**
* Lazily downloads the certificate. Throws a runtime {@link AcmeProtocolException} if * Lazily downloads the certificate. Throws a runtime {@link AcmeLazyLoadingException}
* the download failed. * if the download failed.
*/ */
private void lazyDownload() { private void lazyDownload() {
try { try {
download(); download();
} catch (AcmeException ex) { } catch (AcmeException ex) {
throw new AcmeProtocolException("Could not lazily download certificate", ex); throw new AcmeLazyLoadingException(this, ex);
} }
} }

View File

@ -22,7 +22,7 @@ import java.util.List;
import org.shredzone.acme4j.connector.Connection; import org.shredzone.acme4j.connector.Connection;
import org.shredzone.acme4j.exception.AcmeException; import org.shredzone.acme4j.exception.AcmeException;
import org.shredzone.acme4j.exception.AcmeProtocolException; import org.shredzone.acme4j.exception.AcmeLazyLoadingException;
import org.shredzone.acme4j.util.JSON; import org.shredzone.acme4j.util.JSON;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -142,7 +142,7 @@ public class Order extends AcmeResource {
try { try {
update(); update();
} catch (AcmeException ex) { } catch (AcmeException ex) {
throw new AcmeProtocolException("Could not load lazily", ex); throw new AcmeLazyLoadingException(this, ex);
} }
} }
} }

View File

@ -34,6 +34,7 @@ import org.shredzone.acme4j.connector.Connection;
import org.shredzone.acme4j.connector.Resource; import org.shredzone.acme4j.connector.Resource;
import org.shredzone.acme4j.connector.ResourceIterator; import org.shredzone.acme4j.connector.ResourceIterator;
import org.shredzone.acme4j.exception.AcmeException; import org.shredzone.acme4j.exception.AcmeException;
import org.shredzone.acme4j.exception.AcmeLazyLoadingException;
import org.shredzone.acme4j.exception.AcmeProtocolException; import org.shredzone.acme4j.exception.AcmeProtocolException;
import org.shredzone.acme4j.exception.AcmeRetryAfterException; import org.shredzone.acme4j.exception.AcmeRetryAfterException;
import org.shredzone.acme4j.util.JSON; import org.shredzone.acme4j.util.JSON;
@ -305,7 +306,7 @@ public class Registration extends AcmeResource {
// ignore... The object was still updated. // ignore... The object was still updated.
LOG.debug("Retry-After", ex); LOG.debug("Retry-After", ex);
} catch (AcmeException ex) { } catch (AcmeException ex) {
throw new AcmeProtocolException("Could not load lazily", ex); throw new AcmeLazyLoadingException(this, ex);
} }
} }
} }

View File

@ -0,0 +1,61 @@
/*
* acme4j - Java ACME client
*
* Copyright (C) 2016 Richard "Shred" Körber
* http://acme4j.shredzone.org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*/
package org.shredzone.acme4j.exception;
import static java.util.Objects.requireNonNull;
import java.net.URL;
import org.shredzone.acme4j.AcmeResource;
/**
* This runtime exception is thrown when an {@link AcmeException} occured while trying to
* lazy-load a resource from the ACME server.
*/
public class AcmeLazyLoadingException extends RuntimeException {
private static final long serialVersionUID = 1000353433913721901L;
private final Class<? extends AcmeResource> type;
private final URL location;
/**
* Creates a new {@link AcmeLazyLoadingException}.
*
* @param resource
* {@link AcmeResource} to be loaded
* @param cause
* {@link AcmeException} that was raised
*/
public AcmeLazyLoadingException(AcmeResource resource, AcmeException cause) {
super(requireNonNull(resource).getClass().getSimpleName() + " "
+ requireNonNull(resource).getLocation(), requireNonNull(cause));
type = resource.getClass();
location = resource.getLocation();
}
/**
* Returns the {@link AcmeResource} type of the resource that could not be loaded.
*/
public Class<? extends AcmeResource> getType() {
return type;
}
/**
* Returns the location of the resource that could not be loaded.
*/
public URL getLocation() {
return location;
}
}

View File

@ -0,0 +1,59 @@
/*
* acme4j - Java ACME client
*
* Copyright (C) 2016 Richard "Shred" Körber
* http://acme4j.shredzone.org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*/
package org.shredzone.acme4j.exception;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.assertThat;
import static org.mockito.Mockito.mock;
import java.net.URL;
import org.junit.Test;
import org.shredzone.acme4j.AcmeResource;
import org.shredzone.acme4j.Session;
import org.shredzone.acme4j.util.TestUtils;
/**
* Unit tests for {@link AcmeLazyLoadingException}.
*/
public class AcmeLazyLoadingExceptionTest {
private URL resourceUrl = TestUtils.url("http://example.com/acme/resource/123");
@Test
public void testAcmeLazyLoadingException() {
Session session = mock(Session.class);
AcmeResource resource = new TestResource(session, resourceUrl);
AcmeException cause = new AcmeException("Something went wrong");
AcmeLazyLoadingException ex = new AcmeLazyLoadingException(resource, cause);
assertThat(ex, is(instanceOf(RuntimeException.class)));
assertThat(ex.getMessage(), containsString(resourceUrl.toString()));
assertThat(ex.getMessage(), containsString(TestResource.class.getSimpleName()));
assertThat(ex.getCause(), is((Throwable) cause));
assertThat(ex.getType(), is(equalTo(TestResource.class)));
assertThat(ex.getLocation(), is(resourceUrl));
}
private static class TestResource extends AcmeResource {
private static final long serialVersionUID = 1023419539450677538L;
public TestResource(Session session, URL location) {
super(session);
setLocation(location);
}
}
}