This is an automated email from the ASF dual-hosted git repository.
sebb pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-codec.git
The following commit(s) were added to refs/heads/master by this push:
new 7b27ec6 Normalise EOL (no other changes)
7b27ec6 is described below
commit 7b27ec64b98131ff2bd2e53c9e22638c54b2ede5
Author: Sebb <[email protected]>
AuthorDate: Tue Jun 18 20:16:44 2019 +0100
Normalise EOL (no other changes)
---
README.md | 212 ++--
src/assembly/bin.xml | 88 +-
src/assembly/src.xml | 82 +-
.../java/org/apache/commons/codec/cli/Digest.java | 300 +++---
.../codec/language/DaitchMokotoffSoundex.java | 1104 ++++++++++----------
.../org/apache/commons/codec/language/bm/lang.txt | 32 +-
.../commons/codec/digest/HmacAlgorithmsTest.java | 452 ++++----
.../codec/digest/MessageDigestAlgorithmsTest.java | 328 +++---
.../commons/codec/digest/PureJavaCrc32Test.java | 790 +++++++-------
9 files changed, 1694 insertions(+), 1694 deletions(-)
diff --git a/README.md b/README.md
index e6e33ba..669db91 100644
--- a/README.md
+++ b/README.md
@@ -1,106 +1,106 @@
-<!---
- Licensed to the Apache Software Foundation (ASF) under one or more
- contributor license agreements. See the NOTICE file distributed with
- this work for additional information regarding copyright ownership.
- The ASF licenses this file to You under the Apache License, Version 2.0
- (the "License"); you may not use this file except in compliance with
- the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<!---
- +======================================================================+
- |**** ****|
- |**** THIS FILE IS GENERATED BY THE COMMONS BUILD PLUGIN ****|
- |**** DO NOT EDIT DIRECTLY ****|
- |**** ****|
- +======================================================================+
- | TEMPLATE FILE: readme-md-template.md |
- | commons-build-plugin/trunk/src/main/resources/commons-xdoc-templates |
- +======================================================================+
- | |
- | 1) Re-generate using: mvn commons:readme-md |
- | |
- | 2) Set the following properties in the component's pom: |
- | - commons.componentid (required, alphabetic, lower case) |
- | - commons.release.version (required) |
- | |
- | 3) Example Properties |
- | |
- | <properties> |
- | <commons.componentid>math</commons.componentid> |
- | <commons.release.version>1.2</commons.release.version> |
- | </properties> |
- | |
- +======================================================================+
---->
-Apache Commons Codec
-===================
-
-[](https://travis-ci.org/apache/commons-codec)
-[](https://coveralls.io/r/apache/commons-codec)
-
-The Apache Commons Codec package contains simple encoder and decoders for
- various formats such as Base64 and Hexadecimal. In addition to these
- widely used encoders and decoders, the codec package also maintains a
- collection of phonetic encoding utilities.
-
-Documentation
--------------
-
-More information can be found on the [Apache Commons Codec
homepage](https://commons.apache.org/proper/commons-codec).
-The
[Javadoc](https://commons.apache.org/proper/commons-codec/javadocs/api-release)
can be browsed.
-Questions related to the usage of Apache Commons Codec should be posted to the
[user mailing list][ml].
-
-Where can I get the latest release?
------------------------------------
-You can download source and binaries from our [download
page](https://commons.apache.org/proper/commons-codec/download_codec.cgi).
-
-Alternatively you can pull it from the central Maven repositories:
-
-```xml
-<dependency>
- <groupId>commons-codec</groupId>
- <artifactId>commons-codec</artifactId>
- <version>1.12</version>
-</dependency>
-```
-
-Contributing
-------------
-
-We accept Pull Requests via GitHub. The [developer mailing list][ml] is the
main channel of communication for contributors.
-There are some guidelines which will make applying PRs easier for us:
-+ No tabs! Please use spaces for indentation.
-+ Respect the code style.
-+ Create minimal diffs - disable on save actions like reformat source code or
organize imports. If you feel the source code should be reformatted create a
separate PR for this change.
-+ Provide JUnit tests for your changes and make sure your changes don't break
any existing tests by running ```mvn clean test```.
-
-If you plan to contribute on a regular basis, please consider filing a
[contributor license agreement](https://www.apache.org/licenses/#clas).
-You can learn more about contributing via GitHub in our [contribution
guidelines](CONTRIBUTING.md).
-
-License
--------
-This code is under the [Apache Licence
v2](https://www.apache.org/licenses/LICENSE-2.0).
-
-See the `NOTICE.txt` file for required notices and attributions.
-
-Donations
----------
-You like Apache Commons Codec? Then [donate back to the
ASF](https://www.apache.org/foundation/contributing.html) to support the
development.
-
-Additional Resources
---------------------
-
-+ [Apache Commons Homepage](https://commons.apache.org/)
-+ [Apache Issue Tracker (JIRA)](https://issues.apache.org/jira/browse/CODEC)
-+ [Apache Commons Twitter Account](https://twitter.com/ApacheCommons)
-+ `#apache-commons` IRC channel on `irc.freenode.org`
-
-[ml]:https://commons.apache.org/mail-lists.html
+<!---
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<!---
+ +======================================================================+
+ |**** ****|
+ |**** THIS FILE IS GENERATED BY THE COMMONS BUILD PLUGIN ****|
+ |**** DO NOT EDIT DIRECTLY ****|
+ |**** ****|
+ +======================================================================+
+ | TEMPLATE FILE: readme-md-template.md |
+ | commons-build-plugin/trunk/src/main/resources/commons-xdoc-templates |
+ +======================================================================+
+ | |
+ | 1) Re-generate using: mvn commons:readme-md |
+ | |
+ | 2) Set the following properties in the component's pom: |
+ | - commons.componentid (required, alphabetic, lower case) |
+ | - commons.release.version (required) |
+ | |
+ | 3) Example Properties |
+ | |
+ | <properties> |
+ | <commons.componentid>math</commons.componentid> |
+ | <commons.release.version>1.2</commons.release.version> |
+ | </properties> |
+ | |
+ +======================================================================+
+--->
+Apache Commons Codec
+===================
+
+[](https://travis-ci.org/apache/commons-codec)
+[](https://coveralls.io/r/apache/commons-codec)
+
+The Apache Commons Codec package contains simple encoder and decoders for
+ various formats such as Base64 and Hexadecimal. In addition to these
+ widely used encoders and decoders, the codec package also maintains a
+ collection of phonetic encoding utilities.
+
+Documentation
+-------------
+
+More information can be found on the [Apache Commons Codec
homepage](https://commons.apache.org/proper/commons-codec).
+The
[Javadoc](https://commons.apache.org/proper/commons-codec/javadocs/api-release)
can be browsed.
+Questions related to the usage of Apache Commons Codec should be posted to the
[user mailing list][ml].
+
+Where can I get the latest release?
+-----------------------------------
+You can download source and binaries from our [download
page](https://commons.apache.org/proper/commons-codec/download_codec.cgi).
+
+Alternatively you can pull it from the central Maven repositories:
+
+```xml
+<dependency>
+ <groupId>commons-codec</groupId>
+ <artifactId>commons-codec</artifactId>
+ <version>1.12</version>
+</dependency>
+```
+
+Contributing
+------------
+
+We accept Pull Requests via GitHub. The [developer mailing list][ml] is the
main channel of communication for contributors.
+There are some guidelines which will make applying PRs easier for us:
++ No tabs! Please use spaces for indentation.
++ Respect the code style.
++ Create minimal diffs - disable on save actions like reformat source code or
organize imports. If you feel the source code should be reformatted create a
separate PR for this change.
++ Provide JUnit tests for your changes and make sure your changes don't break
any existing tests by running ```mvn clean test```.
+
+If you plan to contribute on a regular basis, please consider filing a
[contributor license agreement](https://www.apache.org/licenses/#clas).
+You can learn more about contributing via GitHub in our [contribution
guidelines](CONTRIBUTING.md).
+
+License
+-------
+This code is under the [Apache Licence
v2](https://www.apache.org/licenses/LICENSE-2.0).
+
+See the `NOTICE.txt` file for required notices and attributions.
+
+Donations
+---------
+You like Apache Commons Codec? Then [donate back to the
ASF](https://www.apache.org/foundation/contributing.html) to support the
development.
+
+Additional Resources
+--------------------
+
++ [Apache Commons Homepage](https://commons.apache.org/)
++ [Apache Issue Tracker (JIRA)](https://issues.apache.org/jira/browse/CODEC)
++ [Apache Commons Twitter Account](https://twitter.com/ApacheCommons)
++ `#apache-commons` IRC channel on `irc.freenode.org`
+
+[ml]:https://commons.apache.org/mail-lists.html
diff --git a/src/assembly/bin.xml b/src/assembly/bin.xml
index 4c6a171..5762291 100644
--- a/src/assembly/bin.xml
+++ b/src/assembly/bin.xml
@@ -1,44 +1,44 @@
-<!--
- Licensed to the Apache Software Foundation (ASF) under one or more
- contributor license agreements. See the NOTICE file distributed with
- this work for additional information regarding copyright ownership.
- The ASF licenses this file to You under the Apache License, Version 2.0
- (the "License"); you may not use this file except in compliance with
- the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<assembly>
- <id>bin</id>
- <formats>
- <format>tar.gz</format>
- <format>zip</format>
- </formats>
- <includeSiteDirectory>false</includeSiteDirectory>
- <fileSets>
- <fileSet>
- <includes>
- <include>LICENSE.txt</include>
- <include>NOTICE.txt</include>
- <include>RELEASE-NOTES.txt</include>
- </includes>
- </fileSet>
- <fileSet>
- <directory>target</directory>
- <outputDirectory></outputDirectory>
- <includes>
- <include>*.jar</include>
- </includes>
- </fileSet>
- <fileSet>
- <directory>target/site/apidocs</directory>
- <outputDirectory>apidocs</outputDirectory>
- </fileSet>
- </fileSets>
-</assembly>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<assembly>
+ <id>bin</id>
+ <formats>
+ <format>tar.gz</format>
+ <format>zip</format>
+ </formats>
+ <includeSiteDirectory>false</includeSiteDirectory>
+ <fileSets>
+ <fileSet>
+ <includes>
+ <include>LICENSE.txt</include>
+ <include>NOTICE.txt</include>
+ <include>RELEASE-NOTES.txt</include>
+ </includes>
+ </fileSet>
+ <fileSet>
+ <directory>target</directory>
+ <outputDirectory></outputDirectory>
+ <includes>
+ <include>*.jar</include>
+ </includes>
+ </fileSet>
+ <fileSet>
+ <directory>target/site/apidocs</directory>
+ <outputDirectory>apidocs</outputDirectory>
+ </fileSet>
+ </fileSets>
+</assembly>
diff --git a/src/assembly/src.xml b/src/assembly/src.xml
index f7f8f49..4de79c3 100644
--- a/src/assembly/src.xml
+++ b/src/assembly/src.xml
@@ -1,41 +1,41 @@
-<!--
- Licensed to the Apache Software Foundation (ASF) under one or more
- contributor license agreements. See the NOTICE file distributed with
- this work for additional information regarding copyright ownership.
- The ASF licenses this file to You under the Apache License, Version 2.0
- (the "License"); you may not use this file except in compliance with
- the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<assembly>
- <id>src</id>
- <formats>
- <format>tar.gz</format>
- <format>zip</format>
- </formats>
- <baseDirectory>${project.artifactId}-${project.version}-src</baseDirectory>
- <fileSets>
- <fileSet>
- <includes>
- <include>checkstyle*.xml</include>
- <include>LICENSE.txt</include>
- <include>LICENSE-header.txt</include>
- <include>NOTICE.txt</include>
- <include>pmd.xml</include>
- <include>pom.xml</include>
- <include>RELEASE-NOTES*.txt</include>
- <include>TODO</include>
- </includes>
- </fileSet>
- <fileSet>
- <directory>src</directory>
- </fileSet>
- </fileSets>
-</assembly>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<assembly>
+ <id>src</id>
+ <formats>
+ <format>tar.gz</format>
+ <format>zip</format>
+ </formats>
+ <baseDirectory>${project.artifactId}-${project.version}-src</baseDirectory>
+ <fileSets>
+ <fileSet>
+ <includes>
+ <include>checkstyle*.xml</include>
+ <include>LICENSE.txt</include>
+ <include>LICENSE-header.txt</include>
+ <include>NOTICE.txt</include>
+ <include>pmd.xml</include>
+ <include>pom.xml</include>
+ <include>RELEASE-NOTES*.txt</include>
+ <include>TODO</include>
+ </includes>
+ </fileSet>
+ <fileSet>
+ <directory>src</directory>
+ </fileSet>
+ </fileSets>
+</assembly>
diff --git a/src/main/java/org/apache/commons/codec/cli/Digest.java
b/src/main/java/org/apache/commons/codec/cli/Digest.java
index 4f0a064..f6deb36 100644
--- a/src/main/java/org/apache/commons/codec/cli/Digest.java
+++ b/src/main/java/org/apache/commons/codec/cli/Digest.java
@@ -1,150 +1,150 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.commons.codec.cli;
-
-import java.io.File;
-import java.io.IOException;
-import java.nio.charset.Charset;
-import java.security.MessageDigest;
-import java.util.Arrays;
-import java.util.Locale;
-
-import org.apache.commons.codec.binary.Hex;
-import org.apache.commons.codec.digest.DigestUtils;
-import org.apache.commons.codec.digest.MessageDigestAlgorithms;
-
-/**
- * A minimal command line to run digest over files, directories or a string
- *
- * @see #main(String[])
- * @since 1.11
- */
-public class Digest {
-
- /**
- * Runs the digest algorithm in {@code args[0]} on the file in {@code
args[1]}. If there is no {@code args[1]}, use
- * standard input.
- *
- * <p>
- * The algorithm can also be {@code ALL} or {@code *} to output one line
for each known algorithm.
- * </p>
- *
- * @param args
- * {@code args[0]} is one of {@link MessageDigestAlgorithms}
name,
- * {@link MessageDigest} name, {@code ALL}, or {@code *}.
- * {@code args[1+]} is a FILE/DIRECTORY/String.
- * @throws IOException if an error occurs
- */
- public static void main(final String[] args) throws IOException {
- new Digest(args).run();
- }
-
- private final String algorithm;
- private final String[] args;
- private final String[] inputs;
-
- private Digest(final String[] args) {
- if (args == null) {
- throw new IllegalArgumentException("args");
- }
- if (args.length == 0) {
- throw new IllegalArgumentException(
- String.format("Usage: java %s [algorithm]
[FILE|DIRECTORY|string] ...", Digest.class.getName()));
- }
- this.args = args;
- algorithm = args[0];
- if (args.length <= 1) {
- inputs = null;
- } else {
- inputs = new String[args.length -1];
- System.arraycopy(args, 1, inputs, 0, inputs.length);
- }
- }
-
- private void println(final String prefix, final byte[] digest) {
- println(prefix, digest, null);
- }
-
- private void println(final String prefix, final byte[] digest, final
String fileName) {
- // The standard appears to be to print
- // hex, space, then either space or '*' followed by file name
- // where '*' is used for binary files
- // shasum(1) has a -b option which generates " *" separator
- // we don't distinguish binary files at present
- System.out.println(prefix + Hex.encodeHexString(digest) + (fileName !=
null ? " " + fileName : ""));
- }
-
- private void run() throws IOException {
- if (algorithm.equalsIgnoreCase("ALL") || algorithm.equals("*")) {
- run(MessageDigestAlgorithms.values());
- return;
- }
- final MessageDigest messageDigest = DigestUtils.getDigest(algorithm,
null);
- if (messageDigest != null) {
- run("", messageDigest);
- } else {
- run("", DigestUtils.getDigest(algorithm.toUpperCase(Locale.ROOT)));
- }
- }
-
- private void run(final String[] digestAlgorithms) throws IOException {
- for (final String messageDigestAlgorithm : digestAlgorithms) {
- if (DigestUtils.isAvailable(messageDigestAlgorithm)) {
- run(messageDigestAlgorithm + " ", messageDigestAlgorithm);
- }
- }
- }
-
- private void run(final String prefix, final MessageDigest messageDigest)
throws IOException {
- if (inputs == null) {
- println(prefix, DigestUtils.digest(messageDigest, System.in));
- return;
- }
- for(final String source : inputs) {
- final File file = new File(source);
- if (file.isFile()) {
- println(prefix, DigestUtils.digest(messageDigest, file),
source);
- } else if (file.isDirectory()) {
- final File[] listFiles = file.listFiles();
- if (listFiles != null) {
- run(prefix, messageDigest, listFiles);
- }
- } else {
- // use the default charset for the command-line parameter
- final byte[] bytes = source.getBytes(Charset.defaultCharset());
- println(prefix, DigestUtils.digest(messageDigest, bytes));
- }
- }
- }
-
- private void run(final String prefix, final MessageDigest messageDigest,
final File[] files) throws IOException {
- for (final File file : files) {
- if (file.isFile()) {
- println(prefix, DigestUtils.digest(messageDigest, file),
file.getName());
- }
- }
- }
-
- private void run(final String prefix, final String messageDigestAlgorithm)
throws IOException {
- run(prefix, DigestUtils.getDigest(messageDigestAlgorithm));
- }
-
- @Override
- public String toString() {
- return String.format("%s %s", super.toString(), Arrays.toString(args));
- }
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.codec.cli;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.charset.Charset;
+import java.security.MessageDigest;
+import java.util.Arrays;
+import java.util.Locale;
+
+import org.apache.commons.codec.binary.Hex;
+import org.apache.commons.codec.digest.DigestUtils;
+import org.apache.commons.codec.digest.MessageDigestAlgorithms;
+
+/**
+ * A minimal command line to run digest over files, directories or a string
+ *
+ * @see #main(String[])
+ * @since 1.11
+ */
+public class Digest {
+
+ /**
+ * Runs the digest algorithm in {@code args[0]} on the file in {@code
args[1]}. If there is no {@code args[1]}, use
+ * standard input.
+ *
+ * <p>
+ * The algorithm can also be {@code ALL} or {@code *} to output one line
for each known algorithm.
+ * </p>
+ *
+ * @param args
+ * {@code args[0]} is one of {@link MessageDigestAlgorithms}
name,
+ * {@link MessageDigest} name, {@code ALL}, or {@code *}.
+ * {@code args[1+]} is a FILE/DIRECTORY/String.
+ * @throws IOException if an error occurs
+ */
+ public static void main(final String[] args) throws IOException {
+ new Digest(args).run();
+ }
+
+ private final String algorithm;
+ private final String[] args;
+ private final String[] inputs;
+
+ private Digest(final String[] args) {
+ if (args == null) {
+ throw new IllegalArgumentException("args");
+ }
+ if (args.length == 0) {
+ throw new IllegalArgumentException(
+ String.format("Usage: java %s [algorithm]
[FILE|DIRECTORY|string] ...", Digest.class.getName()));
+ }
+ this.args = args;
+ algorithm = args[0];
+ if (args.length <= 1) {
+ inputs = null;
+ } else {
+ inputs = new String[args.length -1];
+ System.arraycopy(args, 1, inputs, 0, inputs.length);
+ }
+ }
+
+ private void println(final String prefix, final byte[] digest) {
+ println(prefix, digest, null);
+ }
+
+ private void println(final String prefix, final byte[] digest, final
String fileName) {
+ // The standard appears to be to print
+ // hex, space, then either space or '*' followed by file name
+ // where '*' is used for binary files
+ // shasum(1) has a -b option which generates " *" separator
+ // we don't distinguish binary files at present
+ System.out.println(prefix + Hex.encodeHexString(digest) + (fileName !=
null ? " " + fileName : ""));
+ }
+
+ private void run() throws IOException {
+ if (algorithm.equalsIgnoreCase("ALL") || algorithm.equals("*")) {
+ run(MessageDigestAlgorithms.values());
+ return;
+ }
+ final MessageDigest messageDigest = DigestUtils.getDigest(algorithm,
null);
+ if (messageDigest != null) {
+ run("", messageDigest);
+ } else {
+ run("", DigestUtils.getDigest(algorithm.toUpperCase(Locale.ROOT)));
+ }
+ }
+
+ private void run(final String[] digestAlgorithms) throws IOException {
+ for (final String messageDigestAlgorithm : digestAlgorithms) {
+ if (DigestUtils.isAvailable(messageDigestAlgorithm)) {
+ run(messageDigestAlgorithm + " ", messageDigestAlgorithm);
+ }
+ }
+ }
+
+ private void run(final String prefix, final MessageDigest messageDigest)
throws IOException {
+ if (inputs == null) {
+ println(prefix, DigestUtils.digest(messageDigest, System.in));
+ return;
+ }
+ for(final String source : inputs) {
+ final File file = new File(source);
+ if (file.isFile()) {
+ println(prefix, DigestUtils.digest(messageDigest, file),
source);
+ } else if (file.isDirectory()) {
+ final File[] listFiles = file.listFiles();
+ if (listFiles != null) {
+ run(prefix, messageDigest, listFiles);
+ }
+ } else {
+ // use the default charset for the command-line parameter
+ final byte[] bytes = source.getBytes(Charset.defaultCharset());
+ println(prefix, DigestUtils.digest(messageDigest, bytes));
+ }
+ }
+ }
+
+ private void run(final String prefix, final MessageDigest messageDigest,
final File[] files) throws IOException {
+ for (final File file : files) {
+ if (file.isFile()) {
+ println(prefix, DigestUtils.digest(messageDigest, file),
file.getName());
+ }
+ }
+ }
+
+ private void run(final String prefix, final String messageDigestAlgorithm)
throws IOException {
+ run(prefix, DigestUtils.getDigest(messageDigestAlgorithm));
+ }
+
+ @Override
+ public String toString() {
+ return String.format("%s %s", super.toString(), Arrays.toString(args));
+ }
+}
diff --git
a/src/main/java/org/apache/commons/codec/language/DaitchMokotoffSoundex.java
b/src/main/java/org/apache/commons/codec/language/DaitchMokotoffSoundex.java
index d35297d..dacb87c 100644
--- a/src/main/java/org/apache/commons/codec/language/DaitchMokotoffSoundex.java
+++ b/src/main/java/org/apache/commons/codec/language/DaitchMokotoffSoundex.java
@@ -1,552 +1,552 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.commons.codec.language;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.HashMap;
-import java.util.LinkedHashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Scanner;
-import java.util.Set;
-
-import org.apache.commons.codec.CharEncoding;
-import org.apache.commons.codec.EncoderException;
-import org.apache.commons.codec.Resources;
-import org.apache.commons.codec.StringEncoder;
-
-/**
- * Encodes a string into a Daitch-Mokotoff Soundex value.
- * <p>
- * The Daitch-Mokotoff Soundex algorithm is a refinement of the Russel and
American Soundex algorithms, yielding greater
- * accuracy in matching especially Slavish and Yiddish surnames with similar
pronunciation but differences in spelling.
- * </p>
- * <p>
- * The main differences compared to the other soundex variants are:
- * </p>
- * <ul>
- * <li>coded names are 6 digits long
- * <li>the initial character of the name is coded
- * <li>rules to encoded multi-character n-grams
- * <li>multiple possible encodings for the same name (branching)
- * </ul>
- * <p>
- * This implementation supports branching, depending on the used method:
- * <ul>
- * <li>{@link #encode(String)} - branching disabled, only the first code will
be returned
- * <li>{@link #soundex(String)} - branching enabled, all codes will be
returned, separated by '|'
- * </ul>
- * <p>
- * Note: this implementation has additional branching rules compared to the
original description of the algorithm. The
- * rules can be customized by overriding the default rules contained in the
resource file
- * {@code org/apache/commons/codec/language/dmrules.txt}.
- * </p>
- * <p>
- * This class is thread-safe.
- * </p>
- *
- * @see Soundex
- * @see <a
href="http://en.wikipedia.org/wiki/Daitch%E2%80%93Mokotoff_Soundex"> Wikipedia
- Daitch-Mokotoff Soundex</a>
- * @see <a href="http://www.avotaynu.com/soundex.htm">Avotaynu - Soundexing
and Genealogy</a>
- *
- * @since 1.10
- */
-public class DaitchMokotoffSoundex implements StringEncoder {
-
- /**
- * Inner class representing a branch during DM soundex encoding.
- */
- private static final class Branch {
- private final StringBuilder builder;
- private String cachedString;
- private String lastReplacement;
-
- private Branch() {
- builder = new StringBuilder();
- lastReplacement = null;
- cachedString = null;
- }
-
- /**
- * Creates a new branch, identical to this branch.
- *
- * @return a new, identical branch
- */
- public Branch createBranch() {
- final Branch branch = new Branch();
- branch.builder.append(toString());
- branch.lastReplacement = this.lastReplacement;
- return branch;
- }
-
- @Override
- public boolean equals(final Object other) {
- if (this == other) {
- return true;
- }
- if (!(other instanceof Branch)) {
- return false;
- }
-
- return toString().equals(((Branch) other).toString());
- }
-
- /**
- * Finish this branch by appending '0's until the maximum code length
has been reached.
- */
- public void finish() {
- while (builder.length() < MAX_LENGTH) {
- builder.append('0');
- cachedString = null;
- }
- }
-
- @Override
- public int hashCode() {
- return toString().hashCode();
- }
-
- /**
- * Process the next replacement to be added to this branch.
- *
- * @param replacement
- * the next replacement to append
- * @param forceAppend
- * indicates if the default processing shall be overridden
- */
- public void processNextReplacement(final String replacement, final
boolean forceAppend) {
- final boolean append = lastReplacement == null ||
!lastReplacement.endsWith(replacement) || forceAppend;
-
- if (append && builder.length() < MAX_LENGTH) {
- builder.append(replacement);
- // remove all characters after the maximum length
- if (builder.length() > MAX_LENGTH) {
- builder.delete(MAX_LENGTH, builder.length());
- }
- cachedString = null;
- }
-
- lastReplacement = replacement;
- }
-
- @Override
- public String toString() {
- if (cachedString == null) {
- cachedString = builder.toString();
- }
- return cachedString;
- }
- }
-
- /**
- * Inner class for storing rules.
- */
- private static final class Rule {
- private final String pattern;
- private final String[] replacementAtStart;
- private final String[] replacementBeforeVowel;
- private final String[] replacementDefault;
-
- protected Rule(final String pattern, final String replacementAtStart,
final String replacementBeforeVowel,
- final String replacementDefault) {
- this.pattern = pattern;
- this.replacementAtStart = replacementAtStart.split("\\|");
- this.replacementBeforeVowel = replacementBeforeVowel.split("\\|");
- this.replacementDefault = replacementDefault.split("\\|");
- }
-
- public int getPatternLength() {
- return pattern.length();
- }
-
- public String[] getReplacements(final String context, final boolean
atStart) {
- if (atStart) {
- return replacementAtStart;
- }
-
- final int nextIndex = getPatternLength();
- final boolean nextCharIsVowel = nextIndex < context.length() ?
isVowel(context.charAt(nextIndex)) : false;
- if (nextCharIsVowel) {
- return replacementBeforeVowel;
- }
-
- return replacementDefault;
- }
-
- private boolean isVowel(final char ch) {
- return ch == 'a' || ch == 'e' || ch == 'i' || ch == 'o' || ch ==
'u';
- }
-
- public boolean matches(final String context) {
- return context.startsWith(pattern);
- }
-
- @Override
- public String toString() {
- return String.format("%s=(%s,%s,%s)", pattern,
Arrays.asList(replacementAtStart),
- Arrays.asList(replacementBeforeVowel),
Arrays.asList(replacementDefault));
- }
- }
-
- private static final String COMMENT = "//";
- private static final String DOUBLE_QUOTE = "\"";
-
- private static final String MULTILINE_COMMENT_END = "*/";
-
- private static final String MULTILINE_COMMENT_START = "/*";
-
- /** The resource file containing the replacement and folding rules */
- private static final String RESOURCE_FILE =
"org/apache/commons/codec/language/dmrules.txt";
-
- /** The code length of a DM soundex value. */
- private static final int MAX_LENGTH = 6;
-
- /** Transformation rules indexed by the first character of their pattern.
*/
- private static final Map<Character, List<Rule>> RULES = new HashMap<>();
-
- /** Folding rules. */
- private static final Map<Character, Character> FOLDINGS = new HashMap<>();
-
- static {
- try (final Scanner scanner = new
Scanner(Resources.getInputStream(RESOURCE_FILE), CharEncoding.UTF_8)) {
- parseRules(scanner, RESOURCE_FILE, RULES, FOLDINGS);
- }
-
- // sort RULES by pattern length in descending order
- for (final Map.Entry<Character, List<Rule>> rule : RULES.entrySet()) {
- final List<Rule> ruleList = rule.getValue();
- Collections.sort(ruleList, new Comparator<Rule>() {
- @Override
- public int compare(final Rule rule1, final Rule rule2) {
- return rule2.getPatternLength() - rule1.getPatternLength();
- }
- });
- }
- }
-
- private static void parseRules(final Scanner scanner, final String
location,
- final Map<Character, List<Rule>> ruleMapping, final Map<Character,
Character> asciiFoldings) {
- int currentLine = 0;
- boolean inMultilineComment = false;
-
- while (scanner.hasNextLine()) {
- currentLine++;
- final String rawLine = scanner.nextLine();
- String line = rawLine;
-
- if (inMultilineComment) {
- if (line.endsWith(MULTILINE_COMMENT_END)) {
- inMultilineComment = false;
- }
- continue;
- }
-
- if (line.startsWith(MULTILINE_COMMENT_START)) {
- inMultilineComment = true;
- } else {
- // discard comments
- final int cmtI = line.indexOf(COMMENT);
- if (cmtI >= 0) {
- line = line.substring(0, cmtI);
- }
-
- // trim leading-trailing whitespace
- line = line.trim();
-
- if (line.length() == 0) {
- continue; // empty lines can be safely skipped
- }
-
- if (line.contains("=")) {
- // folding
- final String[] parts = line.split("=");
- if (parts.length != 2) {
- throw new IllegalArgumentException("Malformed folding
statement split into " + parts.length +
- " parts: " + rawLine + " in " + location);
- }
- final String leftCharacter = parts[0];
- final String rightCharacter = parts[1];
-
- if (leftCharacter.length() != 1 || rightCharacter.length()
!= 1) {
- throw new IllegalArgumentException("Malformed folding
statement - " +
- "patterns are not single characters: " +
rawLine + " in " + location);
- }
-
- asciiFoldings.put(leftCharacter.charAt(0),
rightCharacter.charAt(0));
- } else {
- // rule
- final String[] parts = line.split("\\s+");
- if (parts.length != 4) {
- throw new IllegalArgumentException("Malformed rule
statement split into " + parts.length +
- " parts: " + rawLine + " in " + location);
- }
- try {
- final String pattern = stripQuotes(parts[0]);
- final String replacement1 = stripQuotes(parts[1]);
- final String replacement2 = stripQuotes(parts[2]);
- final String replacement3 = stripQuotes(parts[3]);
-
- final Rule r = new Rule(pattern, replacement1,
replacement2, replacement3);
- final char patternKey = r.pattern.charAt(0);
- List<Rule> rules = ruleMapping.get(patternKey);
- if (rules == null) {
- rules = new ArrayList<>();
- ruleMapping.put(patternKey, rules);
- }
- rules.add(r);
- } catch (final IllegalArgumentException e) {
- throw new IllegalStateException(
- "Problem parsing line '" + currentLine + "' in
" + location, e);
- }
- }
- }
- }
- }
-
- private static String stripQuotes(String str) {
- if (str.startsWith(DOUBLE_QUOTE)) {
- str = str.substring(1);
- }
-
- if (str.endsWith(DOUBLE_QUOTE)) {
- str = str.substring(0, str.length() - 1);
- }
-
- return str;
- }
-
- /** Whether to use ASCII folding prior to encoding. */
- private final boolean folding;
-
- /**
- * Creates a new instance with ASCII-folding enabled.
- */
- public DaitchMokotoffSoundex() {
- this(true);
- }
-
- /**
- * Creates a new instance.
- * <p>
- * With ASCII-folding enabled, certain accented characters will be
transformed to equivalent ASCII characters, e.g.
- * รจ -> e.
- * </p>
- *
- * @param folding
- * if ASCII-folding shall be performed before encoding
- */
- public DaitchMokotoffSoundex(final boolean folding) {
- this.folding = folding;
- }
-
- /**
- * Performs a cleanup of the input string before the actual soundex
transformation.
- * <p>
- * Removes all whitespace characters and performs ASCII folding if enabled.
- * </p>
- *
- * @param input
- * the input string to cleanup
- * @return a cleaned up string
- */
- private String cleanup(final String input) {
- final StringBuilder sb = new StringBuilder();
- for (char ch : input.toCharArray()) {
- if (Character.isWhitespace(ch)) {
- continue;
- }
-
- ch = Character.toLowerCase(ch);
- if (folding && FOLDINGS.containsKey(ch)) {
- ch = FOLDINGS.get(ch);
- }
- sb.append(ch);
- }
- return sb.toString();
- }
-
- /**
- * Encodes an Object using the Daitch-Mokotoff soundex algorithm without
branching.
- * <p>
- * This method is provided in order to satisfy the requirements of the
Encoder interface, and will throw an
- * EncoderException if the supplied object is not of type java.lang.String.
- * </p>
- *
- * @see #soundex(String)
- *
- * @param obj
- * Object to encode
- * @return An object (of type java.lang.String) containing the DM soundex
code, which corresponds to the String
- * supplied.
- * @throws EncoderException
- * if the parameter supplied is not of type java.lang.String
- * @throws IllegalArgumentException
- * if a character is not mapped
- */
- @Override
- public Object encode(final Object obj) throws EncoderException {
- if (!(obj instanceof String)) {
- throw new EncoderException(
- "Parameter supplied to DaitchMokotoffSoundex encode is not
of type java.lang.String");
- }
- return encode((String) obj);
- }
-
- /**
- * Encodes a String using the Daitch-Mokotoff soundex algorithm without
branching.
- *
- * @see #soundex(String)
- *
- * @param source
- * A String object to encode
- * @return A DM Soundex code corresponding to the String supplied
- * @throws IllegalArgumentException
- * if a character is not mapped
- */
- @Override
- public String encode(final String source) {
- if (source == null) {
- return null;
- }
- return soundex(source, false)[0];
- }
-
- /**
- * Encodes a String using the Daitch-Mokotoff soundex algorithm with
branching.
- * <p>
- * In case a string is encoded into multiple codes (see branching rules),
the result will contain all codes,
- * separated by '|'.
- * </p>
- * <p>
- * Example: the name "AUERBACH" is encoded as both
- * </p>
- * <ul>
- * <li>097400</li>
- * <li>097500</li>
- * </ul>
- * <p>
- * Thus the result will be "097400|097500".
- * </p>
- *
- * @param source
- * A String object to encode
- * @return A string containing a set of DM Soundex codes corresponding to
the String supplied
- * @throws IllegalArgumentException
- * if a character is not mapped
- */
- public String soundex(final String source) {
- final String[] branches = soundex(source, true);
- final StringBuilder sb = new StringBuilder();
- int index = 0;
- for (final String branch : branches) {
- sb.append(branch);
- if (++index < branches.length) {
- sb.append('|');
- }
- }
- return sb.toString();
- }
-
- /**
- * Perform the actual DM Soundex algorithm on the input string.
- *
- * @param source
- * A String object to encode
- * @param branching
- * If branching shall be performed
- * @return A string array containing all DM Soundex codes corresponding to
the String supplied depending on the
- * selected branching mode
- */
- private String[] soundex(final String source, final boolean branching) {
- if (source == null) {
- return null;
- }
-
- final String input = cleanup(source);
-
- final Set<Branch> currentBranches = new LinkedHashSet<>();
- currentBranches.add(new Branch());
-
- char lastChar = '\0';
- for (int index = 0; index < input.length(); index++) {
- final char ch = input.charAt(index);
-
- // ignore whitespace inside a name
- if (Character.isWhitespace(ch)) {
- continue;
- }
-
- final String inputContext = input.substring(index);
- final List<Rule> rules = RULES.get(ch);
- if (rules == null) {
- continue;
- }
-
- // use an EMPTY_LIST to avoid false positive warnings wrt
potential null pointer access
- final List<Branch> nextBranches = branching ? new ArrayList<>() :
Collections.<Branch>emptyList();
-
- for (final Rule rule : rules) {
- if (rule.matches(inputContext)) {
- if (branching) {
- nextBranches.clear();
- }
- final String[] replacements =
rule.getReplacements(inputContext, lastChar == '\0');
- final boolean branchingRequired = replacements.length > 1
&& branching;
-
- for (final Branch branch : currentBranches) {
- for (final String nextReplacement : replacements) {
- // if we have multiple replacements, always create
a new branch
- final Branch nextBranch = branchingRequired ?
branch.createBranch() : branch;
-
- // special rule: occurrences of mn or nm are
treated differently
- final boolean force = (lastChar == 'm' && ch ==
'n') || (lastChar == 'n' && ch == 'm');
-
- nextBranch.processNextReplacement(nextReplacement,
force);
-
- if (branching) {
- nextBranches.add(nextBranch);
- } else {
- break;
- }
- }
- }
-
- if (branching) {
- currentBranches.clear();
- currentBranches.addAll(nextBranches);
- }
- index += rule.getPatternLength() - 1;
- break;
- }
- }
-
- lastChar = ch;
- }
-
- final String[] result = new String[currentBranches.size()];
- int index = 0;
- for (final Branch branch : currentBranches) {
- branch.finish();
- result[index++] = branch.toString();
- }
-
- return result;
- }
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.codec.language;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Scanner;
+import java.util.Set;
+
+import org.apache.commons.codec.CharEncoding;
+import org.apache.commons.codec.EncoderException;
+import org.apache.commons.codec.Resources;
+import org.apache.commons.codec.StringEncoder;
+
+/**
+ * Encodes a string into a Daitch-Mokotoff Soundex value.
+ * <p>
+ * The Daitch-Mokotoff Soundex algorithm is a refinement of the Russel and
American Soundex algorithms, yielding greater
+ * accuracy in matching especially Slavish and Yiddish surnames with similar
pronunciation but differences in spelling.
+ * </p>
+ * <p>
+ * The main differences compared to the other soundex variants are:
+ * </p>
+ * <ul>
+ * <li>coded names are 6 digits long
+ * <li>the initial character of the name is coded
+ * <li>rules to encoded multi-character n-grams
+ * <li>multiple possible encodings for the same name (branching)
+ * </ul>
+ * <p>
+ * This implementation supports branching, depending on the used method:
+ * <ul>
+ * <li>{@link #encode(String)} - branching disabled, only the first code will
be returned
+ * <li>{@link #soundex(String)} - branching enabled, all codes will be
returned, separated by '|'
+ * </ul>
+ * <p>
+ * Note: this implementation has additional branching rules compared to the
original description of the algorithm. The
+ * rules can be customized by overriding the default rules contained in the
resource file
+ * {@code org/apache/commons/codec/language/dmrules.txt}.
+ * </p>
+ * <p>
+ * This class is thread-safe.
+ * </p>
+ *
+ * @see Soundex
+ * @see <a
href="http://en.wikipedia.org/wiki/Daitch%E2%80%93Mokotoff_Soundex"> Wikipedia
- Daitch-Mokotoff Soundex</a>
+ * @see <a href="http://www.avotaynu.com/soundex.htm">Avotaynu - Soundexing
and Genealogy</a>
+ *
+ * @since 1.10
+ */
+public class DaitchMokotoffSoundex implements StringEncoder {
+
+ /**
+ * Inner class representing a branch during DM soundex encoding.
+ */
+ private static final class Branch {
+ private final StringBuilder builder;
+ private String cachedString;
+ private String lastReplacement;
+
+ private Branch() {
+ builder = new StringBuilder();
+ lastReplacement = null;
+ cachedString = null;
+ }
+
+ /**
+ * Creates a new branch, identical to this branch.
+ *
+ * @return a new, identical branch
+ */
+ public Branch createBranch() {
+ final Branch branch = new Branch();
+ branch.builder.append(toString());
+ branch.lastReplacement = this.lastReplacement;
+ return branch;
+ }
+
+ @Override
+ public boolean equals(final Object other) {
+ if (this == other) {
+ return true;
+ }
+ if (!(other instanceof Branch)) {
+ return false;
+ }
+
+ return toString().equals(((Branch) other).toString());
+ }
+
+ /**
+ * Finish this branch by appending '0's until the maximum code length
has been reached.
+ */
+ public void finish() {
+ while (builder.length() < MAX_LENGTH) {
+ builder.append('0');
+ cachedString = null;
+ }
+ }
+
+ @Override
+ public int hashCode() {
+ return toString().hashCode();
+ }
+
+ /**
+ * Process the next replacement to be added to this branch.
+ *
+ * @param replacement
+ * the next replacement to append
+ * @param forceAppend
+ * indicates if the default processing shall be overridden
+ */
+ public void processNextReplacement(final String replacement, final
boolean forceAppend) {
+ final boolean append = lastReplacement == null ||
!lastReplacement.endsWith(replacement) || forceAppend;
+
+ if (append && builder.length() < MAX_LENGTH) {
+ builder.append(replacement);
+ // remove all characters after the maximum length
+ if (builder.length() > MAX_LENGTH) {
+ builder.delete(MAX_LENGTH, builder.length());
+ }
+ cachedString = null;
+ }
+
+ lastReplacement = replacement;
+ }
+
+ @Override
+ public String toString() {
+ if (cachedString == null) {
+ cachedString = builder.toString();
+ }
+ return cachedString;
+ }
+ }
+
+ /**
+ * Inner class for storing rules.
+ */
+ private static final class Rule {
+ private final String pattern;
+ private final String[] replacementAtStart;
+ private final String[] replacementBeforeVowel;
+ private final String[] replacementDefault;
+
+ protected Rule(final String pattern, final String replacementAtStart,
final String replacementBeforeVowel,
+ final String replacementDefault) {
+ this.pattern = pattern;
+ this.replacementAtStart = replacementAtStart.split("\\|");
+ this.replacementBeforeVowel = replacementBeforeVowel.split("\\|");
+ this.replacementDefault = replacementDefault.split("\\|");
+ }
+
+ public int getPatternLength() {
+ return pattern.length();
+ }
+
+ public String[] getReplacements(final String context, final boolean
atStart) {
+ if (atStart) {
+ return replacementAtStart;
+ }
+
+ final int nextIndex = getPatternLength();
+ final boolean nextCharIsVowel = nextIndex < context.length() ?
isVowel(context.charAt(nextIndex)) : false;
+ if (nextCharIsVowel) {
+ return replacementBeforeVowel;
+ }
+
+ return replacementDefault;
+ }
+
+ private boolean isVowel(final char ch) {
+ return ch == 'a' || ch == 'e' || ch == 'i' || ch == 'o' || ch ==
'u';
+ }
+
+ public boolean matches(final String context) {
+ return context.startsWith(pattern);
+ }
+
+ @Override
+ public String toString() {
+ return String.format("%s=(%s,%s,%s)", pattern,
Arrays.asList(replacementAtStart),
+ Arrays.asList(replacementBeforeVowel),
Arrays.asList(replacementDefault));
+ }
+ }
+
+ private static final String COMMENT = "//";
+ private static final String DOUBLE_QUOTE = "\"";
+
+ private static final String MULTILINE_COMMENT_END = "*/";
+
+ private static final String MULTILINE_COMMENT_START = "/*";
+
+ /** The resource file containing the replacement and folding rules */
+ private static final String RESOURCE_FILE =
"org/apache/commons/codec/language/dmrules.txt";
+
+ /** The code length of a DM soundex value. */
+ private static final int MAX_LENGTH = 6;
+
+ /** Transformation rules indexed by the first character of their pattern.
*/
+ private static final Map<Character, List<Rule>> RULES = new HashMap<>();
+
+ /** Folding rules. */
+ private static final Map<Character, Character> FOLDINGS = new HashMap<>();
+
+ static {
+ try (final Scanner scanner = new
Scanner(Resources.getInputStream(RESOURCE_FILE), CharEncoding.UTF_8)) {
+ parseRules(scanner, RESOURCE_FILE, RULES, FOLDINGS);
+ }
+
+ // sort RULES by pattern length in descending order
+ for (final Map.Entry<Character, List<Rule>> rule : RULES.entrySet()) {
+ final List<Rule> ruleList = rule.getValue();
+ Collections.sort(ruleList, new Comparator<Rule>() {
+ @Override
+ public int compare(final Rule rule1, final Rule rule2) {
+ return rule2.getPatternLength() - rule1.getPatternLength();
+ }
+ });
+ }
+ }
+
+ private static void parseRules(final Scanner scanner, final String
location,
+ final Map<Character, List<Rule>> ruleMapping, final Map<Character,
Character> asciiFoldings) {
+ int currentLine = 0;
+ boolean inMultilineComment = false;
+
+ while (scanner.hasNextLine()) {
+ currentLine++;
+ final String rawLine = scanner.nextLine();
+ String line = rawLine;
+
+ if (inMultilineComment) {
+ if (line.endsWith(MULTILINE_COMMENT_END)) {
+ inMultilineComment = false;
+ }
+ continue;
+ }
+
+ if (line.startsWith(MULTILINE_COMMENT_START)) {
+ inMultilineComment = true;
+ } else {
+ // discard comments
+ final int cmtI = line.indexOf(COMMENT);
+ if (cmtI >= 0) {
+ line = line.substring(0, cmtI);
+ }
+
+ // trim leading-trailing whitespace
+ line = line.trim();
+
+ if (line.length() == 0) {
+ continue; // empty lines can be safely skipped
+ }
+
+ if (line.contains("=")) {
+ // folding
+ final String[] parts = line.split("=");
+ if (parts.length != 2) {
+ throw new IllegalArgumentException("Malformed folding
statement split into " + parts.length +
+ " parts: " + rawLine + " in " + location);
+ }
+ final String leftCharacter = parts[0];
+ final String rightCharacter = parts[1];
+
+ if (leftCharacter.length() != 1 || rightCharacter.length()
!= 1) {
+ throw new IllegalArgumentException("Malformed folding
statement - " +
+ "patterns are not single characters: " +
rawLine + " in " + location);
+ }
+
+ asciiFoldings.put(leftCharacter.charAt(0),
rightCharacter.charAt(0));
+ } else {
+ // rule
+ final String[] parts = line.split("\\s+");
+ if (parts.length != 4) {
+ throw new IllegalArgumentException("Malformed rule
statement split into " + parts.length +
+ " parts: " + rawLine + " in " + location);
+ }
+ try {
+ final String pattern = stripQuotes(parts[0]);
+ final String replacement1 = stripQuotes(parts[1]);
+ final String replacement2 = stripQuotes(parts[2]);
+ final String replacement3 = stripQuotes(parts[3]);
+
+ final Rule r = new Rule(pattern, replacement1,
replacement2, replacement3);
+ final char patternKey = r.pattern.charAt(0);
+ List<Rule> rules = ruleMapping.get(patternKey);
+ if (rules == null) {
+ rules = new ArrayList<>();
+ ruleMapping.put(patternKey, rules);
+ }
+ rules.add(r);
+ } catch (final IllegalArgumentException e) {
+ throw new IllegalStateException(
+ "Problem parsing line '" + currentLine + "' in
" + location, e);
+ }
+ }
+ }
+ }
+ }
+
+ private static String stripQuotes(String str) {
+ if (str.startsWith(DOUBLE_QUOTE)) {
+ str = str.substring(1);
+ }
+
+ if (str.endsWith(DOUBLE_QUOTE)) {
+ str = str.substring(0, str.length() - 1);
+ }
+
+ return str;
+ }
+
+ /** Whether to use ASCII folding prior to encoding. */
+ private final boolean folding;
+
+ /**
+ * Creates a new instance with ASCII-folding enabled.
+ */
+ public DaitchMokotoffSoundex() {
+ this(true);
+ }
+
+ /**
+ * Creates a new instance.
+ * <p>
+ * With ASCII-folding enabled, certain accented characters will be
transformed to equivalent ASCII characters, e.g.
+ * รจ -> e.
+ * </p>
+ *
+ * @param folding
+ * if ASCII-folding shall be performed before encoding
+ */
+ public DaitchMokotoffSoundex(final boolean folding) {
+ this.folding = folding;
+ }
+
+ /**
+ * Performs a cleanup of the input string before the actual soundex
transformation.
+ * <p>
+ * Removes all whitespace characters and performs ASCII folding if enabled.
+ * </p>
+ *
+ * @param input
+ * the input string to cleanup
+ * @return a cleaned up string
+ */
+ private String cleanup(final String input) {
+ final StringBuilder sb = new StringBuilder();
+ for (char ch : input.toCharArray()) {
+ if (Character.isWhitespace(ch)) {
+ continue;
+ }
+
+ ch = Character.toLowerCase(ch);
+ if (folding && FOLDINGS.containsKey(ch)) {
+ ch = FOLDINGS.get(ch);
+ }
+ sb.append(ch);
+ }
+ return sb.toString();
+ }
+
+ /**
+ * Encodes an Object using the Daitch-Mokotoff soundex algorithm without
branching.
+ * <p>
+ * This method is provided in order to satisfy the requirements of the
Encoder interface, and will throw an
+ * EncoderException if the supplied object is not of type java.lang.String.
+ * </p>
+ *
+ * @see #soundex(String)
+ *
+ * @param obj
+ * Object to encode
+ * @return An object (of type java.lang.String) containing the DM soundex
code, which corresponds to the String
+ * supplied.
+ * @throws EncoderException
+ * if the parameter supplied is not of type java.lang.String
+ * @throws IllegalArgumentException
+ * if a character is not mapped
+ */
+ @Override
+ public Object encode(final Object obj) throws EncoderException {
+ if (!(obj instanceof String)) {
+ throw new EncoderException(
+ "Parameter supplied to DaitchMokotoffSoundex encode is not
of type java.lang.String");
+ }
+ return encode((String) obj);
+ }
+
+ /**
+ * Encodes a String using the Daitch-Mokotoff soundex algorithm without
branching.
+ *
+ * @see #soundex(String)
+ *
+ * @param source
+ * A String object to encode
+ * @return A DM Soundex code corresponding to the String supplied
+ * @throws IllegalArgumentException
+ * if a character is not mapped
+ */
+ @Override
+ public String encode(final String source) {
+ if (source == null) {
+ return null;
+ }
+ return soundex(source, false)[0];
+ }
+
+ /**
+ * Encodes a String using the Daitch-Mokotoff soundex algorithm with
branching.
+ * <p>
+ * In case a string is encoded into multiple codes (see branching rules),
the result will contain all codes,
+ * separated by '|'.
+ * </p>
+ * <p>
+ * Example: the name "AUERBACH" is encoded as both
+ * </p>
+ * <ul>
+ * <li>097400</li>
+ * <li>097500</li>
+ * </ul>
+ * <p>
+ * Thus the result will be "097400|097500".
+ * </p>
+ *
+ * @param source
+ * A String object to encode
+ * @return A string containing a set of DM Soundex codes corresponding to
the String supplied
+ * @throws IllegalArgumentException
+ * if a character is not mapped
+ */
+ public String soundex(final String source) {
+ final String[] branches = soundex(source, true);
+ final StringBuilder sb = new StringBuilder();
+ int index = 0;
+ for (final String branch : branches) {
+ sb.append(branch);
+ if (++index < branches.length) {
+ sb.append('|');
+ }
+ }
+ return sb.toString();
+ }
+
+ /**
+ * Perform the actual DM Soundex algorithm on the input string.
+ *
+ * @param source
+ * A String object to encode
+ * @param branching
+ * If branching shall be performed
+ * @return A string array containing all DM Soundex codes corresponding to
the String supplied depending on the
+ * selected branching mode
+ */
+ private String[] soundex(final String source, final boolean branching) {
+ if (source == null) {
+ return null;
+ }
+
+ final String input = cleanup(source);
+
+ final Set<Branch> currentBranches = new LinkedHashSet<>();
+ currentBranches.add(new Branch());
+
+ char lastChar = '\0';
+ for (int index = 0; index < input.length(); index++) {
+ final char ch = input.charAt(index);
+
+ // ignore whitespace inside a name
+ if (Character.isWhitespace(ch)) {
+ continue;
+ }
+
+ final String inputContext = input.substring(index);
+ final List<Rule> rules = RULES.get(ch);
+ if (rules == null) {
+ continue;
+ }
+
+ // use an EMPTY_LIST to avoid false positive warnings wrt
potential null pointer access
+ final List<Branch> nextBranches = branching ? new ArrayList<>() :
Collections.<Branch>emptyList();
+
+ for (final Rule rule : rules) {
+ if (rule.matches(inputContext)) {
+ if (branching) {
+ nextBranches.clear();
+ }
+ final String[] replacements =
rule.getReplacements(inputContext, lastChar == '\0');
+ final boolean branchingRequired = replacements.length > 1
&& branching;
+
+ for (final Branch branch : currentBranches) {
+ for (final String nextReplacement : replacements) {
+ // if we have multiple replacements, always create
a new branch
+ final Branch nextBranch = branchingRequired ?
branch.createBranch() : branch;
+
+ // special rule: occurrences of mn or nm are
treated differently
+ final boolean force = (lastChar == 'm' && ch ==
'n') || (lastChar == 'n' && ch == 'm');
+
+ nextBranch.processNextReplacement(nextReplacement,
force);
+
+ if (branching) {
+ nextBranches.add(nextBranch);
+ } else {
+ break;
+ }
+ }
+ }
+
+ if (branching) {
+ currentBranches.clear();
+ currentBranches.addAll(nextBranches);
+ }
+ index += rule.getPatternLength() - 1;
+ break;
+ }
+ }
+
+ lastChar = ch;
+ }
+
+ final String[] result = new String[currentBranches.size()];
+ int index = 0;
+ for (final Branch branch : currentBranches) {
+ branch.finish();
+ result[index++] = branch.toString();
+ }
+
+ return result;
+ }
+}
diff --git a/src/main/resources/org/apache/commons/codec/language/bm/lang.txt
b/src/main/resources/org/apache/commons/codec/language/bm/lang.txt
index b04c13b..ae6f28c 100644
--- a/src/main/resources/org/apache/commons/codec/language/bm/lang.txt
+++ b/src/main/resources/org/apache/commons/codec/language/bm/lang.txt
@@ -1,16 +1,16 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
diff --git
a/src/test/java/org/apache/commons/codec/digest/HmacAlgorithmsTest.java
b/src/test/java/org/apache/commons/codec/digest/HmacAlgorithmsTest.java
index 3fcfd57..58fe888 100644
--- a/src/test/java/org/apache/commons/codec/digest/HmacAlgorithmsTest.java
+++ b/src/test/java/org/apache/commons/codec/digest/HmacAlgorithmsTest.java
@@ -1,226 +1,226 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.commons.codec.digest;
-
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.security.NoSuchAlgorithmException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.List;
-
-import javax.crypto.Mac;
-
-import org.apache.commons.lang3.JavaVersion;
-import org.apache.commons.lang3.SystemUtils;
-import org.junit.After;
-import org.junit.Assert;
-import org.junit.Assume;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
-import org.junit.runners.Parameterized.Parameters;
-
-/**
- * Tests {@link HmacAlgorithms}.
- *
- * @since 1.11
- */
-@RunWith(Parameterized.class)
-public class HmacAlgorithmsTest {
-
- static final String STANDARD_KEY_STRING = "key";
-
- static final byte[] STANDARD_KEY_BYTES = STANDARD_KEY_STRING.getBytes();
-
- static final byte[] STANDARD_MD5_RESULT_BYTES = new byte[] { -128, 7, 7,
19, 70, 62, 119, 73, -71, 12, 45, -62, 73,
- 17, -30, 117 };
-
- static final String STANDARD_MD5_RESULT_STRING =
"80070713463e7749b90c2dc24911e275";
-
- static final String STANDARD_PHRASE_STRING = "The quick brown fox jumps
over the lazy dog";
-
- static final byte[] STANDARD_PHRASE_BYTES =
STANDARD_PHRASE_STRING.getBytes();
-
- static final byte[] STANDARD_SHA1_RESULT_BYTES = new byte[] { -34, 124,
-101, -123, -72, -73, -118, -90, -68, -118,
- 122, 54, -9, 10, -112, 112, 28, -99, -76, -39 };
-
- static final String STANDARD_SHA1_RESULT_STRING =
"de7c9b85b8b78aa6bc8a7a36f70a90701c9db4d9";
-
- static final byte[] STANDARD_SHA224_RESULT_BYTES = new byte[] { -120, -1,
-117, 84, 103, 93, 57, -72, -9, 35, 34,
- -26, 95, -7, 69, -59, 45, -106, 55, -103, -120, -83, -94, 86, 57,
116, 126, 105 };
-
- static final String STANDARD_SHA224_RESULT_STRING =
"88ff8b54675d39b8f72322e65ff945c52d96379988ada25639747e69";
-
- static final byte[] STANDARD_SHA256_RESULT_BYTES = new byte[] { -9, -68,
-125, -12, 48, 83, -124, 36, -79, 50, -104,
- -26, -86, 111, -79, 67, -17, 77, 89, -95, 73, 70, 23, 89, -105,
71, -99, -68, 45, 26, 60, -40 };
-
- static final String STANDARD_SHA256_RESULT_STRING =
"f7bc83f430538424b13298e6aa6fb143ef4d59a14946175997479dbc2d1a3cd8";
-
- static final byte[] STANDARD_SHA384_RESULT_BYTES = new byte[] { -41, -12,
114, 126, 44, 11, 57, -82, 15, 30, 64,
- -52, -106, -10, 2, 66, -43, -73, -128, 24, 65, -50, -90, -4, 89,
44, 93, 62, 26, -27, 7, 0, 88, 42, -106,
- -49, 53, -31, -27, 84, -103, 95, -28, -32, 51, -127, -62, 55 };
-
- static final String STANDARD_SHA384_RESULT_STRING =
"D7F4727E2C0B39AE0F1E40CC96F60242D5B7801841CEA6FC592C5D3E1AE50700582A96CF35E1E554995FE4E03381C237"
- .toLowerCase();
-
- static final byte[] STANDARD_SHA512_RESULT_BYTES = new byte[] { -76, 42,
-16, -112, 87, -70, -63, -30, -44, 23, 8,
- -28, -118, -112, 46, 9, -75, -1, 127, 18, -85, 66, -118, 79, -24,
102, 83, -57, 61, -46, 72, -5, -126, -7,
- 72, -91, 73, -9, -73, -111, -91, -76, 25, 21, -18, 77, 30, -61,
-109, 83, 87, -28, -30, 49, 114, 80, -48,
- 55, 42, -6, 46, -66, -21, 58 };
-
- static final String STANDARD_SHA512_RESULT_STRING =
"B42AF09057BAC1E2D41708E48A902E09B5FF7F12AB428A4FE86653C73DD248FB82F948A549F7B791A5B41915EE4D1EC3935357E4E2317250D0372AFA2EBEEB3A"
- .toLowerCase();
-
- private static final byte[] EMPTY_BYTE_ARRAY = new byte[] {};
-
- // TODO HMAC_SHA_224
- @Parameters(name = "{0}")
- public static Collection<Object[]> data() {
- List<Object[]> list = Arrays.asList(
- // @formatter:off
- new Object[][] { { HmacAlgorithms.HMAC_MD5,
STANDARD_MD5_RESULT_BYTES, STANDARD_MD5_RESULT_STRING },
- { HmacAlgorithms.HMAC_SHA_1,
STANDARD_SHA1_RESULT_BYTES, STANDARD_SHA1_RESULT_STRING },
- { HmacAlgorithms.HMAC_SHA_256,
STANDARD_SHA256_RESULT_BYTES, STANDARD_SHA256_RESULT_STRING },
- { HmacAlgorithms.HMAC_SHA_384,
STANDARD_SHA384_RESULT_BYTES, STANDARD_SHA384_RESULT_STRING },
- { HmacAlgorithms.HMAC_SHA_512,
STANDARD_SHA512_RESULT_BYTES, STANDARD_SHA512_RESULT_STRING } });
- // @formatter:on
- if (SystemUtils.isJavaVersionAtLeast(JavaVersion.JAVA_1_8)) {
- list = new ArrayList<>(list);
- list.add(new Object[] {HmacAlgorithms.HMAC_SHA_224,
STANDARD_SHA224_RESULT_BYTES, STANDARD_SHA224_RESULT_STRING});
- }
- return list;
- }
-
- private DigestUtilsTest digestUtilsTest;
-
- private final HmacAlgorithms hmacAlgorithm;
-
- private final byte[] standardResultBytes;
- private final String standardResultString;
-
- public HmacAlgorithmsTest(final HmacAlgorithms hmacAlgorithm, final byte[]
standardResultBytes, final String standardResultString) {
- Assume.assumeTrue(HmacUtils.isAvailable(hmacAlgorithm));
- this.hmacAlgorithm = hmacAlgorithm;
- this.standardResultBytes = standardResultBytes;
- this.standardResultString = standardResultString;
- }
-
- @Before
- public void setUp() throws Exception {
- digestUtilsTest = new DigestUtilsTest();
- digestUtilsTest.setUp();
- }
-
- @After
- public void tearDown() throws Exception {
- digestUtilsTest.tearDown();
- digestUtilsTest = null;
- }
-
- @Test
- public void testAlgorithm() throws NoSuchAlgorithmException {
- final String algorithm = hmacAlgorithm.getName();
- Assert.assertNotNull(algorithm);
- Assert.assertFalse(algorithm.isEmpty());
- Assume.assumeTrue(HmacUtils.isAvailable(hmacAlgorithm));
- Mac.getInstance(algorithm);
- }
-
- @Test(expected = IllegalArgumentException.class)
- public void testGetHmacEmptyKey() {
- HmacUtils.getInitializedMac(hmacAlgorithm, EMPTY_BYTE_ARRAY);
- }
-
- @Test(expected = IllegalArgumentException.class)
- public void testGetHmacNullKey() {
- HmacUtils.getInitializedMac(hmacAlgorithm, null);
- }
-
- @Test(expected = IllegalArgumentException.class)
- public void testHmacFailByteArray() {
- new HmacUtils(hmacAlgorithm, (byte[])
null).hmac(STANDARD_PHRASE_BYTES);
- }
-
- @Test(expected = IllegalArgumentException.class)
- public void testHmacFailInputStream() throws IOException {
- new HmacUtils(hmacAlgorithm, (byte[]) null).hmac(new
ByteArrayInputStream(STANDARD_PHRASE_BYTES));
- }
-
- @Test(expected = IllegalArgumentException.class)
- public void testHmacFailString() {
- new HmacUtils(hmacAlgorithm, (String)
null).hmac(STANDARD_PHRASE_STRING);
- }
-
- @Test(expected = IllegalArgumentException.class)
- public void testHmacHexFailByteArray() {
- new HmacUtils(hmacAlgorithm, (byte[])
null).hmac(STANDARD_PHRASE_BYTES);
- }
-
- @Test(expected = IllegalArgumentException.class)
- public void testHmacHexFailInputStream() throws IOException {
- new HmacUtils(hmacAlgorithm, (byte[]) null).hmac(new
ByteArrayInputStream(STANDARD_PHRASE_BYTES));
- }
-
- @Test(expected = IllegalArgumentException.class)
- public void testHmacHexFailString() {
- new HmacUtils(hmacAlgorithm, (String)
null).hmac(STANDARD_PHRASE_STRING);
- }
-
- @Test
- public void testInitializedMac() {
- final Mac mac = HmacUtils.getInitializedMac(hmacAlgorithm,
STANDARD_KEY_BYTES);
- final Mac mac2 = HmacUtils.getInitializedMac(hmacAlgorithm.getName(),
STANDARD_KEY_BYTES);
- Assert.assertArrayEquals(standardResultBytes,
HmacUtils.updateHmac(mac, STANDARD_PHRASE_STRING).doFinal());
- Assert.assertArrayEquals(standardResultBytes,
HmacUtils.updateHmac(mac2, STANDARD_PHRASE_STRING).doFinal());
- }
-
- @Test
- public void testMacByteArary() {
- Assert.assertArrayEquals(standardResultBytes, new
HmacUtils(hmacAlgorithm, STANDARD_KEY_BYTES).hmac(STANDARD_PHRASE_BYTES));
- }
-
- @Test
- public void testMacHexByteArray() {
- Assert.assertEquals(standardResultString, new HmacUtils(hmacAlgorithm,
STANDARD_KEY_BYTES).hmacHex(STANDARD_PHRASE_BYTES));
- }
-
- @Test
- public void testMacHexInputStream() throws IOException {
- Assert.assertEquals(standardResultString,
- new HmacUtils(hmacAlgorithm, STANDARD_KEY_BYTES).hmacHex(new
ByteArrayInputStream(STANDARD_PHRASE_BYTES)));
- }
-
- @Test
- public void testMacHexString() {
- Assert.assertEquals(standardResultString, new HmacUtils(hmacAlgorithm,
STANDARD_KEY_BYTES).hmacHex(STANDARD_PHRASE_STRING));
- }
-
- @Test
- public void testMacInputStream() throws IOException {
- Assert.assertArrayEquals(standardResultBytes,
- new HmacUtils(hmacAlgorithm, STANDARD_KEY_BYTES).hmac(new
ByteArrayInputStream(STANDARD_PHRASE_BYTES)));
- }
-
- @Test
- public void testMacString() {
- Assert.assertArrayEquals(standardResultBytes, new
HmacUtils(hmacAlgorithm, STANDARD_KEY_BYTES).hmac(STANDARD_PHRASE_STRING));
- }
-
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.codec.digest;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.security.NoSuchAlgorithmException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+
+import javax.crypto.Mac;
+
+import org.apache.commons.lang3.JavaVersion;
+import org.apache.commons.lang3.SystemUtils;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Assume;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+/**
+ * Tests {@link HmacAlgorithms}.
+ *
+ * @since 1.11
+ */
+@RunWith(Parameterized.class)
+public class HmacAlgorithmsTest {
+
+ static final String STANDARD_KEY_STRING = "key";
+
+ static final byte[] STANDARD_KEY_BYTES = STANDARD_KEY_STRING.getBytes();
+
+ static final byte[] STANDARD_MD5_RESULT_BYTES = new byte[] { -128, 7, 7,
19, 70, 62, 119, 73, -71, 12, 45, -62, 73,
+ 17, -30, 117 };
+
+ static final String STANDARD_MD5_RESULT_STRING =
"80070713463e7749b90c2dc24911e275";
+
+ static final String STANDARD_PHRASE_STRING = "The quick brown fox jumps
over the lazy dog";
+
+ static final byte[] STANDARD_PHRASE_BYTES =
STANDARD_PHRASE_STRING.getBytes();
+
+ static final byte[] STANDARD_SHA1_RESULT_BYTES = new byte[] { -34, 124,
-101, -123, -72, -73, -118, -90, -68, -118,
+ 122, 54, -9, 10, -112, 112, 28, -99, -76, -39 };
+
+ static final String STANDARD_SHA1_RESULT_STRING =
"de7c9b85b8b78aa6bc8a7a36f70a90701c9db4d9";
+
+ static final byte[] STANDARD_SHA224_RESULT_BYTES = new byte[] { -120, -1,
-117, 84, 103, 93, 57, -72, -9, 35, 34,
+ -26, 95, -7, 69, -59, 45, -106, 55, -103, -120, -83, -94, 86, 57,
116, 126, 105 };
+
+ static final String STANDARD_SHA224_RESULT_STRING =
"88ff8b54675d39b8f72322e65ff945c52d96379988ada25639747e69";
+
+ static final byte[] STANDARD_SHA256_RESULT_BYTES = new byte[] { -9, -68,
-125, -12, 48, 83, -124, 36, -79, 50, -104,
+ -26, -86, 111, -79, 67, -17, 77, 89, -95, 73, 70, 23, 89, -105,
71, -99, -68, 45, 26, 60, -40 };
+
+ static final String STANDARD_SHA256_RESULT_STRING =
"f7bc83f430538424b13298e6aa6fb143ef4d59a14946175997479dbc2d1a3cd8";
+
+ static final byte[] STANDARD_SHA384_RESULT_BYTES = new byte[] { -41, -12,
114, 126, 44, 11, 57, -82, 15, 30, 64,
+ -52, -106, -10, 2, 66, -43, -73, -128, 24, 65, -50, -90, -4, 89,
44, 93, 62, 26, -27, 7, 0, 88, 42, -106,
+ -49, 53, -31, -27, 84, -103, 95, -28, -32, 51, -127, -62, 55 };
+
+ static final String STANDARD_SHA384_RESULT_STRING =
"D7F4727E2C0B39AE0F1E40CC96F60242D5B7801841CEA6FC592C5D3E1AE50700582A96CF35E1E554995FE4E03381C237"
+ .toLowerCase();
+
+ static final byte[] STANDARD_SHA512_RESULT_BYTES = new byte[] { -76, 42,
-16, -112, 87, -70, -63, -30, -44, 23, 8,
+ -28, -118, -112, 46, 9, -75, -1, 127, 18, -85, 66, -118, 79, -24,
102, 83, -57, 61, -46, 72, -5, -126, -7,
+ 72, -91, 73, -9, -73, -111, -91, -76, 25, 21, -18, 77, 30, -61,
-109, 83, 87, -28, -30, 49, 114, 80, -48,
+ 55, 42, -6, 46, -66, -21, 58 };
+
+ static final String STANDARD_SHA512_RESULT_STRING =
"B42AF09057BAC1E2D41708E48A902E09B5FF7F12AB428A4FE86653C73DD248FB82F948A549F7B791A5B41915EE4D1EC3935357E4E2317250D0372AFA2EBEEB3A"
+ .toLowerCase();
+
+ private static final byte[] EMPTY_BYTE_ARRAY = new byte[] {};
+
+ // TODO HMAC_SHA_224
+ @Parameters(name = "{0}")
+ public static Collection<Object[]> data() {
+ List<Object[]> list = Arrays.asList(
+ // @formatter:off
+ new Object[][] { { HmacAlgorithms.HMAC_MD5,
STANDARD_MD5_RESULT_BYTES, STANDARD_MD5_RESULT_STRING },
+ { HmacAlgorithms.HMAC_SHA_1,
STANDARD_SHA1_RESULT_BYTES, STANDARD_SHA1_RESULT_STRING },
+ { HmacAlgorithms.HMAC_SHA_256,
STANDARD_SHA256_RESULT_BYTES, STANDARD_SHA256_RESULT_STRING },
+ { HmacAlgorithms.HMAC_SHA_384,
STANDARD_SHA384_RESULT_BYTES, STANDARD_SHA384_RESULT_STRING },
+ { HmacAlgorithms.HMAC_SHA_512,
STANDARD_SHA512_RESULT_BYTES, STANDARD_SHA512_RESULT_STRING } });
+ // @formatter:on
+ if (SystemUtils.isJavaVersionAtLeast(JavaVersion.JAVA_1_8)) {
+ list = new ArrayList<>(list);
+ list.add(new Object[] {HmacAlgorithms.HMAC_SHA_224,
STANDARD_SHA224_RESULT_BYTES, STANDARD_SHA224_RESULT_STRING});
+ }
+ return list;
+ }
+
+ private DigestUtilsTest digestUtilsTest;
+
+ private final HmacAlgorithms hmacAlgorithm;
+
+ private final byte[] standardResultBytes;
+ private final String standardResultString;
+
+ public HmacAlgorithmsTest(final HmacAlgorithms hmacAlgorithm, final byte[]
standardResultBytes, final String standardResultString) {
+ Assume.assumeTrue(HmacUtils.isAvailable(hmacAlgorithm));
+ this.hmacAlgorithm = hmacAlgorithm;
+ this.standardResultBytes = standardResultBytes;
+ this.standardResultString = standardResultString;
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ digestUtilsTest = new DigestUtilsTest();
+ digestUtilsTest.setUp();
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ digestUtilsTest.tearDown();
+ digestUtilsTest = null;
+ }
+
+ @Test
+ public void testAlgorithm() throws NoSuchAlgorithmException {
+ final String algorithm = hmacAlgorithm.getName();
+ Assert.assertNotNull(algorithm);
+ Assert.assertFalse(algorithm.isEmpty());
+ Assume.assumeTrue(HmacUtils.isAvailable(hmacAlgorithm));
+ Mac.getInstance(algorithm);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testGetHmacEmptyKey() {
+ HmacUtils.getInitializedMac(hmacAlgorithm, EMPTY_BYTE_ARRAY);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testGetHmacNullKey() {
+ HmacUtils.getInitializedMac(hmacAlgorithm, null);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testHmacFailByteArray() {
+ new HmacUtils(hmacAlgorithm, (byte[])
null).hmac(STANDARD_PHRASE_BYTES);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testHmacFailInputStream() throws IOException {
+ new HmacUtils(hmacAlgorithm, (byte[]) null).hmac(new
ByteArrayInputStream(STANDARD_PHRASE_BYTES));
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testHmacFailString() {
+ new HmacUtils(hmacAlgorithm, (String)
null).hmac(STANDARD_PHRASE_STRING);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testHmacHexFailByteArray() {
+ new HmacUtils(hmacAlgorithm, (byte[])
null).hmac(STANDARD_PHRASE_BYTES);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testHmacHexFailInputStream() throws IOException {
+ new HmacUtils(hmacAlgorithm, (byte[]) null).hmac(new
ByteArrayInputStream(STANDARD_PHRASE_BYTES));
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testHmacHexFailString() {
+ new HmacUtils(hmacAlgorithm, (String)
null).hmac(STANDARD_PHRASE_STRING);
+ }
+
+ @Test
+ public void testInitializedMac() {
+ final Mac mac = HmacUtils.getInitializedMac(hmacAlgorithm,
STANDARD_KEY_BYTES);
+ final Mac mac2 = HmacUtils.getInitializedMac(hmacAlgorithm.getName(),
STANDARD_KEY_BYTES);
+ Assert.assertArrayEquals(standardResultBytes,
HmacUtils.updateHmac(mac, STANDARD_PHRASE_STRING).doFinal());
+ Assert.assertArrayEquals(standardResultBytes,
HmacUtils.updateHmac(mac2, STANDARD_PHRASE_STRING).doFinal());
+ }
+
+ @Test
+ public void testMacByteArary() {
+ Assert.assertArrayEquals(standardResultBytes, new
HmacUtils(hmacAlgorithm, STANDARD_KEY_BYTES).hmac(STANDARD_PHRASE_BYTES));
+ }
+
+ @Test
+ public void testMacHexByteArray() {
+ Assert.assertEquals(standardResultString, new HmacUtils(hmacAlgorithm,
STANDARD_KEY_BYTES).hmacHex(STANDARD_PHRASE_BYTES));
+ }
+
+ @Test
+ public void testMacHexInputStream() throws IOException {
+ Assert.assertEquals(standardResultString,
+ new HmacUtils(hmacAlgorithm, STANDARD_KEY_BYTES).hmacHex(new
ByteArrayInputStream(STANDARD_PHRASE_BYTES)));
+ }
+
+ @Test
+ public void testMacHexString() {
+ Assert.assertEquals(standardResultString, new HmacUtils(hmacAlgorithm,
STANDARD_KEY_BYTES).hmacHex(STANDARD_PHRASE_STRING));
+ }
+
+ @Test
+ public void testMacInputStream() throws IOException {
+ Assert.assertArrayEquals(standardResultBytes,
+ new HmacUtils(hmacAlgorithm, STANDARD_KEY_BYTES).hmac(new
ByteArrayInputStream(STANDARD_PHRASE_BYTES)));
+ }
+
+ @Test
+ public void testMacString() {
+ Assert.assertArrayEquals(standardResultBytes, new
HmacUtils(hmacAlgorithm, STANDARD_KEY_BYTES).hmac(STANDARD_PHRASE_STRING));
+ }
+
+}
diff --git
a/src/test/java/org/apache/commons/codec/digest/MessageDigestAlgorithmsTest.java
b/src/test/java/org/apache/commons/codec/digest/MessageDigestAlgorithmsTest.java
index 6a628a7..bae787c 100644
---
a/src/test/java/org/apache/commons/codec/digest/MessageDigestAlgorithmsTest.java
+++
b/src/test/java/org/apache/commons/codec/digest/MessageDigestAlgorithmsTest.java
@@ -1,164 +1,164 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.commons.codec.digest;
-
-import java.io.ByteArrayInputStream;
-import java.io.File;
-import java.io.IOException;
-import java.lang.reflect.Field;
-import java.lang.reflect.Modifier;
-import java.nio.ByteBuffer;
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-
-import org.junit.After;
-import org.junit.Assert;
-import org.junit.Assume;
-import org.junit.Before;
-import org.junit.BeforeClass;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
-import org.junit.runners.Parameterized.Parameters;
-
-/**
- * Tests {@link MessageDigestAlgorithms}.
- *
- * @since 1.11
- */
-@RunWith(Parameterized.class)
-public class MessageDigestAlgorithmsTest {
-
- @Parameters(name = "{0}")
- public static Object[] data() {
- return MessageDigestAlgorithms.values();
- }
-
- private static boolean contains(final String key) {
- for(final String s : MessageDigestAlgorithms.values()) {
- if (s.equals(key)) {
- return true;
- }
- }
- return false;
- }
-
- @BeforeClass
- public static void checkValues() throws Exception {
- final Field [] fields =
MessageDigestAlgorithms.class.getDeclaredFields();
- boolean ok = true;
- int psf = 0;
- for(final Field f : fields) {
- // Only interested in public fields
- final int modifiers = f.getModifiers();
- if (Modifier.isPublic(modifiers) && Modifier.isStatic(modifiers)
&& Modifier.isFinal(modifiers)) {
- psf++;
- if (!contains((String) f.get(null))) {
- System.out.println("Not found in
MessageDigestAlgorithms.values(): "+f.getName());
- ok = false;
- }
- }
- }
- if (!ok) {
- Assert.fail("One or more entries are missing from the
MessageDigestAlgorithms.values() array");
- }
- if (psf != MessageDigestAlgorithms.values().length) {
- Assert.fail("One or more unexpected entries found in the
MessageDigestAlgorithms.values() array");
- }
- }
-
- private DigestUtilsTest digestUtilsTest;
-
- private final String messageDigestAlgorithm;
-
- public MessageDigestAlgorithmsTest(final String messageDigestAlgorithm) {
- this.messageDigestAlgorithm = messageDigestAlgorithm;
- }
-
- private byte[] digestTestData() {
- return
DigestUtils.digest(DigestUtils.getDigest(messageDigestAlgorithm),getTestData());
- }
-
- private byte[] getTestData() {
- return digestUtilsTest.getTestData();
- }
-
- private File getTestFile() {
- return digestUtilsTest.getTestFile();
- }
-
- @Before
- public void setUp() throws Exception {
- digestUtilsTest = new DigestUtilsTest();
- digestUtilsTest.setUp();
- }
-
- @After
- public void tearDown() throws Exception {
- digestUtilsTest.tearDown();
- digestUtilsTest = null;
- }
-
- @Test
- public void testAlgorithm() throws NoSuchAlgorithmException {
- final String algorithm = messageDigestAlgorithm;
- Assert.assertNotNull(algorithm);
- Assert.assertFalse(algorithm.isEmpty());
- Assume.assumeTrue(DigestUtils.isAvailable(messageDigestAlgorithm));
- MessageDigest.getInstance(algorithm);
- }
-
- @Test
- public void testDigestByteArray() {
- Assume.assumeTrue(DigestUtils.isAvailable(messageDigestAlgorithm));
- Assert.assertArrayEquals(digestTestData(),
-
DigestUtils.digest(DigestUtils.getDigest(messageDigestAlgorithm),
getTestData()));
- Assert.assertArrayEquals(digestTestData(),
DigestUtils.digest(DigestUtils.getDigest(messageDigestAlgorithm),getTestData()));
- }
-
- @Test
- public void testDigestByteBuffer() {
- Assume.assumeTrue(DigestUtils.isAvailable(messageDigestAlgorithm));
- Assert.assertArrayEquals(digestTestData(),
-
DigestUtils.digest(DigestUtils.getDigest(messageDigestAlgorithm),
ByteBuffer.wrap(getTestData())));
- Assert.assertArrayEquals(digestTestData(),
DigestUtils.digest(DigestUtils.getDigest(messageDigestAlgorithm),ByteBuffer.wrap(getTestData())));
- }
-
- @Test
- public void testDigestFile() throws IOException {
- Assume.assumeTrue(DigestUtils.isAvailable(messageDigestAlgorithm));
- Assert.assertArrayEquals(digestTestData(),
-
DigestUtils.digest(DigestUtils.getDigest(messageDigestAlgorithm),
getTestFile()));
- Assert.assertArrayEquals(digestTestData(),
DigestUtils.digest(DigestUtils.getDigest(messageDigestAlgorithm),getTestFile()));
- }
-
- @Test
- public void testDigestInputStream() throws IOException {
- Assume.assumeTrue(DigestUtils.isAvailable(messageDigestAlgorithm));
- Assert.assertArrayEquals(digestTestData(),
-
DigestUtils.digest(DigestUtils.getDigest(messageDigestAlgorithm), new
ByteArrayInputStream(getTestData())));
- Assert.assertArrayEquals(digestTestData(),
DigestUtils.digest(DigestUtils.getDigest(messageDigestAlgorithm),new
ByteArrayInputStream(getTestData())));
- }
-
- @Test
- public void testGetMessageDigest() {
- Assume.assumeTrue(DigestUtils.isAvailable(messageDigestAlgorithm));
- final MessageDigest messageDigest =
DigestUtils.getDigest(messageDigestAlgorithm);
- Assert.assertEquals(messageDigestAlgorithm,
messageDigest.getAlgorithm());
- }
-
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.codec.digest;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.IOException;
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.nio.ByteBuffer;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Assume;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+/**
+ * Tests {@link MessageDigestAlgorithms}.
+ *
+ * @since 1.11
+ */
+@RunWith(Parameterized.class)
+public class MessageDigestAlgorithmsTest {
+
+ @Parameters(name = "{0}")
+ public static Object[] data() {
+ return MessageDigestAlgorithms.values();
+ }
+
+ private static boolean contains(final String key) {
+ for(final String s : MessageDigestAlgorithms.values()) {
+ if (s.equals(key)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @BeforeClass
+ public static void checkValues() throws Exception {
+ final Field [] fields =
MessageDigestAlgorithms.class.getDeclaredFields();
+ boolean ok = true;
+ int psf = 0;
+ for(final Field f : fields) {
+ // Only interested in public fields
+ final int modifiers = f.getModifiers();
+ if (Modifier.isPublic(modifiers) && Modifier.isStatic(modifiers)
&& Modifier.isFinal(modifiers)) {
+ psf++;
+ if (!contains((String) f.get(null))) {
+ System.out.println("Not found in
MessageDigestAlgorithms.values(): "+f.getName());
+ ok = false;
+ }
+ }
+ }
+ if (!ok) {
+ Assert.fail("One or more entries are missing from the
MessageDigestAlgorithms.values() array");
+ }
+ if (psf != MessageDigestAlgorithms.values().length) {
+ Assert.fail("One or more unexpected entries found in the
MessageDigestAlgorithms.values() array");
+ }
+ }
+
+ private DigestUtilsTest digestUtilsTest;
+
+ private final String messageDigestAlgorithm;
+
+ public MessageDigestAlgorithmsTest(final String messageDigestAlgorithm) {
+ this.messageDigestAlgorithm = messageDigestAlgorithm;
+ }
+
+ private byte[] digestTestData() {
+ return
DigestUtils.digest(DigestUtils.getDigest(messageDigestAlgorithm),getTestData());
+ }
+
+ private byte[] getTestData() {
+ return digestUtilsTest.getTestData();
+ }
+
+ private File getTestFile() {
+ return digestUtilsTest.getTestFile();
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ digestUtilsTest = new DigestUtilsTest();
+ digestUtilsTest.setUp();
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ digestUtilsTest.tearDown();
+ digestUtilsTest = null;
+ }
+
+ @Test
+ public void testAlgorithm() throws NoSuchAlgorithmException {
+ final String algorithm = messageDigestAlgorithm;
+ Assert.assertNotNull(algorithm);
+ Assert.assertFalse(algorithm.isEmpty());
+ Assume.assumeTrue(DigestUtils.isAvailable(messageDigestAlgorithm));
+ MessageDigest.getInstance(algorithm);
+ }
+
+ @Test
+ public void testDigestByteArray() {
+ Assume.assumeTrue(DigestUtils.isAvailable(messageDigestAlgorithm));
+ Assert.assertArrayEquals(digestTestData(),
+
DigestUtils.digest(DigestUtils.getDigest(messageDigestAlgorithm),
getTestData()));
+ Assert.assertArrayEquals(digestTestData(),
DigestUtils.digest(DigestUtils.getDigest(messageDigestAlgorithm),getTestData()));
+ }
+
+ @Test
+ public void testDigestByteBuffer() {
+ Assume.assumeTrue(DigestUtils.isAvailable(messageDigestAlgorithm));
+ Assert.assertArrayEquals(digestTestData(),
+
DigestUtils.digest(DigestUtils.getDigest(messageDigestAlgorithm),
ByteBuffer.wrap(getTestData())));
+ Assert.assertArrayEquals(digestTestData(),
DigestUtils.digest(DigestUtils.getDigest(messageDigestAlgorithm),ByteBuffer.wrap(getTestData())));
+ }
+
+ @Test
+ public void testDigestFile() throws IOException {
+ Assume.assumeTrue(DigestUtils.isAvailable(messageDigestAlgorithm));
+ Assert.assertArrayEquals(digestTestData(),
+
DigestUtils.digest(DigestUtils.getDigest(messageDigestAlgorithm),
getTestFile()));
+ Assert.assertArrayEquals(digestTestData(),
DigestUtils.digest(DigestUtils.getDigest(messageDigestAlgorithm),getTestFile()));
+ }
+
+ @Test
+ public void testDigestInputStream() throws IOException {
+ Assume.assumeTrue(DigestUtils.isAvailable(messageDigestAlgorithm));
+ Assert.assertArrayEquals(digestTestData(),
+
DigestUtils.digest(DigestUtils.getDigest(messageDigestAlgorithm), new
ByteArrayInputStream(getTestData())));
+ Assert.assertArrayEquals(digestTestData(),
DigestUtils.digest(DigestUtils.getDigest(messageDigestAlgorithm),new
ByteArrayInputStream(getTestData())));
+ }
+
+ @Test
+ public void testGetMessageDigest() {
+ Assume.assumeTrue(DigestUtils.isAvailable(messageDigestAlgorithm));
+ final MessageDigest messageDigest =
DigestUtils.getDigest(messageDigestAlgorithm);
+ Assert.assertEquals(messageDigestAlgorithm,
messageDigest.getAlgorithm());
+ }
+
+}
diff --git
a/src/test/java/org/apache/commons/codec/digest/PureJavaCrc32Test.java
b/src/test/java/org/apache/commons/codec/digest/PureJavaCrc32Test.java
index f5f0c38..df78d86 100644
--- a/src/test/java/org/apache/commons/codec/digest/PureJavaCrc32Test.java
+++ b/src/test/java/org/apache/commons/codec/digest/PureJavaCrc32Test.java
@@ -1,395 +1,395 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.commons.codec.digest;
-
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.PrintStream;
-import java.lang.reflect.Constructor;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Properties;
-import java.util.Random;
-import java.util.zip.CRC32;
-import java.util.zip.Checksum;
-
-import org.junit.Assert;
-import org.junit.Test;
-
-/**
- * Unit test to verify that the pure-Java CRC32 algorithm gives
- * the same results as the built-in implementation.
- *
- * Copied from Hadoop 2.6.3 (Renamed TestPureJavaCrc32 to PureJavaCrc32Test).
- * @since 1.11
- */
-public class PureJavaCrc32Test {
- private final CRC32 theirs = new CRC32();
- private final PureJavaCrc32 ours = new PureJavaCrc32();
-
- @Test
- public void testCorrectness() throws Exception {
- checkSame();
-
- theirs.update(104);
- ours.update(104);
- checkSame();
-
- checkOnBytes(new byte[] {40, 60, 97, -70}, false);
-
- checkOnBytes("hello world!".getBytes("UTF-8"), false);
-
- final Random random1 = new Random();
- final Random random2 = new Random();
- for (int i = 0; i < 10000; i++) {
- final byte randomBytes[] = new byte[random1.nextInt(2048)];
- random2.nextBytes(randomBytes);
- checkOnBytes(randomBytes, false);
- }
-
- }
-
- private void checkOnBytes(final byte[] bytes, final boolean print) {
- theirs.reset();
- ours.reset();
- checkSame();
-
- for (final byte b : bytes) {
- ours.update(b);
- theirs.update(b);
- checkSame();
- }
-
- if (print) {
- System.out.println("theirs:\t" + Long.toHexString(theirs.getValue())
- + "\nours:\t" + Long.toHexString(ours.getValue()));
- }
-
- theirs.reset();
- ours.reset();
-
- ours.update(bytes, 0, bytes.length);
- theirs.update(bytes, 0, bytes.length);
- if (print) {
- System.out.println("theirs:\t" + Long.toHexString(theirs.getValue())
- + "\nours:\t" + Long.toHexString(ours.getValue()));
- }
-
- checkSame();
-
- if (bytes.length >= 10) {
- ours.update(bytes, 5, 5);
- theirs.update(bytes, 5, 5);
- checkSame();
- }
- }
-
- private void checkSame() {
- Assert.assertEquals(theirs.getValue(), ours.getValue());
- }
-
- /**
- * Generate a table to perform checksums based on the same CRC-32 polynomial
- * that java.util.zip.CRC32 uses.
- */
- public static class Table {
- private final int[][] tables;
-
- private Table(final int nBits, final int nTables,
- final long polynomial) {
- tables = new int[nTables][];
- final int size = 1 << nBits;
- for(int i = 0; i < tables.length; i++) {
- tables[i] = new int[size];
- }
-
- //compute the first table
- final int[] first = tables[0];
- for (int i = 0; i < first.length; i++) {
- int crc = i;
- for (int j = 0; j < nBits; j++) {
- if ((crc & 1) == 1) {
- crc >>>= 1;
- crc ^= polynomial;
- } else {
- crc >>>= 1;
- }
- }
- first[i] = crc;
- }
-
- //compute the remaining tables
- final int mask = first.length - 1;
- for(int j = 1; j < tables.length; j++) {
- final int[] previous = tables[j-1];
- final int[] current = tables[j];
- for (int i = 0; i < current.length; i++) {
- current[i] = (previous[i] >>> nBits) ^ first[previous[i] & mask];
- }
- }
- }
-
- String[] toStrings(final String nameformat) {
- final String[] s = new String[tables.length];
- for (int j = 0; j < tables.length; j++) {
- final int[] t = tables[j];
- final StringBuilder b = new StringBuilder();
- b.append(String.format(" /* "+ nameformat +" */", j));
- for (int i = 0; i < t.length;) {
- b.append("\n ");
- for(int k = 0; k < 4; k++) {
- b.append(String.format("0x%08X, ", t[i++]));
- }
- }
- s[j] = b.toString();
- }
- return s;
- }
-
- @Override
- public String toString() {
- final StringBuilder b = new StringBuilder();
-
- final String tableFormat = String.format("T%d_",
- Integer.numberOfTrailingZeros(tables[0].length)) + "%d";
- final String startFormat = " private static final int
"+tableFormat+"_start = %d*256;";
-
- for (int j = 0; j < tables.length; j++) {
- b.append(String.format(startFormat, j, j));
- b.append("\n");
- }
-
- b.append(" private static final int[] T = new int[] {");
- for(final String s : toStrings(tableFormat)) {
- b.append("\n");
- b.append(s);
- }
- b.setCharAt(b.length() - 2, '\n');
- b.append(" };\n");
- return b.toString();
- }
-
- /** Generate CRC-32 lookup tables */
- public static void main(final String[] args) throws
FileNotFoundException {
- if (args.length != 1) {
- System.err.println("Usage: " + Table.class.getName() + "
<polynomial>");
- System.exit(1);
- }
- final long polynomial = Long.parseLong(args[0], 16);
-
- final int i = 8;
- final Table t = new Table(i, 16, polynomial);
- final String s = t.toString();
- System.out.println(s);
-
- // print to a file
- try (final PrintStream out = new PrintStream(new
FileOutputStream("table" + i + ".txt"), true)) {
- out.println(s);
- }
- }
- }
-
- /**
- * Performance tests to compare performance of the Pure Java implementation
- * to the built-in java.util.zip implementation. This can be run from the
- * command line with:
- *
- * java -cp path/to/test/classes:path/to/common/classes \
- * 'org.apache.hadoop.util.TestPureJavaCrc32$PerformanceTest'
- *
- * The output is in JIRA table format.
- */
- public static class PerformanceTest {
- public static final int MAX_LEN = 32*1024*1024; // up to 32MB chunks
- public static final int BYTES_PER_SIZE = MAX_LEN * 4;
-
- static final Class<? extends Checksum> zip = CRC32.class;
- static final List<Class<? extends Checksum>> CRCS = new ArrayList<>();
- static {
- CRCS.add(zip);
- CRCS.add(PureJavaCrc32.class);
- }
-
-
- public static void main(final String args[]) throws Exception {
- printSystemProperties(System.out);
- doBench(CRCS, System.out);
- }
-
- private static void printCell(final String s, final int width, final
PrintStream out) {
- final int w = s.length() > width? s.length(): width;
- out.printf(" %" + w + "s |", s);
- }
-
- private static void doBench(final List<Class<? extends Checksum>> crcs,
- final PrintStream out) throws Exception {
- final byte[] bytes = new byte[MAX_LEN];
- new Random().nextBytes(bytes);
-
- // Print header
- out.printf("\nPerformance Table (The unit is MB/sec; #T = #Theads)\n");
-
- // Warm up implementations to get jit going.
- for (final Class<? extends Checksum> c : crcs) {
- doBench(c, 1, bytes, 2);
- doBench(c, 1, bytes, 2101);
- }
-
- // Test on a variety of sizes with different number of threads
- for (int size = 32; size <= MAX_LEN; size <<= 1) {
- doBench(crcs, bytes, size, out);
- }
- }
-
- private static void doBench(final List<Class<? extends Checksum>> crcs,
- final byte[] bytes, final int size, final PrintStream out) throws
Exception {
- final String numBytesStr = " #Bytes ";
- final String numThreadsStr = "#T";
- final String diffStr = "% diff";
-
- out.print('|');
- printCell(numBytesStr, 0, out);
- printCell(numThreadsStr, 0, out);
- for (int i = 0; i < crcs.size(); i++) {
- final Class<? extends Checksum> c = crcs.get(i);
- out.print('|');
- printCell(c.getSimpleName(), 8, out);
- for(int j = 0; j < i; j++) {
- printCell(diffStr, diffStr.length(), out);
- }
- }
- out.printf("\n");
-
- for(int numThreads = 1; numThreads <= 16; numThreads <<= 1) {
- out.printf("|");
- printCell(String.valueOf(size), numBytesStr.length(), out);
- printCell(String.valueOf(numThreads), numThreadsStr.length(), out);
-
- BenchResult expected = null;
- final List<BenchResult> previous = new ArrayList<>();
- for(final Class<? extends Checksum> c : crcs) {
- System.gc();
-
- final BenchResult result = doBench(c, numThreads, bytes, size);
- printCell(String.format("%9.1f", result.mbps),
- c.getSimpleName().length()+1, out);
-
- //check result
- if(c == zip) {
- expected = result;
- } else if (expected == null) {
- throw new RuntimeException("The first class is "
- + c.getName() + " but not " + zip.getName());
- } else if (result.value != expected.value) {
- throw new RuntimeException(c + " has bugs!");
- }
-
- //compare result with previous
- for(final BenchResult p : previous) {
- final double diff = (result.mbps - p.mbps) / p.mbps * 100;
- printCell(String.format("%5.1f%%", diff), diffStr.length(), out);
- }
- previous.add(result);
- }
- out.printf("\n");
- }
- }
-
- private static BenchResult doBench(final Class<? extends Checksum> clazz,
- final int numThreads, final byte[] bytes, final int size)
- throws Exception {
-
- final Thread[] threads = new Thread[numThreads];
- final BenchResult[] results = new BenchResult[threads.length];
-
- {
- final int trials = BYTES_PER_SIZE / size;
- final double mbProcessed = trials * size / 1024.0 / 1024.0;
- final Constructor<? extends Checksum> ctor = clazz.getConstructor();
-
- for(int i = 0; i < threads.length; i++) {
- final int index = i;
- threads[i] = new Thread() {
- final Checksum crc = ctor.newInstance();
-
- @Override
- public void run() {
- final long st = System.nanoTime();
- crc.reset();
- for (int trialIndex = 0; trialIndex < trials; trialIndex++) {
- crc.update(bytes, 0, size);
- }
- final long et = System.nanoTime();
- final double secsElapsed = (et - st) / 1000000000.0d;
- results[index] = new BenchResult(crc.getValue(),
mbProcessed/secsElapsed);
- }
- };
- }
- }
-
- for (final Thread thread : threads) {
- thread.start();
- }
- for (final Thread thread : threads) {
- thread.join();
- }
-
- final long expected = results[0].value;
- double sum = results[0].mbps;
- for(int i = 1; i < results.length; i++) {
- if (results[i].value != expected) {
- throw new AssertionError(clazz.getSimpleName() + " results not
matched.");
- }
- sum += results[i].mbps;
- }
- return new BenchResult(expected, sum/results.length);
- }
-
- private static class BenchResult {
- /** CRC value */
- final long value;
- /** Speed (MB per second) */
- final double mbps;
-
- BenchResult(final long value, final double mbps) {
- this.value = value;
- this.mbps = mbps;
- }
- }
-
- private static void printSystemProperties(final PrintStream out) {
- final String[] names = {
- "java.version",
- "java.runtime.name",
- "java.runtime.version",
- "java.vm.version",
- "java.vm.vendor",
- "java.vm.name",
- "java.vm.specification.version",
- "java.specification.version",
- "os.arch",
- "os.name",
- "os.version"
- };
- final Properties p = System.getProperties();
- for(final String n : names) {
- out.println(n + " = " + p.getProperty(n));
- }
- }
- }
-}
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.codec.digest;
+
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.PrintStream;
+import java.lang.reflect.Constructor;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Properties;
+import java.util.Random;
+import java.util.zip.CRC32;
+import java.util.zip.Checksum;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * Unit test to verify that the pure-Java CRC32 algorithm gives
+ * the same results as the built-in implementation.
+ *
+ * Copied from Hadoop 2.6.3 (Renamed TestPureJavaCrc32 to PureJavaCrc32Test).
+ * @since 1.11
+ */
+public class PureJavaCrc32Test {
+ private final CRC32 theirs = new CRC32();
+ private final PureJavaCrc32 ours = new PureJavaCrc32();
+
+ @Test
+ public void testCorrectness() throws Exception {
+ checkSame();
+
+ theirs.update(104);
+ ours.update(104);
+ checkSame();
+
+ checkOnBytes(new byte[] {40, 60, 97, -70}, false);
+
+ checkOnBytes("hello world!".getBytes("UTF-8"), false);
+
+ final Random random1 = new Random();
+ final Random random2 = new Random();
+ for (int i = 0; i < 10000; i++) {
+ final byte randomBytes[] = new byte[random1.nextInt(2048)];
+ random2.nextBytes(randomBytes);
+ checkOnBytes(randomBytes, false);
+ }
+
+ }
+
+ private void checkOnBytes(final byte[] bytes, final boolean print) {
+ theirs.reset();
+ ours.reset();
+ checkSame();
+
+ for (final byte b : bytes) {
+ ours.update(b);
+ theirs.update(b);
+ checkSame();
+ }
+
+ if (print) {
+ System.out.println("theirs:\t" + Long.toHexString(theirs.getValue())
+ + "\nours:\t" + Long.toHexString(ours.getValue()));
+ }
+
+ theirs.reset();
+ ours.reset();
+
+ ours.update(bytes, 0, bytes.length);
+ theirs.update(bytes, 0, bytes.length);
+ if (print) {
+ System.out.println("theirs:\t" + Long.toHexString(theirs.getValue())
+ + "\nours:\t" + Long.toHexString(ours.getValue()));
+ }
+
+ checkSame();
+
+ if (bytes.length >= 10) {
+ ours.update(bytes, 5, 5);
+ theirs.update(bytes, 5, 5);
+ checkSame();
+ }
+ }
+
+ private void checkSame() {
+ Assert.assertEquals(theirs.getValue(), ours.getValue());
+ }
+
+ /**
+ * Generate a table to perform checksums based on the same CRC-32 polynomial
+ * that java.util.zip.CRC32 uses.
+ */
+ public static class Table {
+ private final int[][] tables;
+
+ private Table(final int nBits, final int nTables,
+ final long polynomial) {
+ tables = new int[nTables][];
+ final int size = 1 << nBits;
+ for(int i = 0; i < tables.length; i++) {
+ tables[i] = new int[size];
+ }
+
+ //compute the first table
+ final int[] first = tables[0];
+ for (int i = 0; i < first.length; i++) {
+ int crc = i;
+ for (int j = 0; j < nBits; j++) {
+ if ((crc & 1) == 1) {
+ crc >>>= 1;
+ crc ^= polynomial;
+ } else {
+ crc >>>= 1;
+ }
+ }
+ first[i] = crc;
+ }
+
+ //compute the remaining tables
+ final int mask = first.length - 1;
+ for(int j = 1; j < tables.length; j++) {
+ final int[] previous = tables[j-1];
+ final int[] current = tables[j];
+ for (int i = 0; i < current.length; i++) {
+ current[i] = (previous[i] >>> nBits) ^ first[previous[i] & mask];
+ }
+ }
+ }
+
+ String[] toStrings(final String nameformat) {
+ final String[] s = new String[tables.length];
+ for (int j = 0; j < tables.length; j++) {
+ final int[] t = tables[j];
+ final StringBuilder b = new StringBuilder();
+ b.append(String.format(" /* "+ nameformat +" */", j));
+ for (int i = 0; i < t.length;) {
+ b.append("\n ");
+ for(int k = 0; k < 4; k++) {
+ b.append(String.format("0x%08X, ", t[i++]));
+ }
+ }
+ s[j] = b.toString();
+ }
+ return s;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder b = new StringBuilder();
+
+ final String tableFormat = String.format("T%d_",
+ Integer.numberOfTrailingZeros(tables[0].length)) + "%d";
+ final String startFormat = " private static final int
"+tableFormat+"_start = %d*256;";
+
+ for (int j = 0; j < tables.length; j++) {
+ b.append(String.format(startFormat, j, j));
+ b.append("\n");
+ }
+
+ b.append(" private static final int[] T = new int[] {");
+ for(final String s : toStrings(tableFormat)) {
+ b.append("\n");
+ b.append(s);
+ }
+ b.setCharAt(b.length() - 2, '\n');
+ b.append(" };\n");
+ return b.toString();
+ }
+
+ /** Generate CRC-32 lookup tables */
+ public static void main(final String[] args) throws
FileNotFoundException {
+ if (args.length != 1) {
+ System.err.println("Usage: " + Table.class.getName() + "
<polynomial>");
+ System.exit(1);
+ }
+ final long polynomial = Long.parseLong(args[0], 16);
+
+ final int i = 8;
+ final Table t = new Table(i, 16, polynomial);
+ final String s = t.toString();
+ System.out.println(s);
+
+ // print to a file
+ try (final PrintStream out = new PrintStream(new
FileOutputStream("table" + i + ".txt"), true)) {
+ out.println(s);
+ }
+ }
+ }
+
+ /**
+ * Performance tests to compare performance of the Pure Java implementation
+ * to the built-in java.util.zip implementation. This can be run from the
+ * command line with:
+ *
+ * java -cp path/to/test/classes:path/to/common/classes \
+ * 'org.apache.hadoop.util.TestPureJavaCrc32$PerformanceTest'
+ *
+ * The output is in JIRA table format.
+ */
+ public static class PerformanceTest {
+ public static final int MAX_LEN = 32*1024*1024; // up to 32MB chunks
+ public static final int BYTES_PER_SIZE = MAX_LEN * 4;
+
+ static final Class<? extends Checksum> zip = CRC32.class;
+ static final List<Class<? extends Checksum>> CRCS = new ArrayList<>();
+ static {
+ CRCS.add(zip);
+ CRCS.add(PureJavaCrc32.class);
+ }
+
+
+ public static void main(final String args[]) throws Exception {
+ printSystemProperties(System.out);
+ doBench(CRCS, System.out);
+ }
+
+ private static void printCell(final String s, final int width, final
PrintStream out) {
+ final int w = s.length() > width? s.length(): width;
+ out.printf(" %" + w + "s |", s);
+ }
+
+ private static void doBench(final List<Class<? extends Checksum>> crcs,
+ final PrintStream out) throws Exception {
+ final byte[] bytes = new byte[MAX_LEN];
+ new Random().nextBytes(bytes);
+
+ // Print header
+ out.printf("\nPerformance Table (The unit is MB/sec; #T = #Theads)\n");
+
+ // Warm up implementations to get jit going.
+ for (final Class<? extends Checksum> c : crcs) {
+ doBench(c, 1, bytes, 2);
+ doBench(c, 1, bytes, 2101);
+ }
+
+ // Test on a variety of sizes with different number of threads
+ for (int size = 32; size <= MAX_LEN; size <<= 1) {
+ doBench(crcs, bytes, size, out);
+ }
+ }
+
+ private static void doBench(final List<Class<? extends Checksum>> crcs,
+ final byte[] bytes, final int size, final PrintStream out) throws
Exception {
+ final String numBytesStr = " #Bytes ";
+ final String numThreadsStr = "#T";
+ final String diffStr = "% diff";
+
+ out.print('|');
+ printCell(numBytesStr, 0, out);
+ printCell(numThreadsStr, 0, out);
+ for (int i = 0; i < crcs.size(); i++) {
+ final Class<? extends Checksum> c = crcs.get(i);
+ out.print('|');
+ printCell(c.getSimpleName(), 8, out);
+ for(int j = 0; j < i; j++) {
+ printCell(diffStr, diffStr.length(), out);
+ }
+ }
+ out.printf("\n");
+
+ for(int numThreads = 1; numThreads <= 16; numThreads <<= 1) {
+ out.printf("|");
+ printCell(String.valueOf(size), numBytesStr.length(), out);
+ printCell(String.valueOf(numThreads), numThreadsStr.length(), out);
+
+ BenchResult expected = null;
+ final List<BenchResult> previous = new ArrayList<>();
+ for(final Class<? extends Checksum> c : crcs) {
+ System.gc();
+
+ final BenchResult result = doBench(c, numThreads, bytes, size);
+ printCell(String.format("%9.1f", result.mbps),
+ c.getSimpleName().length()+1, out);
+
+ //check result
+ if(c == zip) {
+ expected = result;
+ } else if (expected == null) {
+ throw new RuntimeException("The first class is "
+ + c.getName() + " but not " + zip.getName());
+ } else if (result.value != expected.value) {
+ throw new RuntimeException(c + " has bugs!");
+ }
+
+ //compare result with previous
+ for(final BenchResult p : previous) {
+ final double diff = (result.mbps - p.mbps) / p.mbps * 100;
+ printCell(String.format("%5.1f%%", diff), diffStr.length(), out);
+ }
+ previous.add(result);
+ }
+ out.printf("\n");
+ }
+ }
+
+ private static BenchResult doBench(final Class<? extends Checksum> clazz,
+ final int numThreads, final byte[] bytes, final int size)
+ throws Exception {
+
+ final Thread[] threads = new Thread[numThreads];
+ final BenchResult[] results = new BenchResult[threads.length];
+
+ {
+ final int trials = BYTES_PER_SIZE / size;
+ final double mbProcessed = trials * size / 1024.0 / 1024.0;
+ final Constructor<? extends Checksum> ctor = clazz.getConstructor();
+
+ for(int i = 0; i < threads.length; i++) {
+ final int index = i;
+ threads[i] = new Thread() {
+ final Checksum crc = ctor.newInstance();
+
+ @Override
+ public void run() {
+ final long st = System.nanoTime();
+ crc.reset();
+ for (int trialIndex = 0; trialIndex < trials; trialIndex++) {
+ crc.update(bytes, 0, size);
+ }
+ final long et = System.nanoTime();
+ final double secsElapsed = (et - st) / 1000000000.0d;
+ results[index] = new BenchResult(crc.getValue(),
mbProcessed/secsElapsed);
+ }
+ };
+ }
+ }
+
+ for (final Thread thread : threads) {
+ thread.start();
+ }
+ for (final Thread thread : threads) {
+ thread.join();
+ }
+
+ final long expected = results[0].value;
+ double sum = results[0].mbps;
+ for(int i = 1; i < results.length; i++) {
+ if (results[i].value != expected) {
+ throw new AssertionError(clazz.getSimpleName() + " results not
matched.");
+ }
+ sum += results[i].mbps;
+ }
+ return new BenchResult(expected, sum/results.length);
+ }
+
+ private static class BenchResult {
+ /** CRC value */
+ final long value;
+ /** Speed (MB per second) */
+ final double mbps;
+
+ BenchResult(final long value, final double mbps) {
+ this.value = value;
+ this.mbps = mbps;
+ }
+ }
+
+ private static void printSystemProperties(final PrintStream out) {
+ final String[] names = {
+ "java.version",
+ "java.runtime.name",
+ "java.runtime.version",
+ "java.vm.version",
+ "java.vm.vendor",
+ "java.vm.name",
+ "java.vm.specification.version",
+ "java.specification.version",
+ "os.arch",
+ "os.name",
+ "os.version"
+ };
+ final Properties p = System.getProperties();
+ for(final String n : names) {
+ out.println(n + " = " + p.getProperty(n));
+ }
+ }
+ }
+}