Skip to content

Commit e772d31

Browse files
committed
[CODEC-273] Add Path APIs to org.apache.commons.codec.digest.DigestUtils
similar to File APIs.
1 parent 6471942 commit e772d31

6 files changed

Lines changed: 134 additions & 11 deletions

File tree

pom.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,7 @@ limitations under the License.
280280
<configuration>
281281
<excludes>
282282
<exclude>src/test/resources/bla.tar.xz</exclude>
283+
<exclude>src/test/resources/empty.bin</exclude>
283284
</excludes>
284285
</configuration>
285286
</plugin>

src/changes/changes.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ The <action> type attribute can be add,update,fix,remove.
5252
<action issue="CODEC-267" dev="aherbert" due-to="Claude Warren" type="add">Add MurmurHash3.hash32x86 methods and IncrementalHash32x86 to fix sign extension error in hash32 methods.</action>
5353
<action issue="CODEC-269" dev="aherbert" type="fix">Allow repeat calls to MurmurHash3.IncrementalHash32.end() to generate the same value.</action>
5454
<action issue="CODEC-272" dev="ggregory" type="add" due-to="Behrang, Alex Herbert, Gary Gregory">Add RandomAccessFile digest methods #31.</action>
55+
<action issue="CODEC-273" dev="ggregory" type="add" due-to="Gary Gregory">Add Path APIs to org.apache.commons.codec.digest.DigestUtils similar to File APIs.</action>
5556
</release>
5657

5758
<release version="1.13" date="2019-07-20" description="Feature and fix release.">

src/main/java/org/apache/commons/codec/digest/DigestUtils.java

Lines changed: 74 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,14 @@
2020
import java.io.BufferedInputStream;
2121
import java.io.File;
2222
import java.io.FileInputStream;
23-
import java.io.RandomAccessFile;
2423
import java.io.IOException;
2524
import java.io.InputStream;
25+
import java.io.RandomAccessFile;
2626
import java.nio.ByteBuffer;
2727
import java.nio.channels.FileChannel;
28+
import java.nio.file.Files;
29+
import java.nio.file.OpenOption;
30+
import java.nio.file.Path;
2831
import java.security.MessageDigest;
2932
import java.security.NoSuchAlgorithmException;
3033

@@ -117,6 +120,24 @@ public static byte[] digest(final MessageDigest messageDigest, final InputStream
117120
return updateDigest(messageDigest, data).digest();
118121
}
119122

123+
/**
124+
* Reads through a File and returns the digest for the data
125+
*
126+
* @param messageDigest
127+
* The MessageDigest to use (e.g. MD5)
128+
* @param data
129+
* Data to digest
130+
* @param options
131+
* options How to open the file
132+
* @return the digest
133+
* @throws IOException
134+
* On error reading from the stream
135+
* @since 1.14
136+
*/
137+
public static byte[] digest(final MessageDigest messageDigest, final Path data, final OpenOption... options) throws IOException {
138+
return updateDigest(messageDigest, data, options).digest();
139+
}
140+
120141
/**
121142
* Reads through a RandomAccessFile using non-blocking-io (NIO) and returns the digest for the data
122143
*
@@ -1267,6 +1288,26 @@ public static MessageDigest updateDigest(final MessageDigest digest, final Input
12671288
return digest;
12681289
}
12691290

1291+
/**
1292+
* Reads through a Path and updates the digest for the data
1293+
*
1294+
* @param digest
1295+
* The MessageDigest to use (e.g. MD5)
1296+
* @param path
1297+
* Data to digest
1298+
* @param options
1299+
* options How to open the file
1300+
* @return the digest
1301+
* @throws IOException
1302+
* On error reading from the stream
1303+
* @since 1.14
1304+
*/
1305+
public static MessageDigest updateDigest(final MessageDigest digest, final Path path, final OpenOption... options) throws IOException {
1306+
try (final BufferedInputStream inputStream = new BufferedInputStream(Files.newInputStream(path, options))) {
1307+
return updateDigest(digest, inputStream);
1308+
}
1309+
}
1310+
12701311

