View Javadoc
1   package org.eclipse.aether.internal.impl;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *  http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import java.net.URI;
23  import java.net.URISyntaxException;
24  import java.util.Arrays;
25  import java.util.ArrayList;
26  import java.util.Collections;
27  import java.util.List;
28  
29  import javax.inject.Named;
30  import javax.inject.Singleton;
31  
32  import org.eclipse.aether.RepositorySystemSession;
33  import org.eclipse.aether.artifact.Artifact;
34  import org.eclipse.aether.metadata.Metadata;
35  import org.eclipse.aether.repository.RemoteRepository;
36  import org.eclipse.aether.spi.connector.layout.RepositoryLayout;
37  import org.eclipse.aether.spi.connector.layout.RepositoryLayoutFactory;
38  import org.eclipse.aether.transfer.NoRepositoryLayoutException;
39  import org.eclipse.aether.util.ConfigUtils;
40  
41  import static java.util.Objects.requireNonNull;
42  
43  /**
44   * Provides a Maven-2 repository layout for repositories with content type {@code "default"}.
45   */
46  @Singleton
47  @Named( "maven2" )
48  public final class Maven2RepositoryLayoutFactory
49      implements RepositoryLayoutFactory
50  {
51  
52      static final String CONFIG_PROP_SIGNATURE_CHECKSUMS = "aether.checksums.forSignature";
53      static final String CONFIG_PROP_CHECKSUMS_ALGORITHMS = "aether.checksums.algorithms";
54  
55      static final String DEFAULT_CHECKSUMS_ALGORITHMS = "SHA-1,MD5";
56  
57      private float priority;
58  
59      public float getPriority()
60      {
61          return priority;
62      }
63  
64      /**
65       * Sets the priority of this component.
66       *
67       * @param priority The priority.
68       * @return This component for chaining, never {@code null}.
69       */
70      public Maven2RepositoryLayoutFactory setPriority( float priority )
71      {
72          this.priority = priority;
73          return this;
74      }
75  
76      public RepositoryLayout newInstance( RepositorySystemSession session, RemoteRepository repository )
77          throws NoRepositoryLayoutException
78      {
79          requireNonNull( session, "session cannot be null" );
80          requireNonNull( repository, "repository cannot be null" );
81          if ( !"default".equals( repository.getContentType() ) )
82          {
83              throw new NoRepositoryLayoutException( repository );
84          }
85          boolean forSignature = ConfigUtils.getBoolean( session, false, CONFIG_PROP_SIGNATURE_CHECKSUMS );
86          List<String> checksumsAlgorithms = Arrays.asList( ConfigUtils.getString( session,
87                  DEFAULT_CHECKSUMS_ALGORITHMS, CONFIG_PROP_CHECKSUMS_ALGORITHMS ).split( "," ) );
88  
89          return forSignature
90                  ? new Maven2RepositoryLayout( checksumsAlgorithms )
91                  : new Maven2RepositoryLayoutEx( checksumsAlgorithms );
92      }
93  
94      private static class Maven2RepositoryLayout
95          implements RepositoryLayout
96      {
97  
98          private final List<String> checksumsAlgorithms;
99  
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 }