You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ofbiz.apache.org by do...@apache.org on 2012/05/05 01:36:25 UTC

svn commit: r1334251 - /ofbiz/trunk/framework/entity/src/org/ofbiz/entity/util/EntityCrypto.java

Author: doogie
Date: Fri May  4 23:36:25 2012
New Revision: 1334251

URL: http://svn.apache.org/viewvc?rev=1334251&view=rev
Log:
FEATURE: Use a ConcurrentHashMap to store the keys loaded from the
database; as such, there is no longer any synchronization on the keyMap.

Modified:
    ofbiz/trunk/framework/entity/src/org/ofbiz/entity/util/EntityCrypto.java

Modified: ofbiz/trunk/framework/entity/src/org/ofbiz/entity/util/EntityCrypto.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/entity/src/org/ofbiz/entity/util/EntityCrypto.java?rev=1334251&r1=1334250&r2=1334251&view=diff
==============================================================================
--- ofbiz/trunk/framework/entity/src/org/ofbiz/entity/util/EntityCrypto.java (original)
+++ ofbiz/trunk/framework/entity/src/org/ofbiz/entity/util/EntityCrypto.java Fri May  4 23:36:25 2012
@@ -24,6 +24,8 @@ import java.util.HashMap;
 import java.util.Map;
 import java.util.Random;
 import java.util.concurrent.Callable;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
 
 import javax.crypto.SecretKey;
 import javax.transaction.Transaction;
@@ -46,7 +48,7 @@ public final class EntityCrypto {
     public static final String module = EntityCrypto.class.getName();
 
     protected final Delegator delegator;
-    protected final Map<String, SecretKey> keyMap = new HashMap<String, SecretKey>();
+    protected final ConcurrentMap<String, SecretKey> keyMap = new ConcurrentHashMap<String, SecretKey>();
 
     public EntityCrypto(Delegator delegator) {
         this.delegator = delegator;
@@ -73,7 +75,27 @@ public final class EntityCrypto {
         try {
             SecretKey key = this.findKey(keyName, false);
             if (key == null) {
-                key = this.createKey(keyName);
+                EntityCryptoException caught = null;
+                try {
+                    this.createKey(keyName);
+                } catch (EntityCryptoException e) {
+                    // either a database read error, or a duplicate key insert
+                    // if the latter, try to fetch the value created by the
+                    // other thread.
+                    caught = e;
+                } finally {
+                    try {
+                        key = this.findKey(keyName, false);
+                    } catch (EntityCryptoException e) {
+                        // this is bad, couldn't lookup the value, some bad juju
+                        // is occuring; rethrow the original exception if available
+                        throw caught != null ? caught : e;
+                    }
+                    if (key == null) {
+                        // this is also bad, couldn't find any key
+                        throw caught != null ? caught : new EntityCryptoException("could not lookup key (" + keyName + ") after creation");
+                    }
+                }
             }
             byte[] encryptedBytes = DesCrypt.encrypt(key, UtilObject.getBytes(obj));
             String hexString = StringUtil.toHexString(encryptedBytes);
@@ -122,10 +144,8 @@ public final class EntityCrypto {
 
     protected SecretKey findKey(String originalKeyName, boolean useOldFunnyKeyHash) throws EntityCryptoException {
         String keyMapName = originalKeyName + useOldFunnyKeyHash;
-        synchronized (keyMap) {
-            if (keyMap.containsKey(keyMapName)) {
-                return keyMap.get(keyMapName);
-            }
+        if (keyMap.containsKey(keyMapName)) {
+            return keyMap.get(keyMapName);
         }
         // it's ok to run the bulk of this method unlocked or
         // unprotected; since the same result will occur even if
@@ -145,16 +165,19 @@ public final class EntityCrypto {
         try {
             byte[] keyBytes = StringUtil.fromHexString(keyValue.getString("keyText"));
             SecretKey key = DesCrypt.getDesKey(keyBytes);
-            synchronized (keyMap) {
-                keyMap.put(keyMapName, key);
-            }
-            return key;
+            keyMap.putIfAbsent(keyMapName, key);
+            // Do not remove the next line, it's there to handle the
+            // case of multiple threads trying to find the same key
+            // both threads will do the findOne call, only one will
+            // succeed at the putIfAbsent, but both will then fetch
+            // the same value with the following get().
+            return keyMap.get(keyMapName);
         } catch (GeneralException e) {
             throw new EntityCryptoException(e);
         }
     }
 
-    protected SecretKey createKey(String originalKeyName) throws EntityCryptoException {
+    protected void createKey(String originalKeyName) throws EntityCryptoException {
         String hashedKeyName = HashCrypt.getDigestHash(originalKeyName);
         SecretKey key = null;
         try {
@@ -176,11 +199,6 @@ public final class EntityCrypto {
         } catch (GenericEntityException e) {
             throw new EntityCryptoException(e);
         }
-        String keyMapName = originalKeyName + false;
-        synchronized (keyMap) {
-            keyMap.put(keyMapName, key);
-        }
-        return key;
     }
 
     protected String getRandomString() {