protected AbstractStorageItem doRetrieveRemoteItem(ResourceStoreRequest request)
throws ItemNotFoundException, RemoteAccessException, StorageException
{
final RepositoryItemUid itemUid = createUid(request.getRequestPath());
final RepositoryItemUidLock itemUidLock = itemUid.getLock();
// all this remote download happens in exclusive lock
itemUidLock.lock(Action.create);
try {
List<String> remoteUrls = getRemoteUrls(request);
List<RepositoryItemValidationEvent> events = new ArrayList<>();
Exception lastException = null;
all_urls:
for (String remoteUrl : remoteUrls) {
int retryCount = 1;
if (getRemoteStorageContext() != null) {
RemoteConnectionSettings settings = getRemoteStorageContext().getRemoteConnectionSettings();
if (settings != null) {
retryCount = settings.getRetrievalRetryCount();
}
}
if (log.isDebugEnabled()) {
log.debug("Using URL:" + remoteUrl + ", retryCount=" + retryCount);
}
// Validate the mirror URL
try {
getRemoteStorage().validateStorageUrl(remoteUrl);
}
catch (RemoteStorageException e) {
lastException = e;
logFailedUrl(remoteUrl, e);
continue all_urls; // retry with next url
}
catch (Exception e) {
lastException = e;
// make it logged, this is RuntimeEx
log.warn("Failed URL validation: {}", remoteUrl, e);
continue all_urls; // retry with next url
}
for (int i = 0; i < retryCount; i++) {
try {
// events.clear();
AbstractStorageItem remoteItem =
getRemoteStorage().retrieveItem(this, request, remoteUrl);
remoteItem = doCacheItem(remoteItem);
if (doValidateRemoteItemContent(request, remoteUrl, remoteItem, events)) {
sendContentValidationEvents(request, events, true);
return remoteItem;
}
else {
continue all_urls; // retry with next url
}
}
catch (ItemNotFoundException e) {
lastException = e;
continue all_urls; // retry with next url
}
catch (RemoteAccessException e) {
lastException = e;
logFailedUrl(remoteUrl, e);
continue all_urls; // retry with next url
}
catch (RemoteStorageException e) {
// in case when we were unable to make outbound request
// at all, do not retry
if (e instanceof RemoteStorageTransportException) {
throw e;
}
lastException = e;
// debug, print all
if (log.isDebugEnabled()) {
logFailedUrl(remoteUrl, e);
}
// not debug, only print the message
else {
Throwable t = ExceptionUtils.getRootCause(e);
if (t == null) {
t = e;
}
log.error(
String.format(
"Got RemoteStorageException in proxy repository %s while retrieving remote artifact \"%s\" from URL %s, this is %s (re)try, cause: %s: %s",
RepositoryStringUtils.getHumanizedNameString(this), request.toString(),
remoteUrl, String.valueOf(i + 1), t.getClass().getName(),
t.getMessage()));
}
// do not switch url yet, obey the retries
}
catch (LocalStorageException e) {
lastException = e;
// debug, print all
if (log.isDebugEnabled()) {
logFailedUrl(remoteUrl, e);
}
// not debug, only print the message
else {
Throwable t = ExceptionUtils.getRootCause(e);
if (t == null) {
t = e;
}
log.error(
"Got LocalStorageException in proxy repository {} while caching retrieved artifact \"{}\" got from URL {}, will attempt next mirror",
RepositoryStringUtils.getHumanizedNameString(this),
request,
remoteUrl,
t
);
}
// do not switch url yet, obey the retries
// TODO: IOException _might_ be actually a fatal error (like Nx process have no perms to write to disk)
// but also might come when caching, from inability to READ the HTTP response body (see NEXUS-5898)
// Hence, we will retry here too, and in case of first type of IO problems no harm will be done
// anyway, but will solve the second type of problems, where retry will be attempted
}
catch (RuntimeException e) {
lastException = e;
// make it logged, this is RuntimeEx
log.warn("Failed URL retrieve/cache: {}", remoteUrl, e);
continue all_urls; // retry with next url
}
// retry with same url
}
}
// if we got here, requested item was not retrieved for some reason
sendContentValidationEvents(request, events, false);
try {
getLocalStorage().deleteItem(this, request);
}
catch (ItemNotFoundException e) {
// good, we want this item deleted
}
catch (UnsupportedStorageOperationException e) {
log.warn("Unexpected Exception in " + RepositoryStringUtils.getHumanizedNameString(this), e);
}
if (lastException instanceof StorageException) {
throw (StorageException) lastException;
}
else if (lastException instanceof ItemNotFoundException) {
throw (ItemNotFoundException) lastException;
}
// validation failed, I guess.
throw new ItemNotFoundException(reasonFor(request, this,
"Path %s fetched from remote storage of %s but failed validation.", request.getRequestPath(),
this));
}
finally {
itemUidLock.unlock();
}
}