ARTEMIS-841 Hash Processors lock free lazy singleton instantiation

This commit is contained in:
Francesco Nigro 2016-11-07 13:33:52 +01:00 committed by Clebert Suconic
parent 6c664c1cbc
commit 3281698f9f
1 changed files with 51 additions and 43 deletions

View File

@ -25,65 +25,74 @@ import org.apache.activemq.artemis.api.core.ActiveMQException;
import org.apache.activemq.artemis.api.core.ActiveMQExceptionType; import org.apache.activemq.artemis.api.core.ActiveMQExceptionType;
import org.apache.activemq.artemis.logs.ActiveMQUtilBundle; import org.apache.activemq.artemis.logs.ActiveMQUtilBundle;
public class PasswordMaskingUtil { public final class PasswordMaskingUtil {
private static final String PLAINTEXT_PROCESSOR = "plaintext"; private PasswordMaskingUtil() {
private static final String SECURE_PROCESSOR = "secure";
private static final Map<String, HashProcessor> 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 //stored password takes 2 forms, ENC() or plain text
public static HashProcessor getHashProcessor(String storedPassword) throws Exception { public static HashProcessor getHashProcessor(String storedPassword) throws Exception {
if (!isEncoded(storedPassword)) { 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) { private static boolean isEncoded(String storedPassword) {
if (storedPassword == null) { return storedPassword == null || (storedPassword.startsWith("ENC(") && storedPassword.endsWith(")"));
return true;
}
if (storedPassword.startsWith("ENC(") && storedPassword.endsWith(")")) {
return true;
}
return false;
} }
public static HashProcessor getHashProcessor() { public static HashProcessor getHashProcessor() {
HashProcessor processor = null; HashProcessor processor = LazySecureProcessorHolder.INSTANCE;
try { //it can be null due to a previous failed attempts to instantiate it!
processor = getSecureProcessor();
} catch (Exception e) {
processor = getPlaintextProcessor();
}
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) { if (processor == null) {
DefaultSensitiveStringCodec codec = (DefaultSensitiveStringCodec) getCodec("org.apache.activemq.artemis.utils.DefaultSensitiveStringCodec;algorithm=one-way"); processor = LazyPlainTextProcessorHolder.INSTANCE;
processor = new SecureHashProcessor(codec);
processors.put(SECURE_PROCESSOR, processor);
} }
return processor; return processor;
} }
}
/* /*
* Loading the codec class. * Loading the codec class.
@ -142,5 +151,4 @@ public class PasswordMaskingUtil {
return new DefaultSensitiveStringCodec(); return new DefaultSensitiveStringCodec();
} }
} }