1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one 3 * or more contributor license agreements. See the NOTICE file 4 * distributed with this work for additional information 5 * regarding copyright ownership. The ASF licenses this file 6 * to you under the Apache License, Version 2.0 (the 7 * "License"); you may not use this file except in compliance 8 * with the License. You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, 13 * software distributed under the License is distributed on an 14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 * KIND, either express or implied. See the License for the 16 * specific language governing permissions and limitations 17 * under the License. 18 */ 19 package org.eclipse.aether.spi.connector.layout; 20 21 import java.net.URI; 22 import java.util.List; 23 24 import org.eclipse.aether.artifact.Artifact; 25 import org.eclipse.aether.metadata.Metadata; 26 import org.eclipse.aether.spi.connector.checksum.ChecksumAlgorithmFactory; 27 28 import static java.util.Objects.requireNonNull; 29 30 /** 31 * The layout for a remote repository whose artifacts/metadata can be addressed via URIs. 32 * <p> 33 * <strong>Note:</strong> Implementations must be stateless. 34 */ 35 public interface RepositoryLayout { 36 37 /** 38 * A descriptor for a checksum location. This descriptor simply associates the location of a checksum file with the 39 * underlying checksum algorithm used to calculate/verify it. 40 */ 41 final class ChecksumLocation { 42 private final URI location; 43 44 private final ChecksumAlgorithmFactory checksumAlgorithmFactory; 45 46 /** 47 * Creates a new checksum file descriptor with the specified algorithm and location. The method 48 * {@link #forLocation(URI, ChecksumAlgorithmFactory)} is usually more convenient though. 49 * 50 * @param location The relative URI to the checksum file within a repository, must not be {@code 51 * null}. 52 * @param checksumAlgorithmFactory The checksum type used to calculate the checksum, must not be {@code null}. 53 */ 54 public ChecksumLocation(URI location, ChecksumAlgorithmFactory checksumAlgorithmFactory) { 55 verify(location, checksumAlgorithmFactory); 56 this.location = location; 57 this.checksumAlgorithmFactory = checksumAlgorithmFactory; 58 } 59 60 /** 61 * Creates a checksum descriptor for the specified artifact/metadata location and algorithm. The location 62 * of the checksum file itself is derived from the supplied resource URI by appending the file extension 63 * specified by the algorithm factory. See {@link ChecksumAlgorithmFactory#getFileExtension()}. 64 * 65 * @param location The relative URI to the artifact/metadata whose checksum file is being 66 * obtained, must not be 67 * {@code null} and must not have a query or fragment part. 68 * @param checksumAlgorithmFactory The algorithm used to calculate the checksum, must not be {@code null}. 69 * @return The checksum file descriptor, never {@code null}. 70 */ 71 public static ChecksumLocation forLocation(URI location, ChecksumAlgorithmFactory checksumAlgorithmFactory) { 72 verify(location, checksumAlgorithmFactory); 73 if (location.getRawQuery() != null) { 74 throw new IllegalArgumentException("resource location must not have query parameters: " + location); 75 } 76 if (location.getRawFragment() != null) { 77 throw new IllegalArgumentException("resource location must not have a fragment: " + location); 78 } 79 return new ChecksumLocation( 80 URI.create(location + "." + checksumAlgorithmFactory.getFileExtension()), checksumAlgorithmFactory); 81 } 82 83 private static void verify(URI location, ChecksumAlgorithmFactory checksumAlgorithmFactory) { 84 requireNonNull(location, "checksum location cannot be null"); 85 if (location.isAbsolute()) { 86 throw new IllegalArgumentException("checksum location must be relative"); 87 } 88 requireNonNull(checksumAlgorithmFactory, "checksum algorithm factory cannot be null"); 89 } 90 91 /** 92 * Gets the {@link ChecksumAlgorithmFactory} that is used to calculate the checksum. 93 * 94 * @return The checksum factory, never {@code null}. 95 */ 96 public ChecksumAlgorithmFactory getChecksumAlgorithmFactory() { 97 return checksumAlgorithmFactory; 98 } 99 100 /** 101 * Gets the location of the checksum file with a remote repository. The URI is relative to the root directory of 102 * the repository. 103 * 104 * @return The relative URI to the checksum file, never {@code null}. 105 */ 106 public URI getLocation() { 107 return location; 108 } 109 110 @Override 111 public String toString() { 112 return location + " (" + checksumAlgorithmFactory.getName() + ")"; 113 } 114 } 115 116 /** 117 * Returns immutable list of {@link ChecksumAlgorithmFactory} this instance of layout uses, never {@code null}. 118 * The order also represents the order how remote external checksums are retrieved and validated. 119 * 120 * @see org.eclipse.aether.spi.connector.checksum.ChecksumPolicy.ChecksumKind 121 * @since 1.8.0 122 */ 123 List<ChecksumAlgorithmFactory> getChecksumAlgorithmFactories(); 124 125 /** 126 * Tells whether given artifact have remote external checksums according to current layout or not. If it returns 127 * {@code true}, then layout configured checksums will be expected: on upload they will be calculated and deployed 128 * along artifact, on download they will be retrieved and validated. 129 * 130 * If it returns {@code false} the given artifacts will have checksums omitted: on upload they will not be 131 * calculated and deployed, and on download they will be not retrieved nor validated. 132 * 133 * The result affects only layout provided checksums. See 134 * {@link org.eclipse.aether.spi.connector.checksum.ChecksumPolicy.ChecksumKind#REMOTE_EXTERNAL}. 135 * On download, the {@link org.eclipse.aether.spi.connector.layout.RepositoryLayout#getChecksumAlgorithmFactories()} 136 * layout required checksums are calculated, and non layout-provided checksums are still utilized. 137 * 138 * Typical case to return {@code false} (to omit checksums) is for artifact signatures, that are already a 139 * "sub-artifact" of some main artifact (for example a JAR), and they can be validated by some other means. 140 * 141 * @see org.eclipse.aether.spi.connector.checksum.ChecksumPolicy.ChecksumKind 142 * @see #getChecksumAlgorithmFactories() 143 * @since 1.8.0 144 */ 145 boolean hasChecksums(Artifact artifact); 146 147 /** 148 * Gets the location within a remote repository where the specified artifact resides. The URI is relative to the 149 * root directory of the repository. 150 * 151 * @param artifact The artifact to get the URI for, must not be {@code null}. 152 * @param upload {@code false} if the artifact is being downloaded, {@code true} if the artifact is being 153 * uploaded. 154 * @return The relative URI to the artifact, never {@code null}. 155 */ 156 URI getLocation(Artifact artifact, boolean upload); 157 158 /** 159 * Gets the location within a remote repository where the specified metadata resides. The URI is relative to the 160 * root directory of the repository. 161 * 162 * @param metadata The metadata to get the URI for, must not be {@code null}. 163 * @param upload {@code false} if the metadata is being downloaded, {@code true} if the metadata is being 164 * uploaded. 165 * @return The relative URI to the metadata, never {@code null}. 166 */ 167 URI getLocation(Metadata metadata, boolean upload); 168 169 /** 170 * Gets the checksums files that a remote repository keeps to help detect data corruption during transfers of the 171 * specified artifact. 172 * 173 * @param artifact The artifact to get the checksum files for, must not be {@code null}. 174 * @param upload {@code false} if the checksums are being downloaded/verified, {@code true} if the checksums are 175 * being uploaded/created. 176 * @param location The relative URI to the artifact within the repository as previously obtained from 177 * {@link #getLocation(Artifact, boolean)}, must not be {@code null}. 178 * @return The checksum files for the given artifact, possibly empty but never {@code null}. If empty, that means 179 * that this layout does not provide checksums for given artifact. 180 */ 181 List<ChecksumLocation> getChecksumLocations(Artifact artifact, boolean upload, URI location); 182 183 /** 184 * Gets the checksums files that a remote repository keeps to help detect data corruption during transfers of the 185 * specified metadata. 186 * 187 * @param metadata The metadata to get the checksum files for, must not be {@code null}. 188 * @param upload {@code false} if the checksums are being downloaded/verified, {@code true} if the checksums are 189 * being uploaded/created. 190 * @param location The relative URI to the metadata within the repository as previously obtained from 191 * {@link #getLocation(Metadata, boolean)}, must not be {@code null}. 192 * @return The checksum files for the given metadata, possibly empty but never {@code null}. If empty, that means 193 * that this layout does not provide checksums for given artifact. 194 */ 195 List<ChecksumLocation> getChecksumLocations(Metadata metadata, boolean upload, URI location); 196 }