View Javadoc

1   package org.apache.maven.index.artifact;
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.text.ParseException;
23  import java.text.SimpleDateFormat;
24  
25  import org.codehaus.plexus.component.annotations.Component;
26  
27  /**
28   * An M2 <code>GavCalculator</code>.
29   * 
30   * @author Jason van Zyl
31   * @author Tamas Cservenak
32   */
33  @Component( role = GavCalculator.class, hint = "maven2" )
34  public class M2GavCalculator
35      implements GavCalculator
36  {
37      public Gav pathToGav( String str )
38      {
39          try
40          {
41              String s = str.startsWith( "/" ) ? str.substring( 1 ) : str;
42  
43              int vEndPos = s.lastIndexOf( '/' );
44  
45              if ( vEndPos == -1 )
46              {
47                  return null;
48              }
49  
50              int aEndPos = s.lastIndexOf( '/', vEndPos - 1 );
51  
52              if ( aEndPos == -1 )
53              {
54                  return null;
55              }
56  
57              int gEndPos = s.lastIndexOf( '/', aEndPos - 1 );
58  
59              if ( gEndPos == -1 )
60              {
61                  return null;
62              }
63  
64              String groupId = s.substring( 0, gEndPos ).replace( '/', '.' );
65              String artifactId = s.substring( gEndPos + 1, aEndPos );
66              String version = s.substring( aEndPos + 1, vEndPos );
67              String fileName = s.substring( vEndPos + 1 );
68  
69              boolean checksum = false;
70              boolean signature = false;
71              Gav.HashType checksumType = null;
72              Gav.SignatureType signatureType = null;
73              if ( s.endsWith( ".md5" ) )
74              {
75                  checksum = true;
76                  checksumType = Gav.HashType.md5;
77                  s = s.substring( 0, s.length() - 4 );
78              }
79              else if ( s.endsWith( ".sha1" ) )
80              {
81                  checksum = true;
82                  checksumType = Gav.HashType.sha1;
83                  s = s.substring( 0, s.length() - 5 );
84              }
85  
86              if ( s.endsWith( ".asc" ) )
87              {
88                  signature = true;
89                  signatureType = Gav.SignatureType.gpg;
90                  s = s.substring( 0, s.length() - 4 );
91              }
92  
93              if ( s.endsWith( "maven-metadata.xml" ) )
94              {
95                  return null;
96              }
97  
98              boolean snapshot = version.endsWith( "SNAPSHOT" );
99  
100             if ( snapshot )
101             {
102                 return getSnapshotGav( s, vEndPos, groupId, artifactId, version, fileName, checksum, signature,
103                     checksumType, signatureType );
104             }
105             else
106             {
107                 return getReleaseGav( s, vEndPos, groupId, artifactId, version, fileName, checksum, signature,
108                     checksumType, signatureType );
109             }
110         }
111         catch ( NumberFormatException e )
112         {
113             return null;
114         }
115         catch ( StringIndexOutOfBoundsException e )
116         {
117             return null;
118         }
119     }
120 
121     private Gav getReleaseGav( String s, int vEndPos, String groupId, String artifactId, String version,
122                                String fileName, boolean checksum, boolean signature, Gav.HashType checksumType,
123                                Gav.SignatureType signatureType )
124     {
125         if ( !fileName.startsWith( artifactId + "-" + version + "." )
126             && !fileName.startsWith( artifactId + "-" + version + "-" ) )
127         {
128             // The path does not represents an artifact (filename does not match artifactId-version)!
129             return null;
130         }
131 
132         int nTailPos = vEndPos + artifactId.length() + version.length() + 2;
133 
134         String tail = s.substring( nTailPos );
135 
136         int nExtPos = tail.indexOf( '.' );
137 
138         if ( nExtPos == -1 )
139         {
140             // NX-563: not allowing extensionless paths to be interpreted as artifact
141             return null;
142         }
143 
144         String ext = tail.substring( nExtPos + 1 );
145 
146         String classifier = tail.charAt( 0 ) == '-' ? tail.substring( 1, nExtPos ) : null;
147 
148         return new Gav( groupId, artifactId, version, classifier, ext, null, null, fileName, checksum, checksumType,
149             signature, signatureType );
150     }
151 
152     private Gav getSnapshotGav( String s, int vEndPos, String groupId, String artifactId, String version,
153                                 String fileName, boolean checksum, boolean signature, Gav.HashType checksumType,
154                                 Gav.SignatureType signatureType )
155     {
156 
157         Integer snapshotBuildNo = null;
158 
159         Long snapshotTimestamp = null;
160 
161         int vSnapshotStart = vEndPos + artifactId.length() + version.length() - 9 + 3;
162 
163         String vSnapshot = s.substring( vSnapshotStart, vSnapshotStart + 8 );
164 
165         String classifier = null;
166 
167         String ext = null;
168 
169         if ( "SNAPSHOT".equals( vSnapshot ) )
170         {
171             int nTailPos = vEndPos + artifactId.length() + version.length() + 2;
172 
173             String tail = s.substring( nTailPos );
174 
175             int nExtPos = tail.indexOf( '.' );
176 
177             if ( nExtPos == -1 )
178             {
179                 // NX-563: not allowing extensionless paths to be interpreted as artifact
180                 return null;
181             }
182 
183             ext = tail.substring( nExtPos + 1 );
184 
185             classifier = tail.charAt( 0 ) == '-' ? tail.substring( 1, nExtPos ) : null;
186         }
187         else
188         {
189             StringBuilder sb = new StringBuilder( vSnapshot );
190             sb.append( s.substring( vSnapshotStart + sb.length(), vSnapshotStart + sb.length() + 8 ) );
191 
192             try
193             {
194                 SimpleDateFormat df = new SimpleDateFormat( "yyyyMMdd.HHmmss" );
195                 snapshotTimestamp = Long.valueOf( df.parse( sb.toString() ).getTime() );
196             }
197             catch ( ParseException e )
198             {
199             }
200 
201             int buildNumberPos = vSnapshotStart + sb.length();
202             StringBuilder bnr = new StringBuilder();
203             while ( s.charAt( buildNumberPos ) >= '0' && s.charAt( buildNumberPos ) <= '9' )
204             {
205                 sb.append( s.charAt( buildNumberPos ) );
206                 bnr.append( s.charAt( buildNumberPos ) );
207                 buildNumberPos++;
208             }
209             String snapshotBuildNumber = sb.toString();
210             snapshotBuildNo = Integer.parseInt( bnr.toString() );
211 
212             int n = version.length() > 9 ? version.length() - 9 + 1 : 0;
213 
214             String tail = s.substring( vEndPos + artifactId.length() + n + snapshotBuildNumber.length() + 2 );
215 
216             int nExtPos = tail.indexOf( '.' );
217 
218             if ( nExtPos == -1 )
219             {
220                 // NX-563: not allowing extensionless paths to be interpreted as artifact
221                 return null;
222             }
223 
224             ext = tail.substring( nExtPos + 1 );
225 
226             classifier = tail.charAt( 0 ) == '-' ? tail.substring( 1, nExtPos ) : null;
227 
228             version = version.substring( 0, version.length() - 8 ) + snapshotBuildNumber;
229         }
230 
231         return new Gav( groupId, artifactId, version, classifier, ext, snapshotBuildNo, snapshotTimestamp, fileName,
232             checksum, checksumType, signature, signatureType );
233     }
234 
235     public String gavToPath( Gav gav )
236     {
237         StringBuilder path = new StringBuilder( "/" );
238 
239         path.append( gav.getGroupId().replaceAll( "(?m)(.)\\.", "$1/" ) ); // replace all '.' except the first char
240 
241         path.append( "/" );
242 
243         path.append( gav.getArtifactId() );
244 
245         path.append( "/" );
246 
247         path.append( gav.getBaseVersion() );
248 
249         path.append( "/" );
250 
251         path.append( calculateArtifactName( gav ) );
252 
253         return path.toString();
254     }
255 
256     public String calculateArtifactName( Gav gav )
257     {
258         if ( gav.getName() != null && gav.getName().trim().length() > 0 )
259         {
260             return gav.getName();
261         }
262         else
263         {
264             StringBuilder path = new StringBuilder( gav.getArtifactId() );
265 
266             path.append( "-" );
267 
268             path.append( gav.getVersion() );
269 
270             if ( gav.getClassifier() != null && gav.getClassifier().trim().length() > 0 )
271             {
272                 path.append( "-" );
273 
274                 path.append( gav.getClassifier() );
275             }
276 
277             if ( gav.getExtension() != null )
278             {
279                 path.append( "." );
280 
281                 path.append( gav.getExtension() );
282             }
283 
284             if ( gav.isSignature() )
285             {
286                 path.append( "." );
287 
288                 path.append( gav.getSignatureType().toString() );
289             }
290 
291             if ( gav.isHash() )
292             {
293                 path.append( "." );
294 
295                 path.append( gav.getHashType().toString() );
296             }
297 
298             return path.toString();
299         }
300     }
301 
302 }