From 3281698f9f15660922a8f835e2e6593088f533bf Mon Sep 17 00:00:00 2001 From: Francesco Nigro Date: Mon, 7 Nov 2016 13:33:52 +0100 Subject: [PATCH] ARTEMIS-841 Hash Processors lock free lazy singleton instantiation --- .../artemis/utils/PasswordMaskingUtil.java | 94 ++++++++++--------- 1 file changed, 51 insertions(+), 43 deletions(-) diff --git a/artemis-commons/src/main/java/org/apache/activemq/artemis/utils/PasswordMaskingUtil.java b/artemis-commons/src/main/java/org/apache/activemq/artemis/utils/PasswordMaskingUtil.java index bee3861f21..6360fb23c9 100644 --- a/artemis-commons/src/main/java/org/apache/activemq/artemis/utils/PasswordMaskingUtil.java +++ b/artemis-commons/src/main/java/org/apache/activemq/artemis/utils/PasswordMaskingUtil.java @@ -25,66 +25,75 @@ import org.apache.activemq.artemis.api.core.ActiveMQException; import org.apache.activemq.artemis.api.core.ActiveMQExceptionType; import org.apache.activemq.artemis.logs.ActiveMQUtilBundle; -public class PasswordMaskingUtil { +public final class PasswordMaskingUtil { - private static final String PLAINTEXT_PROCESSOR = "plaintext"; - private static final String SECURE_PROCESSOR = "secure"; + private PasswordMaskingUtil() { - private static final Map processors = new HashMap<>(); + } + + private static final class LazyPlainTextProcessorHolder { + + private LazyPlainTextProcessorHolder() { + + } + + private static final HashProcessor INSTANCE = new NoHashProcessor(); + + } + + private static final class LazySecureProcessorHolder { + + private LazySecureProcessorHolder() { + + } + + private static final HashProcessor INSTANCE; + private static final Exception EXCEPTION; + + static { + HashProcessor processor = null; + Exception exception = null; + final String codecDesc = "org.apache.activemq.artemis.utils.DefaultSensitiveStringCodec;algorithm=one-way"; + try { + final DefaultSensitiveStringCodec codec = (DefaultSensitiveStringCodec) PasswordMaskingUtil.getCodec(codecDesc); + processor = new SecureHashProcessor(codec); + } catch (Exception e) { + //THE STACK TRACE IS THE ORIGINAL ONE! + exception = e; + } finally { + EXCEPTION = exception; + INSTANCE = processor; + } + } + } //stored password takes 2 forms, ENC() or plain text public static HashProcessor getHashProcessor(String storedPassword) throws Exception { if (!isEncoded(storedPassword)) { - return getPlaintextProcessor(); + return LazyPlainTextProcessorHolder.INSTANCE; } - return getSecureProcessor(); + final Exception secureProcessorException = LazySecureProcessorHolder.EXCEPTION; + if (secureProcessorException != null) { + //reuse old descriptions/messages of the exception but refill the stack trace + throw new RuntimeException(secureProcessorException); + } + return LazySecureProcessorHolder.INSTANCE; } private static boolean isEncoded(String storedPassword) { - if (storedPassword == null) { - return true; - } - - if (storedPassword.startsWith("ENC(") && storedPassword.endsWith(")")) { - return true; - } - return false; + return storedPassword == null || (storedPassword.startsWith("ENC(") && storedPassword.endsWith(")")); } public static HashProcessor getHashProcessor() { - HashProcessor processor = null; - try { - processor = getSecureProcessor(); - } catch (Exception e) { - processor = getPlaintextProcessor(); + HashProcessor processor = LazySecureProcessorHolder.INSTANCE; + //it can be null due to a previous failed attempts to instantiate it! + if (processor == null) { + processor = LazyPlainTextProcessorHolder.INSTANCE; } return processor; } - public static HashProcessor getPlaintextProcessor() { - synchronized (processors) { - HashProcessor plain = processors.get(PLAINTEXT_PROCESSOR); - if (plain == null) { - plain = new NoHashProcessor(); - processors.put(PLAINTEXT_PROCESSOR, plain); - } - return plain; - } - } - - public static HashProcessor getSecureProcessor() throws Exception { - synchronized (processors) { - HashProcessor processor = processors.get(SECURE_PROCESSOR); - if (processor == null) { - DefaultSensitiveStringCodec codec = (DefaultSensitiveStringCodec) getCodec("org.apache.activemq.artemis.utils.DefaultSensitiveStringCodec;algorithm=one-way"); - processor = new SecureHashProcessor(codec); - processors.put(SECURE_PROCESSOR, processor); - } - return processor; - } - } - /* * Loading the codec class. * @@ -142,5 +151,4 @@ public class PasswordMaskingUtil { return new DefaultSensitiveStringCodec(); } - }