001package org.eclipse.aether.internal.impl;
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.net.URISyntaxException;
024import java.util.Arrays;
025import java.util.ArrayList;
026import java.util.Collections;
027import java.util.List;
028
029import javax.inject.Named;
030import javax.inject.Singleton;
031
032import org.eclipse.aether.RepositorySystemSession;
033import org.eclipse.aether.artifact.Artifact;
034import org.eclipse.aether.metadata.Metadata;
035import org.eclipse.aether.repository.RemoteRepository;
036import org.eclipse.aether.spi.connector.layout.RepositoryLayout;
037import org.eclipse.aether.spi.connector.layout.RepositoryLayoutFactory;
038import org.eclipse.aether.transfer.NoRepositoryLayoutException;
039import org.eclipse.aether.util.ConfigUtils;
040
041import static java.util.Objects.requireNonNull;
042
043/**
044 * Provides a Maven-2 repository layout for repositories with content type {@code "default"}.
045 */
046@Singleton
047@Named( "maven2" )
048public final class Maven2RepositoryLayoutFactory
049    implements RepositoryLayoutFactory
050{
051
052    static final String CONFIG_PROP_SIGNATURE_CHECKSUMS = "aether.checksums.forSignature";
053    static final String CONFIG_PROP_CHECKSUMS_ALGORITHMS = "aether.checksums.algorithms";
054
055    static final String DEFAULT_CHECKSUMS_ALGORITHMS = "SHA-1,MD5";
056
057    private float priority;
058
059    public float getPriority()
060    {
061        return priority;
062    }
063
064    /**
065     * Sets the priority of this component.
066     *
067     * @param priority The priority.
068     * @return This component for chaining, never {@code null}.
069     */
070    public Maven2RepositoryLayoutFactory setPriority( float priority )
071    {
072        this.priority = priority;
073        return this;
074    }
075
076    public RepositoryLayout newInstance( RepositorySystemSession session, RemoteRepository repository )
077        throws NoRepositoryLayoutException
078    {
079        requireNonNull( session, "session cannot be null" );
080        requireNonNull( repository, "repository cannot be null" );
081        if ( !"default".equals( repository.getContentType() ) )
082        {
083            throw new NoRepositoryLayoutException( repository );
084        }
085        boolean forSignature = ConfigUtils.getBoolean( session, false, CONFIG_PROP_SIGNATURE_CHECKSUMS );
086        List<String> checksumsAlgorithms = Arrays.asList( ConfigUtils.getString( session,
087                DEFAULT_CHECKSUMS_ALGORITHMS, CONFIG_PROP_CHECKSUMS_ALGORITHMS ).split( "," ) );
088
089        return forSignature
090                ? new Maven2RepositoryLayout( checksumsAlgorithms )
091                : new Maven2RepositoryLayoutEx( checksumsAlgorithms );
092    }
093
094    private static class Maven2RepositoryLayout
095        implements RepositoryLayout
096    {
097
098        private final List<String> checksumsAlgorithms;
099
100        protected Maven2RepositoryLayout( List<String> checksumsAlgorithms )
101        {
102            this.checksumsAlgorithms = checksumsAlgorithms;
103        }
104
105        private URI toUri( String path )
106        {
107            try
108            {
109                return new URI( null, null, path, null );
110            }
111            catch ( URISyntaxException e )
112            {
113                throw new IllegalStateException( e );
114            }
115        }
116
117        public URI getLocation( Artifact artifact, boolean upload )
118        {
119            StringBuilder path = new StringBuilder( 128 );
120
121            path.append( artifact.getGroupId().replace( '.', '/' ) ).append( '/' );
122
123            path.append( artifact.getArtifactId() ).append( '/' );
124
125            path.append( artifact.getBaseVersion() ).append( '/' );
126
127            path.append( artifact.getArtifactId() ).append( '-' ).append( artifact.getVersion() );
128
129            if ( artifact.getClassifier().length() > 0 )
130            {
131                path.append( '-' ).append( artifact.getClassifier() );
132            }
133
134            if ( artifact.getExtension().length() > 0 )
135            {
136                path.append( '.' ).append( artifact.getExtension() );
137            }
138
139            return toUri( path.toString() );
140        }
141
142        public URI getLocation( Metadata metadata, boolean upload )
143        {
144            StringBuilder path = new StringBuilder( 128 );
145
146            if ( metadata.getGroupId().length() > 0 )
147            {
148                path.append( metadata.getGroupId().replace( '.', '/' ) ).append( '/' );
149
150                if ( metadata.getArtifactId().length() > 0 )
151                {
152                    path.append( metadata.getArtifactId() ).append( '/' );
153
154                    if ( metadata.getVersion().length() > 0 )
155                    {
156                        path.append( metadata.getVersion() ).append( '/' );
157                    }
158                }
159            }
160
161            path.append( metadata.getType() );
162
163            return toUri( path.toString() );
164        }
165
166        public List<Checksum> getChecksums( Artifact artifact, boolean upload, URI location )
167        {
168            return getChecksums( location );
169        }
170
171        public List<Checksum> getChecksums( Metadata metadata, boolean upload, URI location )
172        {
173            return getChecksums( location );
174        }
175
176        private List<Checksum> getChecksums( URI location )
177        {
178            List<Checksum> checksums = new ArrayList<>( checksumsAlgorithms.size() );
179            for ( String algorithm : checksumsAlgorithms )
180            {
181                checksums.add( Checksum.forLocation( location, algorithm ) );
182            }
183            return checksums;
184        }
185
186    }
187
188    private static class Maven2RepositoryLayoutEx
189        extends Maven2RepositoryLayout
190    {
191
192        protected Maven2RepositoryLayoutEx( List<String> checksumsAlgorithms )
193        {
194            super( checksumsAlgorithms );
195        }
196
197        @Override
198        public List<Checksum> getChecksums( Artifact artifact, boolean upload, URI location )
199        {
200            if ( isSignature( artifact.getExtension() ) )
201            {
202                return Collections.emptyList();
203            }
204            return super.getChecksums( artifact, upload, location );
205        }
206
207        private boolean isSignature( String extension )
208        {
209            return extension.endsWith( ".asc" );
210        }
211
212    }
213
214}