12711312
/**
12721313
* Reads through a RandomAccessFile and updates the digest for the data using non-blocking-io (NIO)
@@ -1397,6 +1438,22 @@ public byte[] digest(final InputStream data) throws IOException {
13971438
return updateDigest(messageDigest, data).digest();
13981439
}
13991440

1441+
/**
1442+
* Reads through a File and returns the digest for the data
1443+
*
1444+
* @param data
1445+
* Data to digest
1446+
* @param options
1447+
* options How to open the file
1448+
* @return the digest
1449+
* @throws IOException
1450+
* On error reading from the stream
1451+
* @since 1.14
1452+
*/
1453+
public byte[] digest(final Path data, final OpenOption... options) throws IOException {
1454+
return updateDigest(messageDigest, data, options).digest();
1455+
}
1456+
14001457
/**
14011458
* Reads through a byte array and returns the digest for the data.
14021459
*
@@ -1448,6 +1505,22 @@ public String digestAsHex(final File data) throws IOException {
14481505
return Hex.encodeHexString(digest(data));
14491506
}
14501507

1508+
/**
1509+
* Reads through a File and returns the digest for the data
1510+
*
1511+
* @param data
1512+
* Data to digest
1513+
* @param options
1514+
* options How to open the file
1515+
* @return the digest as a hex string
1516+
* @throws IOException
1517+
* On error reading from the stream
1518+
* @since 1.11
1519+
*/
1520+
public String digestAsHex(final Path data, final OpenOption... options) throws IOException {
1521+
return Hex.encodeHexString(digest(data, options));
1522+
}
1523+
14511524
/**
14521525
* Reads through an InputStream and returns the digest for the data
14531526
*

src/test/java/org/apache/commons/codec/digest/DigestUtilsTest.java

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@
2626
import java.io.IOException;
2727
import java.io.RandomAccessFile;
2828
import java.nio.ByteBuffer;
29+
import java.nio.file.Path;
30+
import java.nio.file.Paths;
2931
import java.security.MessageDigest;
3032
import java.util.Random;
3133

@@ -44,6 +46,8 @@
4446
*/
4547
public class DigestUtilsTest {
4648

49+
private static final String EMPTY_STRING = "";
50+
4751
private final byte[] testData = new byte[1024 * 1024];
4852

4953
private File testFile;
@@ -68,6 +72,10 @@ File getTestFile() {
6872
return testFile;
6973
}
7074

75+
Path getTestPath() {
76+
return testFile.toPath();
77+
}
78+
7179
RandomAccessFile getTestRandomAccessFile() {
7280
return testRandomAccessFileWrapper;
7381
}
@@ -106,7 +114,7 @@ public void testInternalNoSuchAlgorithmException() {
106114
@Test
107115
public void testMd2Hex() throws IOException {
108116
// Examples from RFC 1319
109-
assertEquals("8350e5a3e24c153df2275c9f80692773", DigestUtils.md2Hex(""));
117+
assertEquals("8350e5a3e24c153df2275c9f80692773", DigestUtils.md2Hex(EMPTY_STRING));
110118

111119
assertEquals("32ec01ec4a6dac72c0ab96fb34c0b5d1", DigestUtils.md2Hex("a"));
112120

@@ -159,7 +167,7 @@ public void testMd2Length() {
159167
@Test
160168
public void testMd5Hex() throws IOException {
161169
// Examples from RFC 1321
162-
assertEquals("d41d8cd98f00b204e9800998ecf8427e", DigestUtils.md5Hex(""));
170+
assertEquals("d41d8cd98f00b204e9800998ecf8427e", DigestUtils.md5Hex(EMPTY_STRING));
163171

164172
assertEquals("0cc175b9c0f1b6a831c399e269772661", DigestUtils.md5Hex("a"));
165173

@@ -278,16 +286,30 @@ public void testSha1UpdateWithString(){
278286
}
279287

280288
@Test
281-
public void testSha224() {
289+
public void testSha224_StringAsHex() {
282290
assumeJava8();
283291
assertEquals("d14a028c2a3a2bc9476102bb288234c415a2b01f828ea62ac5b3e42f",
284-
new DigestUtils(MessageDigestAlgorithms.SHA_224).digestAsHex(("")));
292+
new DigestUtils(MessageDigestAlgorithms.SHA_224).digestAsHex(EMPTY_STRING));
285293
assertEquals("730e109bd7a8a32b1cb9d9a09aa2325d2430587ddbc0c38bad911525",
286294
new DigestUtils(MessageDigestAlgorithms.SHA_224).digestAsHex("The quick brown fox jumps over the lazy dog"));
287295

288296
// Examples from FIPS 180-4?
289297
}
290298

299+
@Test
300+
public void testSha224_FileAsHex() throws IOException {
301+
assumeJava8();
302+
assertEquals("d14a028c2a3a2bc9476102bb288234c415a2b01f828ea62ac5b3e42f",
303+
new DigestUtils(MessageDigestAlgorithms.SHA_224).digestAsHex(new File("src/test/resources/empty.bin")));
304+
}
305+
306+
@Test
307+
public void testSha224_PathAsHex() throws IOException {
308+
assumeJava8();
309+
assertEquals("d14a028c2a3a2bc9476102bb288234c415a2b01f828ea62ac5b3e42f",
310+
new DigestUtils(MessageDigestAlgorithms.SHA_224).digestAsHex(Paths.get("src/test/resources/empty.bin")));
311+
}
312+
291313
@Test
292314
public void testSha256() throws IOException {
293315
// Examples from FIPS 180-2
@@ -342,7 +364,7 @@ public void testSha3_224() {
342364
// https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/SHA3-224_Msg0.pdf
343365
assertEquals(
344366
"6b4e03423667dbb73b6e15454f0eb1abd4597f9a1b078e3f5b5a6bc7",
345-
DigestUtils.sha3_224Hex(""));
367+
DigestUtils.sha3_224Hex(EMPTY_STRING));
346368
}
347369

348370
@Test
@@ -353,7 +375,7 @@ public void testSha3_256() {
353375
// https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/SHA3-256_Msg0.pdf
354376
assertEquals(
355377
"a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a",
356-
DigestUtils.sha3_256Hex(""));
378+
DigestUtils.sha3_256Hex(EMPTY_STRING));
357379
}
358380

359381
@Test
@@ -364,7 +386,7 @@ public void testSha3_384() {
364386
// https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/SHA3-384_Msg0.pdf
365387
assertEquals(
366388
"0c63a75b845e4f7d01107d852e4c2485c51a50aaaa94fc61995e71bbee983a2ac3713831264adb47fb6bd1e058d5f004",
367-
DigestUtils.sha3_384Hex(""));
389+
DigestUtils.sha3_384Hex(EMPTY_STRING));
368390
}
369391

370392
@Test
@@ -375,7 +397,7 @@ public void testSha3_512() {
375397
// https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/SHA3-512_Msg0.pdf
376398
assertEquals(
377399
"a69f73cca23a9ac5c8b567dc185a756e97c982164fe25859e0d1dcc1475c80a615b2123af1f5f94c11e3e9402c3ac558f500199d95b6d3e301758586281dcd26",
378-
DigestUtils.sha3_512Hex(""));
400+
DigestUtils.sha3_512Hex(EMPTY_STRING));
379401
}
380402

381403
@Test

src/test/java/org/apache/commons/codec/digest/MessageDigestAlgorithmsTest.java

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@
2323
import java.lang.reflect.Field;
2424
import java.lang.reflect.Modifier;
2525
import java.nio.ByteBuffer;
26+
import java.nio.file.OpenOption;
27+
import java.nio.file.Path;
28+
import java.nio.file.StandardOpenOption;
2629
import java.security.MessageDigest;
2730
import java.security.NoSuchAlgorithmException;
2831

@@ -107,6 +110,10 @@ private File getTestFile() {
107110
return digestUtilsTest.getTestFile();
108111
}
109112

113+
private Path getTestPath() {
114+
return digestUtilsTest.getTestPath();
115+
}
116+
110117
private RandomAccessFile getTestRandomAccessFile() {
111118
return digestUtilsTest.getTestRandomAccessFile();
112119
}
@@ -152,8 +159,9 @@ public void testDigestByteBuffer() {
152159
public void testDigestFile() throws IOException {
153160
Assume.assumeTrue(DigestUtils.isAvailable(messageDigestAlgorithm));
154161
Assert.assertArrayEquals(digestTestData(),
155-
DigestUtils.digest(DigestUtils.getDigest(messageDigestAlgorithm), getTestFile()));
156-
Assert.assertArrayEquals(digestTestData(), DigestUtils.digest(DigestUtils.getDigest(messageDigestAlgorithm),getTestFile()));
162+
DigestUtils.digest(DigestUtils.getDigest(messageDigestAlgorithm), getTestFile()));
163+
Assert.assertArrayEquals(digestTestData(),
164+
DigestUtils.digest(DigestUtils.getDigest(messageDigestAlgorithm), getTestFile()));
157165
}
158166

159167
@Test
@@ -164,6 +172,24 @@ public void testDigestInputStream() throws IOException {
164172
Assert.assertArrayEquals(digestTestData(), DigestUtils.digest(DigestUtils.getDigest(messageDigestAlgorithm),new ByteArrayInputStream(getTestData())));
165173
}
166174

175+
private void testDigestPath(OpenOption... options) throws IOException {
176+
Assume.assumeTrue(DigestUtils.isAvailable(messageDigestAlgorithm));
177+
Assert.assertArrayEquals(digestTestData(),
178+
DigestUtils.digest(DigestUtils.getDigest(messageDigestAlgorithm), getTestPath(), options));
179+
Assert.assertArrayEquals(digestTestData(),
180+
DigestUtils.digest(DigestUtils.getDigest(messageDigestAlgorithm), getTestPath(), options));
181+
}
182+
183+
@Test
184+
public void testDigestPathOpenOptionsEmpty() throws IOException {
185+
testDigestPath();
186+
}
187+
188+
@Test
189+
public void testDigestPathStandardOpenOptionRead() throws IOException {
190+
testDigestPath(StandardOpenOption.READ);
191+
}
192+
167193
@Test
168194
public void testGetMessageDigest() {
169195
Assume.assumeTrue(DigestUtils.isAvailable(messageDigestAlgorithm));

src/test/resources/empty.bin

Whitespace-only changes.

0 commit comments

Comments
 (0)