The standard Java class MessageDigest
can be used to return instances for various message digest algorithms. Implementing a simple factory helps you to return these instances in a type safe way without magic strings and preventing catch blocks with NoSuchAlgorithmException
in your code.
Implementation
Our implementation will depend on an enum that contains all the different message digest algorithms and a factory that returns instances of MessageDigest
.
Here’s the enum: it holds the different algorithms and the corresponding string identifier that’s passed to MessageDigest.getInstance()
.
public enum MessageDigestAlgorithm { MD2("MD2"), MD5("MD5"), SHA1("SHA-1"), SHA256("SHA-256"), SHA384("SHA-384"), SHA512("SHA-512"); /** Algorithm name as defined in {@link MessageDigest#getInstance(String)} */ private final String algorithm; private MessageDigestAlgorithm(final String algorithm) { this.algorithm = algorithm; } public String getAlgorithm() { return this.algorithm; } } |
The factory class is straight forward as well and just contains a method that returns instances of MessageDigest
. The algorithms names hard coded in the above enum are passed to the getInstance
method and the exception should never occur.
public class MessageDigestFactory { public static MessageDigest getMessageDigest( final MessageDigestAlgorithm algorithm) { // Validation if (algorithm == null) throw new IllegalArgumentException("Algorithm is 'null'."); try { return MessageDigest.getInstance(algorithm.getAlgorithm()); } catch (final NoSuchAlgorithmException ignored) { // Should never happen return null; } } private MessageDigestFactory() { // can't be instantiated } } |
Testing
Finally here is a unit test that evaluates the different algorithms and makes sure that passing null
to our above method results in an exception.
public class MessageDigestFactoryTest { @Test public void getMessageDigest() { Assert.assertEquals("MD2", MessageDigestFactory.getMessageDigest( MessageDigestAlgorithm.MD2).getAlgorithm()); /* Test MD5, SHA-* as well... */ try { MessageDigestFactory.getMessageDigest(null); Assert.fail("Should throw exception"); } catch (final IllegalArgumentException ignored) { } } } |
Conclusion
Using an enum is an easy way to hard code expected magic strings and in combination with the factory returning instances of, e.g., MessageDigest
in a type safe way without the need to check for a certain exception makes your code much cleaner.