Remove all deprecated code

master
Richard Körber 2025-04-26 13:31:27 +02:00
parent feee96444f
commit ce60dc9368
No known key found for this signature in database
GPG Key ID: AAB9FD19C78AA3E0
16 changed files with 24 additions and 240 deletions

View File

@ -22,7 +22,6 @@ import java.util.Optional;
import edu.umd.cs.findbugs.annotations.Nullable;
import org.shredzone.acme4j.exception.AcmeException;
import org.shredzone.acme4j.exception.AcmeLazyLoadingException;
import org.shredzone.acme4j.exception.AcmeRetryAfterException;
import org.shredzone.acme4j.toolbox.JSON;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -55,7 +54,7 @@ public abstract class AcmeJsonResource extends AcmeResource {
/**
* Returns the JSON representation of the resource data.
* <p>
* If there is no data, {@link #update()} is invoked to fetch it from the server.
* If there is no data, {@link #fetch()} is invoked to fetch it from the server.
* <p>
* This method can be used to read proprietary data from the resources.
*
@ -109,34 +108,6 @@ public abstract class AcmeJsonResource extends AcmeResource {
retryAfter = null;
}
/**
* Updates this resource, by fetching the current resource data from the server.
* <p>
* Note: Prefer to use {@link #fetch()} instead. It is working the same way, but
* returns the Retry-After instant instead of throwing an exception. This method will
* become deprecated in a future release.
*
* @throws AcmeException
* if the resource could not be fetched.
* @throws AcmeRetryAfterException
* the resource is still being processed, and the server returned an estimated
* date when the process will be completed. If you are polling for the
* resource to complete, you should wait for the date given in
* {@link AcmeRetryAfterException#getRetryAfter()}. Note that the status of
* the resource is updated even if this exception was thrown.
* @see #fetch()
* @deprecated Use {@link #fetch()} instead. It returns the retry-after value as
* {@link Optional} instead of throwing an {@link AcmeRetryAfterException}. This
* method will be removed in a future version.
*/
@Deprecated
public void update() throws AcmeException {
var retryAfter = fetch();
if (retryAfter.isPresent()) {
throw new AcmeRetryAfterException(getClass().getSimpleName() + " is not completed yet", retryAfter.get());
}
}
/**
* Updates this resource, by fetching the current resource data from the server.
*
@ -145,7 +116,6 @@ public abstract class AcmeJsonResource extends AcmeResource {
* before trying again. Empty if the server did not return a "Retry-After" header.
* @throws AcmeException
* if the resource could not be fetched.
* @see #update()
* @since 3.2.0
*/
public Optional<Instant> fetch() throws AcmeException {
@ -158,10 +128,6 @@ public abstract class AcmeJsonResource extends AcmeResource {
retryAfterOpt.ifPresent(instant -> LOG.debug("Retry-After: {}", instant));
setRetryAfter(retryAfterOpt.orElse(null));
return retryAfterOpt;
} catch (AcmeRetryAfterException ex) {
LOG.debug("Retry-After while attempting to read the resource", ex);
setRetryAfter(ex.getRetryAfter());
return Optional.of(ex.getRetryAfter());
}
}

View File

@ -154,29 +154,6 @@ public class Order extends AcmeJsonResource implements PollableResource {
return certificate;
}
/**
* Gets the STAR extension's {@link Certificate} if it is available.
*
* @since 2.6
* @throws IllegalStateException
* if the order is not ready yet. You must finalize the order first, and wait
* for the status to become {@link Status#VALID}. It is also thrown if the
* order has been {@link Status#CANCELED}.
* @deprecated Use {@link #getCertificate()} for STAR certificates as well.
*/
@Deprecated
@SuppressFBWarnings("EI_EXPOSE_REP") // behavior is intended
public Certificate getAutoRenewalCertificate() {
if (autoRenewalCertificate == null) {
autoRenewalCertificate = getJSON().get("star-certificate")
.optional()
.map(Value::asURL)
.map(getLogin()::bindCertificate)
.orElseThrow(() -> new IllegalStateException("Order is in an invalid state"));
}
return autoRenewalCertificate;
}
/**
* Returns whether this is a STAR certificate ({@code true}) or a standard certificate
* ({@code false}).

View File

@ -40,38 +40,6 @@ public class Dns01Challenge extends TokenChallenge {
*/
public static final String RECORD_NAME_PREFIX = "_acme-challenge";
/**
* Converts a domain identifier to the Resource Record name to be used for the DNS TXT
* record.
*
* @param identifier
* Domain {@link Identifier} of the domain to be validated
* @return Resource Record name (e.g. {@code _acme-challenge.www.example.org.}, note
* the trailing full stop character).
* @since 2.14
* @deprecated Use {@link #getRRName(Identifier)}
*/
@Deprecated
public static String toRRName(Identifier identifier) {
return toRRName(identifier.getDomain());
}
/**
* Converts a domain identifier to the Resource Record name to be used for the DNS TXT
* record.
*
* @param domain
* Domain name to be validated
* @return Resource Record name (e.g. {@code _acme-challenge.www.example.org.}, note
* the trailing full stop character).
* @since 2.14
* @deprecated Use {@link #getRRName(String)}
*/
@Deprecated
public static String toRRName(String domain) {
return RECORD_NAME_PREFIX + '.' + domain + '.';
}
/**
* Creates a new generic {@link Dns01Challenge} object.
*
@ -92,10 +60,10 @@ public class Dns01Challenge extends TokenChallenge {
* Domain {@link Identifier} of the domain to be validated
* @return Resource Record name (e.g. {@code _acme-challenge.www.example.org.}, note
* the trailing full stop character).
* @since 3.6.0
* @since 4.0.0
*/
public String getRRName(Identifier identifier) {
return toRRName(identifier);
return getRRName(identifier.getDomain());
}
/**
@ -106,10 +74,10 @@ public class Dns01Challenge extends TokenChallenge {
* Domain name to be validated
* @return Resource Record name (e.g. {@code _acme-challenge.www.example.org.}, note
* the trailing full stop character).
* @since 3.6.0
* @since 4.0.0
*/
public String getRRName(String domain) {
return toRRName(domain);
return RECORD_NAME_PREFIX + '.' + domain + '.';
}
/**

View File

@ -30,7 +30,7 @@ import org.shredzone.acme4j.toolbox.JSON;
*
* @draft This class is currently based on an RFC draft. It may be changed or removed
* without notice to reflect future changes to the draft. SemVer rules do not apply here.
* @since 3.6.0
* @since 4.0.0
*/
public class DnsAccount01Challenge extends TokenChallenge {
@Serial

View File

@ -50,7 +50,6 @@ import org.shredzone.acme4j.exception.AcmeException;
import org.shredzone.acme4j.exception.AcmeNetworkException;
import org.shredzone.acme4j.exception.AcmeProtocolException;
import org.shredzone.acme4j.exception.AcmeRateLimitedException;
import org.shredzone.acme4j.exception.AcmeRetryAfterException;
import org.shredzone.acme4j.exception.AcmeServerException;
import org.shredzone.acme4j.exception.AcmeUnauthorizedException;
import org.shredzone.acme4j.exception.AcmeUserActionRequiredException;
@ -132,12 +131,7 @@ public class DefaultConnection implements Connection {
var rc = getResponse().statusCode();
if (rc != HTTP_OK && rc != HTTP_NO_CONTENT) {
var message = "Server responded with HTTP " + rc + " while trying to retrieve a nonce";
var retryAfterInstant = getRetryAfter();
if (retryAfterInstant.isPresent()) {
throw new AcmeRetryAfterException(message, retryAfterInstant.get());
}
throw new AcmeException(message);
throw new AcmeException("Server responded with HTTP " + rc + " while trying to retrieve a nonce");
}
session.setNonce(getNonce()

View File

@ -1,60 +0,0 @@
/*
* acme4j - Java ACME client
*
* Copyright (C) 2016 Richard "Shred" Körber
* http://acme4j.shredzone.org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*/
package org.shredzone.acme4j.exception;
import java.io.Serial;
import java.time.Instant;
import java.util.Objects;
import org.shredzone.acme4j.AcmeJsonResource;
/**
* A server side process has not been completed yet. The server also provides an estimate
* of when the process is expected to complete.
* <p>
* Note: Prefer to use {@link AcmeJsonResource#fetch()}. Invoking
* {@link AcmeJsonResource#update()} and catching this exception is unnecessary
* complicated and a legacy from acme4j v2 which will disappear in a future release.
*
* @deprecated Will be removed in a future version.
*/
@Deprecated
public class AcmeRetryAfterException extends AcmeException {
@Serial
private static final long serialVersionUID = 4461979121063649905L;
private final Instant retryAfter;
/**
* Creates a new {@link AcmeRetryAfterException}.
*
* @param msg
* Error details
* @param retryAfter
* retry-after date returned by the server
*/
public AcmeRetryAfterException(String msg, Instant retryAfter) {
super(msg);
this.retryAfter = Objects.requireNonNull(retryAfter);
}
/**
* Returns the retry-after instant returned by the server. This is only an estimate
* of when a retry attempt might succeed.
*/
public Instant getRetryAfter() {
return retryAfter;
}
}

View File

@ -161,7 +161,7 @@ public final class AcmeUtils {
*
* @param data Byte array to encode
* @return Base32 encoded data (includes padding)
* @since 3.6.0
* @since 4.0.0
*/
public static String base32Encode(byte[] data) {
var result = new StringBuilder();

View File

@ -100,7 +100,7 @@ public class AccountTest {
var login = provider.createLogin();
var account = new Account(login);
account.update();
account.fetch();
assertThat(login.getAccountLocation()).isEqualTo(locationUrl);
assertThat(account.getLocation()).isEqualTo(locationUrl);

View File

@ -136,7 +136,7 @@ public class AuthorizationTest {
provider.putTestChallenge("tls-alpn-01", TlsAlpn01Challenge::new);
var auth = new Authorization(login, locationUrl);
auth.update();
auth.fetch();
assertThat(auth.getIdentifier().getDomain()).isEqualTo("example.org");
assertThat(auth.getStatus()).isEqualTo(Status.VALID);
@ -175,7 +175,7 @@ public class AuthorizationTest {
provider.putTestChallenge("dns-01", Dns01Challenge::new);
var auth = new Authorization(login, locationUrl);
auth.update();
auth.fetch();
assertThat(auth.getIdentifier().getDomain()).isEqualTo("example.org");
assertThat(auth.getStatus()).isEqualTo(Status.VALID);

View File

@ -61,7 +61,7 @@ public class OrderTest {
var login = provider.createLogin();
var order = new Order(login, locationUrl);
order.update();
order.fetch();
try (var softly = new AutoCloseableSoftAssertions()) {
softly.assertThat(order.getStatus()).isEqualTo(Status.PENDING);
@ -206,8 +206,6 @@ public class OrderTest {
softly.assertThat(order.isAutoRenewalCertificate()).isFalse();
softly.assertThat(order.getCertificate().getLocation())
.isEqualTo(url("https://example.com/acme/cert/1234"));
softly.assertThatIllegalStateException()
.isThrownBy(order::getAutoRenewalCertificate);
softly.assertThat(order.getFinalizeLocation()).isEqualTo(finalizeUrl);
var auths = order.getAuthorizations();
@ -245,7 +243,7 @@ public class OrderTest {
var login = provider.createLogin();
var order = new Order(login, locationUrl);
order.update();
order.fetch();
try (var softly = new AutoCloseableSoftAssertions()) {
softly.assertThat(order.isAutoRenewing()).isTrue();
@ -290,8 +288,6 @@ public class OrderTest {
softly.assertThat(order.isAutoRenewalCertificate()).isTrue();
softly.assertThat(order.getCertificate().getLocation())
.isEqualTo(url("https://example.com/acme/cert/1234"));
softly.assertThat(order.getAutoRenewalCertificate().getLocation())
.isEqualTo(url("https://example.com/acme/cert/1234"));
softly.assertThat(order.isAutoRenewing()).isTrue();
softly.assertThat(order.getAutoRenewalStartDate().orElseThrow())
.isEqualTo("2018-01-01T00:00:00Z");

View File

@ -146,7 +146,7 @@ public class ChallengeTest {
var challenge = new Http01Challenge(login, getJSON("triggerHttpChallengeResponse"));
challenge.update();
challenge.fetch();
assertThat(challenge.getStatus()).isEqualTo(Status.VALID);
assertThat(challenge.getLocation()).isEqualTo(locationUrl);

View File

@ -52,7 +52,6 @@ import org.shredzone.acme4j.Session;
import org.shredzone.acme4j.exception.AcmeException;
import org.shredzone.acme4j.exception.AcmeProtocolException;
import org.shredzone.acme4j.exception.AcmeRateLimitedException;
import org.shredzone.acme4j.exception.AcmeRetryAfterException;
import org.shredzone.acme4j.exception.AcmeServerException;
import org.shredzone.acme4j.exception.AcmeUnauthorizedException;
import org.shredzone.acme4j.exception.AcmeUserActionRequiredException;
@ -144,29 +143,25 @@ public class DefaultConnectionTest {
}
/**
* Test that {@link DefaultConnection#getNonce()} handles a retry-after header
* correctly.
* Test that {@link DefaultConnection#getNonce()} handles fails correctly.
*/
@Test
public void testGetNonceFromHeaderRetryAfter() {
public void testGetNonceFromHeaderFailed() throws AcmeException {
var retryAfter = Instant.now().plusSeconds(30L).truncatedTo(SECONDS);
stubFor(head(urlEqualTo(NEW_NONCE_PATH)).willReturn(aResponse()
.withStatus(HttpURLConnection.HTTP_UNAVAILABLE)
.withHeader("Content-Type", "application/problem+json")
.withHeader("Retry-After", DATE_FORMATTER.format(retryAfter))
// do not send a body here because it is a HEAD request!
));
assertThat(session.getNonce()).isNull();
var ex = assertThrows(AcmeRetryAfterException.class, () -> {
assertThatExceptionOfType(AcmeException.class).isThrownBy(() -> {
try (var conn = session.connect()) {
conn.resetNonce(session);
}
});
assertThat(ex.getMessage()).isEqualTo("Server responded with HTTP 503 while trying to retrieve a nonce");
assertThat(ex.getRetryAfter()).isEqualTo(retryAfter);
verify(headRequestedFor(urlEqualTo(NEW_NONCE_PATH)));
}

View File

@ -1,53 +0,0 @@
/*
* 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.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertThrows;
import java.time.Duration;
import java.time.Instant;
import org.junit.jupiter.api.Test;
/**
* Unit tests for {@link AcmeRetryAfterException}.
*/
public class AcmeRetryAfterExceptionTest {
/**
* Test that parameters are correctly returned.
*/
@Test
public void testAcmeRetryAfterException() {
var detail = "Too early";
var retryAfter = Instant.now().plus(Duration.ofMinutes(1));
var ex = new AcmeRetryAfterException(detail, retryAfter);
assertThat(ex.getMessage()).isEqualTo(detail);
assertThat(ex.getRetryAfter()).isEqualTo(retryAfter);
}
/**
* Test that date is required.
*/
@Test
public void testRequiredAcmeRetryAfterException() {
assertThrows(NullPointerException.class, () -> {
throw new AcmeRetryAfterException("null-test", null);
});
}
}

View File

@ -165,7 +165,7 @@ public class AccountIT extends PebbleITBase {
URI.create("mailto:acme2@example.com"));
// Still the same after updating
acct.update();
acct.fetch();
assertThat(acct.getContacts()).contains(
URI.create("mailto:acme@example.com"),
URI.create("mailto:acme2@example.com"));
@ -191,7 +191,7 @@ public class AccountIT extends PebbleITBase {
assertThrows(AcmeServerException.class, () -> {
Session sessionOldKey = new Session(pebbleURI());
Account oldAccount = sessionOldKey.login(location, keyPair).getAccount();
oldAccount.update();
oldAccount.fetch();
}, "Old account key is still accessible");
var sessionNewKey = new Session(pebbleURI());
@ -223,7 +223,7 @@ public class AccountIT extends PebbleITBase {
() -> {
Session session2 = new Session(pebbleURI());
Account acct2 = session2.login(location, keyPair).getAccount();
acct2.update();
acct2.fetch();
}, "Account can still be accessed");
assertThat(ex.getMessage()).isEqualTo("Account has been deactivated");
}

View File

@ -75,7 +75,7 @@ public class OrderWildcardIT extends PebbleITBase {
var challenge = auth.findChallenge(Dns01Challenge.class).orElseThrow();
var challengeDomainName = Dns01Challenge.toRRName(TEST_DOMAIN);
var challengeDomainName = challenge.getRRName(TEST_DOMAIN);
client.dnsAddTxtRecord(challengeDomainName, challenge.getDigest());

View File

@ -2,10 +2,11 @@
This document will help you migrate your code to the latest _acme4j_ version.
## Migration to Version 3.6.0
## Migration to Version 4.0.0
- Removed all methods that were marked as deprecated.
- _acme4j_ requires JRE 17 or higher now.
- In order to keep the API consistent, the static method `Dns01Challenge.toRRName()` is replaced with a class method `Dns01Challenge.getRRName()`. The static method is marked as deprecated, but is still functional.
- In order to keep the API consistent, the static method `Dns01Challenge.toRRName()` is replaced with a class method `Dns01Challenge.getRRName()`. So all you have to do is to invoke `challenge.getRRName()` instead of `Dns01Challenge.toRRName()`.
## Migration to Version 3.5.0