shaded.org.eclipse.aether.connector.basic.ChecksumValidator Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of spring-cloud-contract-shade Show documentation
Show all versions of spring-cloud-contract-shade Show documentation
Spring Cloud Contract Shaded Dependencies
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package shaded.shaded.org.eclipse.aether.connector.basic;
import java.io.File;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.net.URI;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import shaded.shaded.org.eclipse.aether.spi.connector.checksum.ChecksumAlgorithmFactory;
import shaded.shaded.org.eclipse.aether.spi.connector.checksum.ChecksumPolicy;
import shaded.shaded.org.eclipse.aether.spi.connector.checksum.ChecksumPolicy.ChecksumKind;
import shaded.shaded.org.eclipse.aether.spi.connector.layout.RepositoryLayout.ChecksumLocation;
import shaded.shaded.org.eclipse.aether.spi.io.FileProcessor;
import org.eclipse.aether.transfer.ChecksumFailureException;
import org.eclipse.aether.util.FileUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Performs checksum validation for a downloaded file.
*/
final class ChecksumValidator {
interface ChecksumFetcher {
/**
* Fetches the checksums from remote location into provided local file. The checksums fetched in this way
* are of kind {@link ChecksumKind#REMOTE_EXTERNAL}.
*/
boolean fetchChecksum(URI remote, File local) throws Exception;
}
private static final Logger LOGGER = LoggerFactory.getLogger(ChecksumValidator.class);
private final File dataFile;
private final Collection checksumAlgorithmFactories;
private final FileProcessor fileProcessor;
private final ChecksumFetcher checksumFetcher;
private final ChecksumPolicy checksumPolicy;
private final Map providedChecksums;
private final Collection checksumLocations;
private final Map checksumExpectedValues;
ChecksumValidator(
File dataFile,
Collection checksumAlgorithmFactories,
FileProcessor fileProcessor,
ChecksumFetcher checksumFetcher,
ChecksumPolicy checksumPolicy,
Map providedChecksums,
Collection checksumLocations) {
this.dataFile = dataFile;
this.checksumAlgorithmFactories = checksumAlgorithmFactories;
this.fileProcessor = fileProcessor;
this.checksumFetcher = checksumFetcher;
this.checksumPolicy = checksumPolicy;
this.providedChecksums = providedChecksums;
this.checksumLocations = checksumLocations;
this.checksumExpectedValues = new HashMap<>();
}
public ChecksumCalculator newChecksumCalculator(File targetFile) {
if (checksumPolicy != null) {
return ChecksumCalculator.newInstance(targetFile, checksumAlgorithmFactories);
}
return null;
}
public void validate(Map actualChecksums, Map includedChecksums)
throws ChecksumFailureException {
if (checksumPolicy == null) {
return;
}
if (providedChecksums != null && validateChecksums(actualChecksums, ChecksumKind.PROVIDED, providedChecksums)) {
return;
}
if (includedChecksums != null
&& validateChecksums(actualChecksums, ChecksumKind.REMOTE_INCLUDED, includedChecksums)) {
return;
}
if (!checksumLocations.isEmpty()) {
if (validateExternalChecksums(actualChecksums)) {
return;
}
checksumPolicy.onNoMoreChecksums();
}
}
private boolean validateChecksums(Map actualChecksums, ChecksumKind kind, Map checksums)
throws ChecksumFailureException {
for (Map.Entry entry : checksums.entrySet()) {
String algo = entry.getKey();
Object calculated = actualChecksums.get(algo);
if (!(calculated instanceof String)) {
continue;
}
ChecksumAlgorithmFactory checksumAlgorithmFactory = checksumAlgorithmFactories.stream()
.filter(a -> a.getName().equals(algo))
.findFirst()
.orElse(null);
if (checksumAlgorithmFactory == null) {
continue;
}
String actual = String.valueOf(calculated);
String expected = entry.getValue().toString();
checksumExpectedValues.put(getChecksumFile(checksumAlgorithmFactory), expected);
if (!isEqualChecksum(expected, actual)) {
checksumPolicy.onChecksumMismatch(
checksumAlgorithmFactory.getName(),
kind,
new ChecksumFailureException(expected, kind.name(), actual));
} else if (checksumPolicy.onChecksumMatch(checksumAlgorithmFactory.getName(), kind)) {
return true;
}
}
return false;
}
private boolean validateExternalChecksums(Map actualChecksums) throws ChecksumFailureException {
for (ChecksumLocation checksumLocation : checksumLocations) {
ChecksumAlgorithmFactory factory = checksumLocation.getChecksumAlgorithmFactory();
Object calculated = actualChecksums.get(factory.getName());
if (calculated instanceof Exception) {
checksumPolicy.onChecksumError(
factory.getName(), ChecksumKind.REMOTE_EXTERNAL, new ChecksumFailureException((Exception)
calculated));
continue;
}
File checksumFile = getChecksumFile(checksumLocation.getChecksumAlgorithmFactory());
try (FileUtils.TempFile tempFile = FileUtils.newTempFile()) {
File tmp = tempFile.getPath().toFile();
try {
if (!checksumFetcher.fetchChecksum(checksumLocation.getLocation(), tmp)) {
continue;
}
} catch (Exception e) {
checksumPolicy.onChecksumError(
factory.getName(), ChecksumKind.REMOTE_EXTERNAL, new ChecksumFailureException(e));
continue;
}
String actual = String.valueOf(calculated);
String expected = fileProcessor.readChecksum(tmp);
checksumExpectedValues.put(checksumFile, expected);
if (!isEqualChecksum(expected, actual)) {
checksumPolicy.onChecksumMismatch(
factory.getName(),
ChecksumKind.REMOTE_EXTERNAL,
new ChecksumFailureException(expected, ChecksumKind.REMOTE_EXTERNAL.name(), actual));
} else if (checksumPolicy.onChecksumMatch(factory.getName(), ChecksumKind.REMOTE_EXTERNAL)) {
return true;
}
} catch (IOException e) {
checksumPolicy.onChecksumError(
factory.getName(), ChecksumKind.REMOTE_EXTERNAL, new ChecksumFailureException(e));
}
}
return false;
}
private static boolean isEqualChecksum(String expected, String actual) {
return expected.equalsIgnoreCase(actual);
}
private File getChecksumFile(ChecksumAlgorithmFactory factory) {
return new File(dataFile.getPath() + '.' + factory.getFileExtension());
}
public void retry() {
checksumPolicy.onTransferRetry();
checksumExpectedValues.clear();
}
public boolean handle(ChecksumFailureException exception) {
return checksumPolicy.onTransferChecksumFailure(exception);
}
public void commit() {
for (Map.Entry entry : checksumExpectedValues.entrySet()) {
File checksumFile = entry.getKey();
try {
fileProcessor.writeChecksum(checksumFile, entry.getValue());
} catch (IOException e) {
LOGGER.debug("Failed to write checksum file {}", checksumFile, e);
throw new UncheckedIOException(e);
}
}
checksumExpectedValues.clear();
}
}