1 package org.apache.maven.repository.reporting;
4 * Copyright 2005-2006 The Apache Software Foundation.
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
19 import org.apache.maven.artifact.Artifact;
20 import org.apache.maven.artifact.repository.ArtifactRepository;
21 import org.apache.maven.artifact.repository.metadata.RepositoryMetadata;
22 import org.apache.maven.model.Model;
25 import java.io.FileInputStream;
26 import java.io.FileNotFoundException;
27 import java.io.IOException;
28 import java.io.InputStream;
29 import java.io.InputStreamReader;
31 import java.security.MessageDigest;
32 import java.security.NoSuchAlgorithmException;
35 * This class reports invalid and mismatched checksums of artifacts and metadata files.
36 * It validates MD5 and SHA-1 checksums.
38 public class ChecksumArtifactReporter
39 implements ArtifactReportProcessor, MetadataReportProcessor
41 String ROLE = ChecksumArtifactReporter.class.getName();
43 protected InputStream md5InputStream;
45 protected InputStream sha1InputStream;
47 private boolean isLocal = true;
50 * Validate the checksum of the specified artifact.
57 public void processArtifact( Model model, Artifact artifact, ArtifactReporter reporter,
58 ArtifactRepository repository )
60 //System.out.println( " " );
62 // .println( "===================================== +++++ PROCESS ARTIFACT +++++ ====================================" );
64 String artifactUrl = "";
65 String repositoryUrl = "";
67 if ( !"file".equals( repository.getProtocol() ) )
70 repositoryUrl = repository.getUrl();
74 repositoryUrl = repository.getBasedir();
77 artifactUrl = repositoryUrl + artifact.getGroupId() + "/" + artifact.getArtifactId() + "/" +
78 artifact.getBaseVersion() + "/" + artifact.getArtifactId() + "-" + artifact.getBaseVersion() + "." +
81 //check if checksum files exist
82 boolean md5Exists = getMD5File( artifactUrl );
83 boolean sha1Exists = getSHA1File( artifactUrl );
87 if ( validateChecksum( artifactUrl, "MD5" ) )
89 reporter.addSuccess( artifact );
93 reporter.addFailure( artifact, "MD5 checksum does not match." );
98 reporter.addFailure( artifact, "MD5 checksum file does not exist." );
103 if ( validateChecksum( artifactUrl, "SHA-1" ) )
105 reporter.addSuccess( artifact );
109 reporter.addFailure( artifact, "SHA-1 checksum does not match." );
114 reporter.addFailure( artifact, "SHA-1 checksum file does not exist." );
119 * Validate the checksums of the metadata. Get the metadata file from the
120 * repository then validate the checksum.
122 public void processMetadata( RepositoryMetadata metadata, ArtifactRepository repository, ArtifactReporter reporter )
124 // System.out.println( " " );
126 // .println( "====================================== +++++ PROCESS METADATA +++++ ==============================" );
128 String metadataUrl = "", repositoryUrl = "", filename = "";
129 if ( !"file".equals( repository.getProtocol() ) )
132 repositoryUrl = repository.getUrl() + "/";
133 filename = metadata.getRemoteFilename();
137 repositoryUrl = repository.getBasedir() + "/";
138 filename = metadata.getLocalFilename( repository );
141 if ( metadata.storedInArtifactVersionDirectory() == true && metadata.storedInGroupDirectory() == false )
144 metadataUrl = repositoryUrl + metadata.getGroupId() + "/" + metadata.getArtifactId() + "/" +
145 metadata.getBaseVersion() + "/";
147 else if ( metadata.storedInArtifactVersionDirectory() == false && metadata.storedInGroupDirectory() == true )
150 metadataUrl = repositoryUrl + metadata.getGroupId() + "/";
155 metadataUrl = repositoryUrl + metadata.getGroupId() + "/" + metadata.getArtifactId() + "/";
158 //add the file name of the metadata
159 metadataUrl = metadataUrl + filename;
161 //check if checksum files exist
162 boolean md5Exists = getMD5File( metadataUrl );
163 boolean sha1Exists = getSHA1File( metadataUrl );
167 if ( validateChecksum( metadataUrl, "MD5" ) )
169 reporter.addSuccess( metadata );
173 reporter.addFailure( metadata, "MD5 checksum does not match." );
178 reporter.addFailure( metadata, "MD5 checksum file does not exist." );
183 if ( validateChecksum( metadataUrl, "SHA-1" ) )
185 reporter.addSuccess( metadata );
189 reporter.addFailure( metadata, "SHA-1 checksum does not match." );
194 reporter.addFailure( metadata, "SHA-1 checksum file does not exist." );
200 * Get the MD5 Checksum file. If not found, return false.
202 * @param filename The name of the artifact whose MD5 Checksum file will be retrieved.
205 public boolean getMD5File( String filename )
211 md5InputStream = new FileInputStream( filename + ".md5" );
215 URL url = new URL( filename );
216 md5InputStream = url.openStream();
219 md5InputStream.close();
221 catch ( Exception e )
229 * Get the SHA1 Checksum file. If not found, return false.
231 * @param filename The name of the artifact whose SHA-1 Checksum file will be retrieved.
234 public boolean getSHA1File( String filename )
240 sha1InputStream = new FileInputStream( filename + ".sha1" );
244 URL url = new URL( filename );
245 sha1InputStream = url.openStream();
247 sha1InputStream.close();
249 catch ( Exception e )
257 * Validate the checksum of the file.
259 * @param fileUrl The file to be validated.
260 * @param algo The checksum algorithm used.
263 protected boolean validateChecksum( String fileUrl, String algo )
265 boolean valid = false;
266 byte[] chk1 = null, chk2 = null;
270 //Create checksum for jar file
272 if ( "SHA-1".equals( algo ) )
276 chk1 = createChecksum( fileUrl, algo );
281 chk2 = new byte[chk1.length];
282 File f = new File( fileUrl + ext );
283 InputStream is = null;
285 //check whether the file is located locally or remotely
288 is = new FileInputStream( f );
292 URL url = new URL( fileUrl + ext );
293 is = url.openStream();
296 char[] chars = new char[is.available()];
297 InputStreamReader isr = new InputStreamReader( is );
301 String chk2Str = new String( chars );
302 //System.out.println( "-----" + algo + " Checksum value (CHK1 - created checksum for jar file) ::::: "
303 // + byteArrayToHexStr( chk1 ) );
304 // System.out.println( "-----" + algo + " Checksum value (CHK2 - content of CHECKSUM file) ::::: "
307 if ( chk2Str.toUpperCase().equals( byteArrayToHexStr( chk1 ).toUpperCase() ) )
319 catch ( Exception e )
321 //e.printStackTrace();
327 * Create a checksum from the specified metadata file.
329 * @param filename The file that will be created a checksum.
330 * @param algo The algorithm to be used (MD5, SHA-1)
332 * @throws FileNotFoundException
333 * @throws NoSuchAlgorithmException
334 * @throws IOException
336 protected byte[] createChecksum( String filename, String algo )
337 throws FileNotFoundException, NoSuchAlgorithmException, IOException
340 InputStream fis = null;
341 byte[] buffer = new byte[1024];
343 //check whether file is located locally or remotely
346 fis = new FileInputStream( filename );
350 URL url = new URL( filename );
351 fis = url.openStream();
354 MessageDigest complete = MessageDigest.getInstance( algo );
358 numRead = fis.read( buffer );
361 complete.update( buffer, 0, numRead );
364 while ( numRead != -1 );
367 return complete.digest();
371 * Convert an incoming array of bytes into a string that represents each of
372 * the bytes as two hex characters.
377 public String byteArrayToHexStr( byte[] data )
383 for ( int cnt = 0; cnt < data.length; cnt++ )
385 //Deposit a byte into the 8 lsb of an int.
386 tempInt = data[cnt] & 0xFF;
388 //Get hex representation of the int as a string.
389 tempStr = Integer.toHexString( tempInt );
391 //Append a leading 0 if necessary so that each hex string will contain 2 characters.
392 if ( tempStr.length() == 1 )
394 tempStr = "0" + tempStr;
397 //Concatenate the two characters to the output string.
398 output = output + tempStr;
401 return output.toUpperCase();