1 package org.apache.maven.plugin.install;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import org.apache.commons.codec.binary.Hex;
23 import org.apache.maven.plugin.MojoExecutionException;
24 import org.codehaus.plexus.util.IOUtil;
25 import org.codehaus.plexus.util.StringUtils;
26
27 import java.io.*;
28 import java.security.MessageDigest;
29 import java.util.regex.Matcher;
30 import java.util.regex.Pattern;
31
32
33
34
35 public class SimpleDigester
36 {
37
38 private final MessageDigest messageDigest;
39
40 private static final int bufsize = 65536;
41
42 public SimpleDigester( String algorithm )
43 {
44 messageDigest = DualDigester.getDigester( algorithm );
45 }
46
47 public static SimpleDigester md5()
48 {
49 return new SimpleDigester( "MD5" );
50 }
51
52 public static SimpleDigester sha1()
53 {
54 return new SimpleDigester( "SHA-1" );
55 }
56
57 public String calculate( File file )
58 throws MojoExecutionException
59 {
60 FileInputStream fis = null;
61 BufferedInputStream bis = null;
62
63 try
64 {
65 fis = new FileInputStream( file );
66 int bufsiz = (int) Math.min( file.length(), bufsize );
67 bis = new BufferedInputStream( fis, bufsiz );
68 messageDigest.reset();
69 update( bis );
70 return Hex.encodeHexString( messageDigest.digest() );
71 }
72 catch ( IOException e )
73 {
74 throw new MojoExecutionException(
75 "Failed to calculate " + messageDigest.getAlgorithm() + " checksum for " + file, e );
76 }
77 finally
78 {
79 IOUtil.close( bis );
80 IOUtil.close( fis );
81 }
82 }
83
84 private void update( InputStream is )
85 throws IOException
86 {
87 byte[] buffer = new byte[bufsize];
88 int size = is.read( buffer, 0, bufsize );
89 while ( size >= 0 )
90 {
91 messageDigest.update( buffer, 0, size );
92 size = is.read( buffer, 0, bufsize );
93 }
94 }
95
96 public void verify( File file, String checksum )
97 throws MojoExecutionException
98 {
99 String trimmed = cleanChecksum( checksum, messageDigest.getAlgorithm(), file.getName() );
100 String sum = calculate( file );
101 if ( !StringUtils.equalsIgnoreCase( trimmed, sum ) )
102 {
103 throw new RuntimeException( "Checksum failed (expected=" + trimmed + ", actual=" + sum + ")" );
104 }
105 }
106
107 private static String cleanChecksum( String checksum, String algorithm, String path )
108 {
109 String trimmed = checksum.replace( '\n', ' ' ).trim();
110
111
112 String regex = algorithm.replaceAll( "-", "" ) + "\\s*\\((.*?)\\)\\s*=\\s*([a-fA-F0-9]+)";
113 Matcher m = Pattern.compile( regex ).matcher( trimmed );
114 if ( m.matches() )
115 {
116 String filename = m.group( 1 );
117 if ( !isValidChecksumPattern( filename, path ) )
118 {
119 throw new RuntimeException( "Supplied checksum does not match checksum pattern" );
120 }
121 trimmed = m.group( 2 );
122 }
123 else
124 {
125
126 m = Pattern.compile( "([a-fA-F0-9]+)\\s+\\*?(.+)" ).matcher( trimmed );
127 if ( m.matches() )
128 {
129 String filename = m.group( 2 );
130 if ( !isValidChecksumPattern( filename, path ) )
131 {
132 throw new RuntimeException( "Supplied checksum does not match checksum pattern" );
133 }
134 trimmed = m.group( 1 );
135 }
136 }
137 return trimmed;
138 }
139
140 private static boolean isValidChecksumPattern( String filename, String path )
141 {
142 return filename.endsWith( path ) || filename.equals( "-" );
143 }
144
145 }