blob: e9a1ccd70b2dede62218658af075b75dca302429 [file] [log] [blame]
/*
* 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 org.eclipse.aether.internal.impl;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import org.eclipse.aether.RepositorySystemSession;
import org.eclipse.aether.artifact.Artifact;
import org.eclipse.aether.internal.impl.checksum.DefaultChecksumAlgorithmFactorySelector;
import org.eclipse.aether.metadata.Metadata;
import org.eclipse.aether.repository.RemoteRepository;
import org.eclipse.aether.spi.connector.checksum.ChecksumAlgorithmFactory;
import org.eclipse.aether.spi.connector.checksum.ChecksumAlgorithmFactorySelector;
import org.eclipse.aether.spi.connector.layout.RepositoryLayout;
import org.eclipse.aether.spi.connector.layout.RepositoryLayoutFactory;
import org.eclipse.aether.transfer.NoRepositoryLayoutException;
import org.eclipse.aether.util.ConfigUtils;
import static java.util.Objects.requireNonNull;
/**
* Provides a Maven-2 repository layout for repositories with content type {@code "default"}.
*/
@Singleton
@Named("maven2")
public final class Maven2RepositoryLayoutFactory implements RepositoryLayoutFactory {
public static final String CONFIG_PROP_CHECKSUMS_ALGORITHMS = "aether.checksums.algorithms";
private static final String DEFAULT_CHECKSUMS_ALGORITHMS = "SHA-1,MD5";
public static final String CONFIG_PROP_OMIT_CHECKSUMS_FOR_EXTENSIONS =
"aether.checksums.omitChecksumsForExtensions";
private static final String DEFAULT_OMIT_CHECKSUMS_FOR_EXTENSIONS = ".asc,.sigstore";
private float priority;
private final ChecksumAlgorithmFactorySelector checksumAlgorithmFactorySelector;
public float getPriority() {
return priority;
}
/**
* Service locator ctor.
*/
@Deprecated
public Maven2RepositoryLayoutFactory() {
this(new DefaultChecksumAlgorithmFactorySelector());
}
@Inject
public Maven2RepositoryLayoutFactory(ChecksumAlgorithmFactorySelector checksumAlgorithmFactorySelector) {
this.checksumAlgorithmFactorySelector = requireNonNull(checksumAlgorithmFactorySelector);
}
/**
* Sets the priority of this component.
*
* @param priority The priority.
* @return This component for chaining, never {@code null}.
*/
public Maven2RepositoryLayoutFactory setPriority(float priority) {
this.priority = priority;
return this;
}
public RepositoryLayout newInstance(RepositorySystemSession session, RemoteRepository repository)
throws NoRepositoryLayoutException {
requireNonNull(session, "session cannot be null");
requireNonNull(repository, "repository cannot be null");
if (!"default".equals(repository.getContentType())) {
throw new NoRepositoryLayoutException(repository);
}
List<ChecksumAlgorithmFactory> checksumsAlgorithms = checksumAlgorithmFactorySelector.selectList(
ConfigUtils.parseCommaSeparatedUniqueNames(ConfigUtils.getString(
session,
DEFAULT_CHECKSUMS_ALGORITHMS,
CONFIG_PROP_CHECKSUMS_ALGORITHMS + "." + repository.getId(),
CONFIG_PROP_CHECKSUMS_ALGORITHMS)));
// ensure uniqueness of (potentially user set) extension list
Set<String> omitChecksumsForExtensions = Arrays.stream(ConfigUtils.getString(
session,
DEFAULT_OMIT_CHECKSUMS_FOR_EXTENSIONS,
CONFIG_PROP_OMIT_CHECKSUMS_FOR_EXTENSIONS)
.split(","))
.filter(s -> s != null && !s.trim().isEmpty())
.collect(Collectors.toSet());
// validation: enforce that all strings in this set are having leading dot
if (omitChecksumsForExtensions.stream().anyMatch(s -> !s.startsWith("."))) {
throw new IllegalArgumentException(String.format(
"The configuration %s contains illegal values: %s (all entries must start with '.' (dot))",
CONFIG_PROP_OMIT_CHECKSUMS_FOR_EXTENSIONS, omitChecksumsForExtensions));
}
return new Maven2RepositoryLayout(
checksumAlgorithmFactorySelector, checksumsAlgorithms, omitChecksumsForExtensions);
}
private static class Maven2RepositoryLayout implements RepositoryLayout {
private final ChecksumAlgorithmFactorySelector checksumAlgorithmFactorySelector;
private final List<ChecksumAlgorithmFactory> configuredChecksumAlgorithms;
private final Set<String> extensionsWithoutChecksums;
private Maven2RepositoryLayout(
ChecksumAlgorithmFactorySelector checksumAlgorithmFactorySelector,
List<ChecksumAlgorithmFactory> configuredChecksumAlgorithms,
Set<String> extensionsWithoutChecksums) {
this.checksumAlgorithmFactorySelector = requireNonNull(checksumAlgorithmFactorySelector);
this.configuredChecksumAlgorithms = Collections.unmodifiableList(configuredChecksumAlgorithms);
this.extensionsWithoutChecksums = requireNonNull(extensionsWithoutChecksums);
}
private URI toUri(String path) {
try {
return new URI(null, null, path, null);
} catch (URISyntaxException e) {
throw new IllegalStateException(e);
}
}
@Override
public List<ChecksumAlgorithmFactory> getChecksumAlgorithmFactories() {
return configuredChecksumAlgorithms;
}
@Override
public boolean hasChecksums(Artifact artifact) {
String artifactExtension = artifact.getExtension(); // ie. pom.asc
for (String extensionWithoutChecksums : extensionsWithoutChecksums) {
if (artifactExtension.endsWith(extensionWithoutChecksums)) {
return false;
}
}
return true;
}
@Override
public URI getLocation(Artifact artifact, boolean upload) {
StringBuilder path = new StringBuilder(128);
path.append(artifact.getGroupId().replace('.', '/')).append('/');
path.append(artifact.getArtifactId()).append('/');
path.append(artifact.getBaseVersion()).append('/');
path.append(artifact.getArtifactId()).append('-').append(artifact.getVersion());
if (artifact.getClassifier().length() > 0) {
path.append('-').append(artifact.getClassifier());
}
if (artifact.getExtension().length() > 0) {
path.append('.').append(artifact.getExtension());
}
return toUri(path.toString());
}
@Override
public URI getLocation(Metadata metadata, boolean upload) {
StringBuilder path = new StringBuilder(128);
if (metadata.getGroupId().length() > 0) {
path.append(metadata.getGroupId().replace('.', '/')).append('/');
if (metadata.getArtifactId().length() > 0) {
path.append(metadata.getArtifactId()).append('/');
if (metadata.getVersion().length() > 0) {
path.append(metadata.getVersion()).append('/');
}
}
}
path.append(metadata.getType());
return toUri(path.toString());
}
@Override
public List<ChecksumLocation> getChecksumLocations(Artifact artifact, boolean upload, URI location) {
if (!hasChecksums(artifact) || isChecksum(artifact.getExtension())) {
return Collections.emptyList();
}
return getChecksumLocations(location);
}
@Override
public List<ChecksumLocation> getChecksumLocations(Metadata metadata, boolean upload, URI location) {
return getChecksumLocations(location);
}
private List<ChecksumLocation> getChecksumLocations(URI location) {
List<ChecksumLocation> checksumLocations = new ArrayList<>(configuredChecksumAlgorithms.size());
for (ChecksumAlgorithmFactory checksumAlgorithmFactory : configuredChecksumAlgorithms) {
checksumLocations.add(ChecksumLocation.forLocation(location, checksumAlgorithmFactory));
}
return checksumLocations;
}
private boolean isChecksum(String extension) {
return checksumAlgorithmFactorySelector.isChecksumExtension(extension);
}
}
}