001package org.eclipse.aether.spi.connector.layout;
002
003/*
004 * Licensed to the Apache Software Foundation (ASF) under one
005 * or more contributor license agreements.  See the NOTICE file
006 * distributed with this work for additional information
007 * regarding copyright ownership.  The ASF licenses this file
008 * to you under the Apache License, Version 2.0 (the
009 * "License"); you may not use this file except in compliance
010 * with the License.  You may obtain a copy of the License at
011 * 
012 *  http://www.apache.org/licenses/LICENSE-2.0
013 * 
014 * Unless required by applicable law or agreed to in writing,
015 * software distributed under the License is distributed on an
016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017 * KIND, either express or implied.  See the License for the
018 * specific language governing permissions and limitations
019 * under the License.
020 */
021
022import java.net.URI;
023import java.util.List;
024import java.util.Locale;
025
026import org.eclipse.aether.artifact.Artifact;
027import org.eclipse.aether.metadata.Metadata;
028
029/**
030 * The layout for a remote repository whose artifacts/metadata can be addressed via URIs.
031 * <p>
032 * <strong>Note:</strong> Implementations must be stateless.
033 */
034public interface RepositoryLayout
035{
036
037    /**
038     * A descriptor for a checksum file. This descriptor simply associates the location of a checksum file with the
039     * underlying algorithm used to calculate/verify it. Checksum algorithms are denoted by names as used with
040     * {@link java.security.MessageDigest#getInstance(String)}, e.g. {@code "SHA-1"} or {@code "MD5"}.
041     */
042    static final class Checksum
043    {
044
045        private final String algorithm;
046
047        private final URI location;
048
049        /**
050         * Creates a new checksum file descriptor with the specified algorithm and location. The method
051         * {@link #forLocation(URI, String)} is usually more convenient though.
052         * 
053         * @param algorithm The algorithm used to calculate the checksum, must not be {@code null}.
054         * @param location The relative URI to the checksum file within a repository, must not be {@code null}.
055         */
056        public Checksum( String algorithm, URI location )
057        {
058            verify( algorithm, location );
059            this.algorithm = algorithm;
060            this.location = location;
061        }
062
063        /**
064         * Creates a checksum file descriptor for the specified artifact/metadata location and algorithm. The location
065         * of the checksum file itself is derived from the supplied resource URI by appending the file extension
066         * corresponding to the algorithm. The file extension in turn is derived from the algorithm name by stripping
067         * out any hyphen ('-') characters and lower-casing the name, e.g. "SHA-1" is mapped to ".sha1".
068         * 
069         * @param location The relative URI to the artifact/metadata whose checksum file is being obtained, must not be
070         *            {@code null} and must not have a query or fragment part.
071         * @param algorithm The algorithm used to calculate the checksum, must not be {@code null}.
072         * @return The checksum file descriptor, never {@code null}.
073         */
074        public static Checksum forLocation( URI location, String algorithm )
075        {
076            verify( algorithm, location );
077            if ( location.getRawQuery() != null )
078            {
079                throw new IllegalArgumentException( "resource location must not have query parameters: " + location );
080            }
081            if ( location.getRawFragment() != null )
082            {
083                throw new IllegalArgumentException( "resource location must not have a fragment: " + location );
084            }
085            String extension = '.' + algorithm.replace( "-", "" ).toLowerCase( Locale.ENGLISH );
086            return new Checksum( algorithm, URI.create( location.toString() + extension ) );
087        }
088
089        private static void verify( String algorithm, URI location )
090        {
091            if ( algorithm == null || algorithm.length() <= 0 )
092            {
093                throw new IllegalArgumentException( "checksum algorithm has not been specified" );
094            }
095            if ( location == null )
096            {
097                throw new IllegalArgumentException( "checksum location has not been specified" );
098            }
099            if ( location.isAbsolute() )
100            {
101                throw new IllegalArgumentException( "checksum location must be relative" );
102            }
103        }
104
105        /**
106         * Gets the name of the algorithm that is used to calculate the checksum.
107         * 
108         * @return The algorithm name, never {@code null}.
109         * @see java.security.MessageDigest#getInstance(String)
110         */
111        public String getAlgorithm()
112        {
113            return algorithm;
114        }
115
116        /**
117         * Gets the location of the checksum file with a remote repository. The URI is relative to the root directory of
118         * the repository.
119         * 
120         * @return The relative URI to the checksum file, never {@code null}.
121         */
122        public URI getLocation()
123        {
124            return location;
125        }
126
127        @Override
128        public String toString()
129        {
130            return location + " (" + algorithm + ")";
131        }
132
133    }
134
135    /**
136     * Gets the location within a remote repository where the specified artifact resides. The URI is relative to the
137     * root directory of the repository.
138     * 
139     * @param artifact The artifact to get the URI for, must not be {@code null}.
140     * @param upload {@code false} if the artifact is being downloaded, {@code true} if the artifact is being uploaded.
141     * @return The relative URI to the artifact, never {@code null}.
142     */
143    URI getLocation( Artifact artifact, boolean upload );
144
145    /**
146     * Gets the location within a remote repository where the specified metadata resides. The URI is relative to the
147     * root directory of the repository.
148     * 
149     * @param metadata The metadata to get the URI for, must not be {@code null}.
150     * @param upload {@code false} if the metadata is being downloaded, {@code true} if the metadata is being uploaded.
151     * @return The relative URI to the metadata, never {@code null}.
152     */
153    URI getLocation( Metadata metadata, boolean upload );
154
155    /**
156     * Gets the checksums files that a remote repository keeps to help detect data corruption during transfers of the
157     * specified artifact.
158     * 
159     * @param artifact The artifact to get the checksum files for, must not be {@code null}.
160     * @param upload {@code false} if the checksums are being downloaded/verified, {@code true} if the checksums are
161     *            being uploaded/created.
162     * @param location The relative URI to the artifact within the repository as previously obtained from
163     *            {@link #getLocation(Artifact, boolean)}, must not be {@code null}.
164     * @return The checksum files for the given artifact, possibly empty but never {@code null}.
165     */
166    List<Checksum> getChecksums( Artifact artifact, boolean upload, URI location );
167
168    /**
169     * Gets the checksums files that a remote repository keeps to help detect data corruption during transfers of the
170     * specified metadata.
171     * 
172     * @param metadata The metadata to get the checksum files for, must not be {@code null}.
173     * @param upload {@code false} if the checksums are being downloaded/verified, {@code true} if the checksums are
174     *            being uploaded/created.
175     * @param location The relative URI to the metadata within the repository as previously obtained from
176     *            {@link #getLocation(Metadata, boolean)}, must not be {@code null}.
177     * @return The checksum files for the given metadata, possibly empty but never {@code null}.
178     */
179    List<Checksum> getChecksums( Metadata metadata, boolean upload, URI location );
180
181}