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