diff --git a/cadc-util/build.gradle b/cadc-util/build.gradle
index 564392ae..0b126f90 100644
--- a/cadc-util/build.gradle
+++ b/cadc-util/build.gradle
@@ -15,7 +15,7 @@ sourceCompatibility = 1.8
group = 'org.opencadc'
-version = '1.12.16'
+version = '1.12.17'
description = 'OpenCADC core utility library'
def git_url = 'https://github.com/opencadc/core'
diff --git a/cadc-util/src/main/java/ca/nrc/cadc/net/HttpTransfer.java b/cadc-util/src/main/java/ca/nrc/cadc/net/HttpTransfer.java
index 672d1bb8..69afc107 100644
--- a/cadc-util/src/main/java/ca/nrc/cadc/net/HttpTransfer.java
+++ b/cadc-util/src/main/java/ca/nrc/cadc/net/HttpTransfer.java
@@ -3,7 +3,7 @@
******************* CANADIAN ASTRONOMY DATA CENTRE *******************
************** CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES **************
*
-* (c) 2020. (c) 2020.
+* (c) 2026. (c) 2026.
* Government of Canada Gouvernement du Canada
* National Research Council Conseil national de recherches
* Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6
@@ -90,6 +90,7 @@
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
+import java.net.SocketException;
import java.net.SocketTimeoutException;
import java.net.URI;
import java.net.URL;
@@ -190,13 +191,12 @@ private RetryReason(int val) {
}
/**
- * The maximum retry delay (128 seconds).
+ * The maximum retry delay (90 seconds).
*/
- public static final int MAX_RETRY_DELAY = 128;
- public static final int DEFAULT_RETRY_DELAY = 30;
-
+ public static final int MAX_RETRY_DELAY = 90;
+ public static final int DEFAULT_RETRY_DELAY = 1;
protected int maxRetries = 3;
- protected int retryDelay = 1; // 1, 2, 4 sec
+ protected int retryDelay = DEFAULT_RETRY_DELAY; // 1, 2, 4 sec
protected RetryReason retryReason = RetryReason.TRANSIENT;
protected int numRetries = 0;
@@ -824,13 +824,9 @@ protected void checkTransient(int code, String msg, HttpURLConnection conn)
if (dt == 0) {
if (curRetryDelay == 0) {
curRetryDelay = retryDelay;
- }
-
- if (curRetryDelay > 0) {
+ } else if (curRetryDelay < MAX_RETRY_DELAY) {
dt = curRetryDelay;
curRetryDelay *= 2;
- } else {
- dt = DEFAULT_RETRY_DELAY;
}
}
@@ -839,26 +835,20 @@ protected void checkTransient(int code, String msg, HttpURLConnection conn)
}
protected void checkErrors(URL url, HttpURLConnection conn)
- throws AccessControlException, NotAuthenticatedException,
+ throws AccessControlException, NotAuthenticatedException, PermissionDeniedException,
ByteLimitExceededException, ExpectationFailedException, IllegalArgumentException,
PreconditionFailedException, ResourceAlreadyExistsException, ResourceNotFoundException,
- TransientException, IOException, InterruptedException, RangeNotSatisfiableException {
+ RemoteServiceException, TransientException, IOException, InterruptedException, RangeNotSatisfiableException {
try {
this.responseCode = conn.getResponseCode();
log.debug("checkErrors: " + responseCode + " for " + url);
captureResponseHeaders(conn);
} catch (SocketTimeoutException ex) {
- int timeoutRetryDelay = DEFAULT_RETRY_DELAY;
- if (connectionTimeout > 0 || readTimeout > 0) {
- // user specified timeouts are indicative of how responsive the client expects the
- // server to be...
- timeoutRetryDelay = Math.max(connectionTimeout, readTimeout) / 1000; // ms to sec
- }
- throw new TransientException("connection/read timeout: " + url, ex, timeoutRetryDelay);
+ throw new TransientException("url=" + toLoggableString(url) + " connection/read timeout");
+ } catch (SocketException ex) {
+ throw new RemoteServiceException("url=" + toLoggableString(url) + " " + ex.getMessage());
}
-
-
if (100 <= responseCode && responseCode < 400) {
return;
}
@@ -877,13 +867,13 @@ protected void checkErrors(URL url, HttpURLConnection conn)
// invalid client-cert
throw new NotAuthenticatedException(responseBody);
}
- throw new IOException(responseBody);
+ throw new RemoteServiceException("url=" + toLoggableString(url) + " msg=" + responseBody);
case HttpURLConnection.HTTP_UNAUTHORIZED:
throw new NotAuthenticatedException(responseBody);
case HttpURLConnection.HTTP_FORBIDDEN:
- throw new AccessControlException(responseBody);
- case HTTP_LOCKED:
+ throw new PermissionDeniedException(responseBody);
+ case HttpConstants.HTTP_LOCKED:
throw new ResourceLockedException(responseBody);
case HttpURLConnection.HTTP_NOT_FOUND:
throw new ResourceNotFoundException(responseBody);
@@ -891,19 +881,18 @@ protected void checkErrors(URL url, HttpURLConnection conn)
throw new ResourceAlreadyExistsException(responseBody);
case HttpURLConnection.HTTP_PRECON_FAILED:
throw new PreconditionFailedException(responseBody);
-
case HttpURLConnection.HTTP_ENTITY_TOO_LARGE:
throw new ByteLimitExceededException(responseBody, -1);
- case HTTP_RANGE_NOT_SATISFIABLE:
+ case HttpConstants.HTTP_RANGE_NOT_SATISFIABLE:
throw new RangeNotSatisfiableException(responseBody);
- case HTTP_EXPECT_FAIL:
+ case HttpConstants.HTTP_EXPECT_FAIL:
throw new ExpectationFailedException(responseBody);
case HttpURLConnection.HTTP_INTERNAL_ERROR:
- String loggableURL = toLoggableString(url);
- throw new RemoteServiceException("url=" + loggableURL + " msg=" + responseBody);
+ throw new RemoteServiceException("url=" + toLoggableString(url) + " msg=" + responseBody);
case HttpURLConnection.HTTP_UNAVAILABLE:
+ case HttpURLConnection.HTTP_GATEWAY_TIMEOUT:
throw new TransientException(responseBody);
default:
diff --git a/cadc-util/src/main/java/ca/nrc/cadc/net/PermissionDeniedException.java b/cadc-util/src/main/java/ca/nrc/cadc/net/PermissionDeniedException.java
new file mode 100644
index 00000000..4ceb58c4
--- /dev/null
+++ b/cadc-util/src/main/java/ca/nrc/cadc/net/PermissionDeniedException.java
@@ -0,0 +1,84 @@
+/*
+************************************************************************
+******************* CANADIAN ASTRONOMY DATA CENTRE *******************
+************** CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES **************
+*
+* (c) 2026. (c) 2026.
+* Government of Canada Gouvernement du Canada
+* National Research Council Conseil national de recherches
+* Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6
+* All rights reserved Tous droits réservés
+*
+* NRC disclaims any warranties, Le CNRC dénie toute garantie
+* expressed, implied, or énoncée, implicite ou légale,
+* statutory, of any kind with de quelque nature que ce
+* respect to the software, soit, concernant le logiciel,
+* including without limitation y compris sans restriction
+* any warranty of merchantability toute garantie de valeur
+* or fitness for a particular marchande ou de pertinence
+* purpose. NRC shall not be pour un usage particulier.
+* liable in any event for any Le CNRC ne pourra en aucun cas
+* damages, whether direct or être tenu responsable de tout
+* indirect, special or general, dommage, direct ou indirect,
+* consequential or incidental, particulier ou général,
+* arising from the use of the accessoire ou fortuit, résultant
+* software. Neither the name de l'utilisation du logiciel. Ni
+* of the National Research le nom du Conseil National de
+* Council of Canada nor the Recherches du Canada ni les noms
+* names of its contributors may de ses participants ne peuvent
+* be used to endorse or promote être utilisés pour approuver ou
+* products derived from this promouvoir les produits dérivés
+* software without specific prior de ce logiciel sans autorisation
+* written permission. préalable et particulière
+* par écrit.
+*
+* This file is part of the Ce fichier fait partie du projet
+* OpenCADC project. OpenCADC.
+*
+* OpenCADC is free software: OpenCADC est un logiciel libre ;
+* you can redistribute it and/or vous pouvez le redistribuer ou le
+* modify it under the terms of modifier suivant les termes de
+* the GNU Affero General Public la “GNU Affero General Public
+* License as published by the License” telle que publiée
+* Free Software Foundation, par la Free Software Foundation
+* either version 3 of the : soit la version 3 de cette
+* License, or (at your option) licence, soit (à votre gré)
+* any later version. toute version ultérieure.
+*
+* OpenCADC is distributed in the OpenCADC est distribué
+* hope that it will be useful, dans l’espoir qu’il vous
+* but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE
+* without even the implied GARANTIE : sans même la garantie
+* warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ
+* or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF
+* PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence
+* General Public License for Générale Publique GNU Affero
+* more details. pour plus de détails.
+*
+* You should have received Vous devriez avoir reçu une
+* a copy of the GNU Affero copie de la Licence Générale
+* General Public License along Publique GNU Affero avec
+* with OpenCADC. If not, see OpenCADC ; si ce n’est
+* . pas le cas, consultez :
+* .
+*
+************************************************************************
+*/
+
+package ca.nrc.cadc.net;
+
+import java.security.AccessControlException;
+import org.apache.log4j.Logger;
+
+/**
+ * Replacement for deprecated AccessControlException.
+ *
+ * @author pdowler
+ */
+public class PermissionDeniedException extends AccessControlException {
+ private static final Logger log = Logger.getLogger(PermissionDeniedException.class);
+
+ public PermissionDeniedException(String msg) {
+ super(msg);
+ }
+}