You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cayenne.apache.org by aa...@apache.org on 2014/03/28 15:56:13 UTC

svn commit: r1582769 - in /cayenne/main/trunk/cayenne-crypto/src: main/java/org/apache/cayenne/crypto/ main/java/org/apache/cayenne/crypto/batch/ main/java/org/apache/cayenne/crypto/cipher/ main/java/org/apache/cayenne/crypto/reader/ test/java/org/apac...

Author: aadamchik
Date: Fri Mar 28 14:56:12 2014
New Revision: 1582769

URL: http://svn.apache.org/r1582769
Log:
CAY-1916 cayenne-crypto module that enables data encryption for certain model attributes

batching encryptors and decryptors to handle whole rows. this allows to use ciphers more efficiently

Added:
    cayenne/main/trunk/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/cipher/BindingsTransformer.java
      - copied, changed from r1582631, cayenne/main/trunk/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/cipher/Decryptor.java
    cayenne/main/trunk/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/cipher/DefaultBindingsTransformer.java
      - copied, changed from r1582631, cayenne/main/trunk/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/cipher/CryptoFactory.java
    cayenne/main/trunk/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/cipher/DefaultCryptoFactory.java
    cayenne/main/trunk/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/cipher/DefaultMapTransformer.java
      - copied, changed from r1582631, cayenne/main/trunk/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/cipher/CryptoFactory.java
    cayenne/main/trunk/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/cipher/MapTransformer.java
      - copied, changed from r1582631, cayenne/main/trunk/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/cipher/Encryptor.java
    cayenne/main/trunk/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/cipher/ValueTransformer.java
      - copied, changed from r1582631, cayenne/main/trunk/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/cipher/Decryptor.java
    cayenne/main/trunk/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/cipher/ValueTransformerFactory.java
      - copied, changed from r1582631, cayenne/main/trunk/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/cipher/Decryptor.java
    cayenne/main/trunk/cayenne-crypto/src/test/java/org/apache/cayenne/crypto/unit/Rot13TransformerFactory.java
      - copied, changed from r1582631, cayenne/main/trunk/cayenne-crypto/src/test/java/org/apache/cayenne/crypto/unit/Rot13CryptoFactory.java
    cayenne/main/trunk/cayenne-crypto/src/test/java/org/apache/cayenne/crypto/unit/Rot13TransformerFactoryTest.java
      - copied, changed from r1582631, cayenne/main/trunk/cayenne-crypto/src/test/java/org/apache/cayenne/crypto/unit/Rot13CryptoFactoryTest.java
Removed:
    cayenne/main/trunk/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/cipher/Decryptor.java
    cayenne/main/trunk/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/cipher/Encryptor.java
    cayenne/main/trunk/cayenne-crypto/src/test/java/org/apache/cayenne/crypto/unit/Rot13CryptoFactory.java
    cayenne/main/trunk/cayenne-crypto/src/test/java/org/apache/cayenne/crypto/unit/Rot13CryptoFactoryTest.java
Modified:
    cayenne/main/trunk/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/CryptoModuleBuilder.java
    cayenne/main/trunk/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/batch/CryptoBatchTranslatorFactoryDecorator.java
    cayenne/main/trunk/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/cipher/CryptoFactory.java
    cayenne/main/trunk/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/reader/CryptoRowReaderFactoryDecorator.java
    cayenne/main/trunk/cayenne-crypto/src/test/java/org/apache/cayenne/crypto/Crypto_InRuntime_Test.java

Modified: cayenne/main/trunk/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/CryptoModuleBuilder.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/CryptoModuleBuilder.java?rev=1582769&r1=1582768&r2=1582769&view=diff
==============================================================================
--- cayenne/main/trunk/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/CryptoModuleBuilder.java (original)
+++ cayenne/main/trunk/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/CryptoModuleBuilder.java Fri Mar 28 14:56:12 2014
@@ -22,6 +22,8 @@ import org.apache.cayenne.access.jdbc.re
 import org.apache.cayenne.access.translator.batch.BatchTranslatorFactory;
 import org.apache.cayenne.crypto.batch.CryptoBatchTranslatorFactoryDecorator;
 import org.apache.cayenne.crypto.cipher.CryptoFactory;
+import org.apache.cayenne.crypto.cipher.DefaultCryptoFactory;
+import org.apache.cayenne.crypto.cipher.ValueTransformerFactory;
 import org.apache.cayenne.crypto.map.ColumnMapper;
 import org.apache.cayenne.crypto.reader.CryptoRowReaderFactoryDecorator;
 import org.apache.cayenne.di.Binder;
@@ -37,13 +39,13 @@ import org.apache.cayenne.di.Module;
  */
 public class CryptoModuleBuilder {
 
-    private Class<? extends CryptoFactory> cryptoFactoryType;
+    private Class<? extends ValueTransformerFactory> valueTransformerFactoryType;
 
     private ColumnMapper columnMapper;
     private Class<? extends ColumnMapper> columnMapperType;
 
-    public CryptoModuleBuilder cryptoFactory(Class<? extends CryptoFactory> cryptoFactoryType) {
-        this.cryptoFactoryType = cryptoFactoryType;
+    public CryptoModuleBuilder valueTransformer(Class<? extends ValueTransformerFactory> valueTransformerFactoryType) {
+        this.valueTransformerFactoryType = valueTransformerFactoryType;
         return this;
     }
 
@@ -64,8 +66,8 @@ public class CryptoModuleBuilder {
      */
     public Module build() {
 
-        if (cryptoFactoryType == null) {
-            throw new IllegalStateException("'CryptoHandler' is not initialized");
+        if (valueTransformerFactoryType == null) {
+            throw new IllegalStateException("'ValueTransformerFactory' is not initialized");
         }
 
         if (columnMapperType == null && columnMapper == null) {
@@ -76,7 +78,9 @@ public class CryptoModuleBuilder {
 
             @Override
             public void configure(Binder binder) {
-                binder.bind(CryptoFactory.class).to(cryptoFactoryType);
+
+                binder.bind(CryptoFactory.class).to(DefaultCryptoFactory.class);
+                binder.bind(ValueTransformerFactory.class).to(valueTransformerFactoryType);
 
                 if (columnMapperType != null) {
                     binder.bind(ColumnMapper.class).to(columnMapperType);

Modified: cayenne/main/trunk/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/batch/CryptoBatchTranslatorFactoryDecorator.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/batch/CryptoBatchTranslatorFactoryDecorator.java?rev=1582769&r1=1582768&r2=1582769&view=diff
==============================================================================
--- cayenne/main/trunk/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/batch/CryptoBatchTranslatorFactoryDecorator.java (original)
+++ cayenne/main/trunk/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/batch/CryptoBatchTranslatorFactoryDecorator.java Fri Mar 28 14:56:12 2014
@@ -18,18 +18,13 @@
  ****************************************************************/
 package org.apache.cayenne.crypto.batch;
 
-import java.util.ArrayList;
-import java.util.List;
-
 import org.apache.cayenne.access.translator.batch.BatchParameterBinding;
 import org.apache.cayenne.access.translator.batch.BatchTranslator;
 import org.apache.cayenne.access.translator.batch.BatchTranslatorFactory;
+import org.apache.cayenne.crypto.cipher.BindingsTransformer;
 import org.apache.cayenne.crypto.cipher.CryptoFactory;
-import org.apache.cayenne.crypto.cipher.Encryptor;
-import org.apache.cayenne.crypto.map.ColumnMapper;
 import org.apache.cayenne.dba.DbAdapter;
 import org.apache.cayenne.di.Inject;
-import org.apache.cayenne.map.DbAttribute;
 import org.apache.cayenne.query.BatchQuery;
 import org.apache.cayenne.query.BatchQueryRow;
 
@@ -38,17 +33,13 @@ import org.apache.cayenne.query.BatchQue
  */
 public class CryptoBatchTranslatorFactoryDecorator implements BatchTranslatorFactory {
 
-    private static final PositionalEncryptor[] EMPTY_ENCRYPTORS = new PositionalEncryptor[0];
-
-    private ColumnMapper columnMapper;
     private CryptoFactory cryptoFactory;
     private BatchTranslatorFactory delegate;
 
     public CryptoBatchTranslatorFactoryDecorator(@Inject BatchTranslatorFactory delegate,
-            @Inject CryptoFactory cryptoFactory, @Inject ColumnMapper columnMapper) {
+            @Inject CryptoFactory cryptoFactory) {
 
         this.cryptoFactory = cryptoFactory;
-        this.columnMapper = columnMapper;
         this.delegate = delegate;
     }
 
@@ -58,34 +49,15 @@ public class CryptoBatchTranslatorFactor
 
         return new BatchTranslator() {
 
-            private int len;
-            private PositionalEncryptor[] encryptors;
-
-            private void ensureEncryptorsCompiled() {
-                if (this.encryptors == null) {
-                    BatchParameterBinding[] bindings = getBindings();
-
-                    int len = bindings.length;
-                    List<PositionalEncryptor> encList = null;
-
-                    for (int i = 0; i < len; i++) {
+            private boolean encryptorCompiled;
+            private BindingsTransformer encryptor;
 
-                        DbAttribute a = bindings[i].getAttribute();
-                        if (columnMapper.isEncrypted(a)) {
-
-                            if (encList == null) {
-                                encList = new ArrayList<PositionalEncryptor>(len - i);
-                            }
-
-                            Encryptor e = cryptoFactory.getEncryptor(a);
-                            encList.add(new PositionalEncryptor(i, e));
-                        }
-                    }
-
-                    this.encryptors = encList == null ? EMPTY_ENCRYPTORS : encList
-                            .toArray(new PositionalEncryptor[encList.size()]);
-                    this.len = encryptors.length;
+            private void ensureEncryptorCompiled() {
+                if (!encryptorCompiled) {
+                    encryptor = cryptoFactory.createEncryptor(getBindings());
+                    encryptorCompiled = true;
                 }
+
             }
 
             @Override
@@ -101,14 +73,12 @@ public class CryptoBatchTranslatorFactor
             @Override
             public BatchParameterBinding[] updateBindings(BatchQueryRow row) {
 
-                ensureEncryptorsCompiled();
+                ensureEncryptorCompiled();
 
                 BatchParameterBinding[] bindings = delegateTranslator.updateBindings(row);
 
-                for (int i = 0; i < len; i++) {
-                    BatchParameterBinding b = bindings[encryptors[i].position];
-                    Object encrypted = encryptors[i].encryptor.encrypt(b.getValue());
-                    b.setValue(encrypted);
+                if (encryptor != null) {
+                    encryptor.transform(bindings);
                 }
 
                 return bindings;
@@ -116,13 +86,4 @@ public class CryptoBatchTranslatorFactor
         };
     }
 
-    class PositionalEncryptor {
-        final int position;
-        final Encryptor encryptor;
-
-        PositionalEncryptor(int position, Encryptor encryptor) {
-            this.position = position;
-            this.encryptor = encryptor;
-        }
-    }
 }

Copied: cayenne/main/trunk/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/cipher/BindingsTransformer.java (from r1582631, cayenne/main/trunk/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/cipher/Decryptor.java)
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/cipher/BindingsTransformer.java?p2=cayenne/main/trunk/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/cipher/BindingsTransformer.java&p1=cayenne/main/trunk/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/cipher/Decryptor.java&r1=1582631&r2=1582769&rev=1582769&view=diff
==============================================================================
--- cayenne/main/trunk/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/cipher/Decryptor.java (original)
+++ cayenne/main/trunk/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/cipher/BindingsTransformer.java Fri Mar 28 14:56:12 2014
@@ -18,12 +18,12 @@
  ****************************************************************/
 package org.apache.cayenne.crypto.cipher;
 
+import org.apache.cayenne.access.translator.batch.BatchParameterBinding;
+
 /**
- * An decryptor object configured to decrypt a value of a certain type.
- * 
  * @since 3.2
  */
-public interface Decryptor {
+public interface BindingsTransformer {
 
-    Object decrypt(Object ciphertext);
+    void transform(BatchParameterBinding[] bindings);
 }

Modified: cayenne/main/trunk/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/cipher/CryptoFactory.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/cipher/CryptoFactory.java?rev=1582769&r1=1582768&r2=1582769&view=diff
==============================================================================
--- cayenne/main/trunk/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/cipher/CryptoFactory.java (original)
+++ cayenne/main/trunk/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/cipher/CryptoFactory.java Fri Mar 28 14:56:12 2014
@@ -18,7 +18,8 @@
  ****************************************************************/
 package org.apache.cayenne.crypto.cipher;
 
-import org.apache.cayenne.map.DbAttribute;
+import org.apache.cayenne.access.jdbc.ColumnDescriptor;
+import org.apache.cayenne.access.translator.batch.BatchParameterBinding;
 
 /**
  * A factory that creates encryption/decryption handlers that can be used to
@@ -28,7 +29,7 @@ import org.apache.cayenne.map.DbAttribut
  */
 public interface CryptoFactory {
 
-    Encryptor getEncryptor(DbAttribute column);
+    BindingsTransformer createEncryptor(BatchParameterBinding[] bindings);
 
-    Decryptor getDecryptor(DbAttribute column);
+    MapTransformer createDecryptor(ColumnDescriptor[] columns, Object sampleRow);
 }

Copied: cayenne/main/trunk/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/cipher/DefaultBindingsTransformer.java (from r1582631, cayenne/main/trunk/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/cipher/CryptoFactory.java)
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/cipher/DefaultBindingsTransformer.java?p2=cayenne/main/trunk/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/cipher/DefaultBindingsTransformer.java&p1=cayenne/main/trunk/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/cipher/CryptoFactory.java&r1=1582631&r2=1582769&rev=1582769&view=diff
==============================================================================
--- cayenne/main/trunk/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/cipher/CryptoFactory.java (original)
+++ cayenne/main/trunk/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/cipher/DefaultBindingsTransformer.java Fri Mar 28 14:56:12 2014
@@ -18,17 +18,35 @@
  ****************************************************************/
 package org.apache.cayenne.crypto.cipher;
 
-import org.apache.cayenne.map.DbAttribute;
+import javax.crypto.Cipher;
+
+import org.apache.cayenne.access.translator.batch.BatchParameterBinding;
 
 /**
- * A factory that creates encryption/decryption handlers that can be used to
- * process data.
- * 
  * @since 3.2
  */
-public interface CryptoFactory {
+public class DefaultBindingsTransformer implements BindingsTransformer {
+
+    private int[] positions;
+    private ValueTransformer[] transformers;
+    private Cipher cipher;
+
+    public DefaultBindingsTransformer(int[] positions, ValueTransformer[] transformers, Cipher cipher) {
+        this.positions = positions;
+        this.transformers = transformers;
+        this.cipher = cipher;
+    }
+
+    @Override
+    public void transform(BatchParameterBinding[] bindings) {
+
+        int len = positions.length;
 
-    Encryptor getEncryptor(DbAttribute column);
+        for (int i = 0; i < len; i++) {
+            BatchParameterBinding b = bindings[positions[i]];
+            Object transformed = transformers[i].transform(cipher, b.getValue());
+            b.setValue(transformed);
+        }
+    }
 
-    Decryptor getDecryptor(DbAttribute column);
 }

Added: cayenne/main/trunk/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/cipher/DefaultCryptoFactory.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/cipher/DefaultCryptoFactory.java?rev=1582769&view=auto
==============================================================================
--- cayenne/main/trunk/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/cipher/DefaultCryptoFactory.java (added)
+++ cayenne/main/trunk/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/cipher/DefaultCryptoFactory.java Fri Mar 28 14:56:12 2014
@@ -0,0 +1,121 @@
+/*****************************************************************
+ *   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.cayenne.crypto.cipher;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.cayenne.access.jdbc.ColumnDescriptor;
+import org.apache.cayenne.access.translator.batch.BatchParameterBinding;
+import org.apache.cayenne.crypto.map.ColumnMapper;
+import org.apache.cayenne.di.Inject;
+import org.apache.cayenne.map.DbAttribute;
+
+public class DefaultCryptoFactory implements CryptoFactory {
+
+    private ColumnMapper columnMapper;
+    private ValueTransformerFactory transformerFactory;
+
+    public DefaultCryptoFactory(@Inject ColumnMapper columnMapper, @Inject ValueTransformerFactory transformerFactory) {
+        this.columnMapper = columnMapper;
+        this.transformerFactory = transformerFactory;
+    }
+
+    @Override
+    public MapTransformer createDecryptor(ColumnDescriptor[] columns, Object sampleRow) {
+
+        if (!(sampleRow instanceof Map)) {
+            return null;
+        }
+
+        int len = columns.length;
+        List<Integer> cryptoColumns = null;
+
+        for (int i = 0; i < len; i++) {
+
+            DbAttribute a = columns[i].getAttribute();
+            if (a != null && columnMapper.isEncrypted(a)) {
+                if (cryptoColumns == null) {
+                    cryptoColumns = new ArrayList<Integer>(len - i);
+                }
+
+                cryptoColumns.add(i);
+            }
+        }
+
+        if (cryptoColumns != null) {
+
+            int dlen = cryptoColumns.size();
+            String[] keys = new String[dlen];
+            ValueTransformer[] transformers = new ValueTransformer[dlen];
+
+            for (int i = 0; i < dlen; i++) {
+
+                ColumnDescriptor cd = columns[cryptoColumns.get(i)];
+                keys[i] = cd.getDataRowKey();
+                transformers[i] = transformerFactory.getDecryptor(cd.getAttribute().getType());
+            }
+
+            // TODO: use real cipher
+            return new DefaultMapTransformer(keys, transformers, null);
+        }
+
+        return null;
+    }
+
+    @Override
+    public BindingsTransformer createEncryptor(BatchParameterBinding[] bindings) {
+        int len = bindings.length;
+        List<Integer> cryptoColumns = null;
+
+        for (int i = 0; i < len; i++) {
+
+            DbAttribute a = bindings[i].getAttribute();
+            if (columnMapper.isEncrypted(a)) {
+
+                if (cryptoColumns == null) {
+                    cryptoColumns = new ArrayList<Integer>(len - i);
+                }
+
+                cryptoColumns.add(i);
+            }
+        }
+
+        if (cryptoColumns != null) {
+
+            int dlen = cryptoColumns.size();
+            int[] positions = new int[dlen];
+            ValueTransformer[] transformers = new ValueTransformer[dlen];
+
+            for (int i = 0; i < dlen; i++) {
+                int pos = cryptoColumns.get(i);
+                BatchParameterBinding b = bindings[pos];
+                positions[i] = pos;
+                transformers[i] = transformerFactory.getEncryptor(b.getAttribute().getType());
+            }
+
+            // TODO: use real cipher
+            return new DefaultBindingsTransformer(positions, transformers, null);
+        }
+
+        return null;
+    }
+
+}

Copied: cayenne/main/trunk/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/cipher/DefaultMapTransformer.java (from r1582631, cayenne/main/trunk/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/cipher/CryptoFactory.java)
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/cipher/DefaultMapTransformer.java?p2=cayenne/main/trunk/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/cipher/DefaultMapTransformer.java&p1=cayenne/main/trunk/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/cipher/CryptoFactory.java&r1=1582631&r2=1582769&rev=1582769&view=diff
==============================================================================
--- cayenne/main/trunk/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/cipher/CryptoFactory.java (original)
+++ cayenne/main/trunk/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/cipher/DefaultMapTransformer.java Fri Mar 28 14:56:12 2014
@@ -18,17 +18,34 @@
  ****************************************************************/
 package org.apache.cayenne.crypto.cipher;
 
-import org.apache.cayenne.map.DbAttribute;
+import java.util.Map;
 
-/**
- * A factory that creates encryption/decryption handlers that can be used to
- * process data.
- * 
- * @since 3.2
- */
-public interface CryptoFactory {
+import javax.crypto.Cipher;
 
-    Encryptor getEncryptor(DbAttribute column);
+public class DefaultMapTransformer implements MapTransformer {
 
-    Decryptor getDecryptor(DbAttribute column);
+    private String[] keys;
+    private ValueTransformer[] transformers;
+    private Cipher cipher;
+
+    public DefaultMapTransformer(String[] keys, ValueTransformer[] transformers, Cipher cipher) {
+        this.keys = keys;
+        this.transformers = transformers;
+        this.cipher = cipher;
+    }
+
+    @Override
+    public void transform(Map<String, Object> map) {
+
+        int len = keys.length;
+
+        for (int i = 0; i < len; i++) {
+            Object value = map.get(keys[i]);
+
+            if (value != null) {
+                Object transformed = transformers[i].transform(cipher, value);
+                map.put(keys[i], transformed);
+            }
+        }
+    }
 }

Copied: cayenne/main/trunk/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/cipher/MapTransformer.java (from r1582631, cayenne/main/trunk/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/cipher/Encryptor.java)
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/cipher/MapTransformer.java?p2=cayenne/main/trunk/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/cipher/MapTransformer.java&p1=cayenne/main/trunk/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/cipher/Encryptor.java&r1=1582631&r2=1582769&rev=1582769&view=diff
==============================================================================
--- cayenne/main/trunk/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/cipher/Encryptor.java (original)
+++ cayenne/main/trunk/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/cipher/MapTransformer.java Fri Mar 28 14:56:12 2014
@@ -18,12 +18,12 @@
  ****************************************************************/
 package org.apache.cayenne.crypto.cipher;
 
+import java.util.Map;
+
 /**
- * An encryptor object configured to encrypt a value of a certain type.
- * 
  * @since 3.2
  */
-public interface Encryptor {
+public interface MapTransformer {
 
-    Object encrypt(Object plaintext);
+    void transform(Map<String, Object> map);
 }

Copied: cayenne/main/trunk/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/cipher/ValueTransformer.java (from r1582631, cayenne/main/trunk/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/cipher/Decryptor.java)
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/cipher/ValueTransformer.java?p2=cayenne/main/trunk/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/cipher/ValueTransformer.java&p1=cayenne/main/trunk/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/cipher/Decryptor.java&r1=1582631&r2=1582769&rev=1582769&view=diff
==============================================================================
--- cayenne/main/trunk/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/cipher/Decryptor.java (original)
+++ cayenne/main/trunk/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/cipher/ValueTransformer.java Fri Mar 28 14:56:12 2014
@@ -18,12 +18,14 @@
  ****************************************************************/
 package org.apache.cayenne.crypto.cipher;
 
+import javax.crypto.Cipher;
+
 /**
- * An decryptor object configured to decrypt a value of a certain type.
+ * An encryptor or decryptor of a single value.
  * 
  * @since 3.2
  */
-public interface Decryptor {
+public interface ValueTransformer {
 
-    Object decrypt(Object ciphertext);
+    Object transform(Cipher cipher, Object value);
 }

Copied: cayenne/main/trunk/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/cipher/ValueTransformerFactory.java (from r1582631, cayenne/main/trunk/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/cipher/Decryptor.java)
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/cipher/ValueTransformerFactory.java?p2=cayenne/main/trunk/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/cipher/ValueTransformerFactory.java&p1=cayenne/main/trunk/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/cipher/Decryptor.java&r1=1582631&r2=1582769&rev=1582769&view=diff
==============================================================================
--- cayenne/main/trunk/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/cipher/Decryptor.java (original)
+++ cayenne/main/trunk/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/cipher/ValueTransformerFactory.java Fri Mar 28 14:56:12 2014
@@ -19,11 +19,11 @@
 package org.apache.cayenne.crypto.cipher;
 
 /**
- * An decryptor object configured to decrypt a value of a certain type.
- * 
  * @since 3.2
  */
-public interface Decryptor {
+public interface ValueTransformerFactory {
 
-    Object decrypt(Object ciphertext);
+    ValueTransformer getEncryptor(int jdbcType);
+
+    ValueTransformer getDecryptor(int jdbcType);
 }

Modified: cayenne/main/trunk/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/reader/CryptoRowReaderFactoryDecorator.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/reader/CryptoRowReaderFactoryDecorator.java?rev=1582769&r1=1582768&r2=1582769&view=diff
==============================================================================
--- cayenne/main/trunk/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/reader/CryptoRowReaderFactoryDecorator.java (original)
+++ cayenne/main/trunk/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/reader/CryptoRowReaderFactoryDecorator.java Fri Mar 28 14:56:12 2014
@@ -19,8 +19,6 @@
 package org.apache.cayenne.crypto.reader;
 
 import java.sql.ResultSet;
-import java.util.ArrayList;
-import java.util.List;
 import java.util.Map;
 
 import org.apache.cayenne.access.jdbc.ColumnDescriptor;
@@ -28,27 +26,20 @@ import org.apache.cayenne.access.jdbc.Ro
 import org.apache.cayenne.access.jdbc.reader.RowReader;
 import org.apache.cayenne.access.jdbc.reader.RowReaderFactory;
 import org.apache.cayenne.crypto.cipher.CryptoFactory;
-import org.apache.cayenne.crypto.cipher.Decryptor;
-import org.apache.cayenne.crypto.map.ColumnMapper;
+import org.apache.cayenne.crypto.cipher.MapTransformer;
 import org.apache.cayenne.dba.DbAdapter;
 import org.apache.cayenne.di.Inject;
-import org.apache.cayenne.map.DbAttribute;
 import org.apache.cayenne.map.ObjAttribute;
 import org.apache.cayenne.query.QueryMetadata;
 
 public class CryptoRowReaderFactoryDecorator implements RowReaderFactory {
 
-    private static final MapEntryDecryptor[] EMPTY_DECRYPTORS = new MapEntryDecryptor[0];
-
     private RowReaderFactory delegate;
     private CryptoFactory cryptoFactory;
-    private ColumnMapper columnMapper;
 
-    public CryptoRowReaderFactoryDecorator(@Inject RowReaderFactory delegate, @Inject CryptoFactory cryptoFactory,
-            @Inject ColumnMapper columnMapper) {
+    public CryptoRowReaderFactoryDecorator(@Inject RowReaderFactory delegate, @Inject CryptoFactory cryptoFactory) {
         this.delegate = delegate;
         this.cryptoFactory = cryptoFactory;
-        this.columnMapper = columnMapper;
     }
 
     @Override
@@ -59,37 +50,13 @@ public class CryptoRowReaderFactoryDecor
 
         return new RowReader<Object>() {
 
-            private int len;
-            private MapEntryDecryptor[] decryptors;
+            private boolean decryptorCompiled;
+            private MapTransformer decryptor;
 
             private void ensureDecryptorCompiled(Object row) {
-                if (decryptors == null) {
-
-                    List<MapEntryDecryptor> decList = null;
-
-                    if (row instanceof Map) {
-
-                        ColumnDescriptor[] columns = descriptor.getColumns();
-                        int len = columns.length;
-
-                        for (int i = 0; i < len; i++) {
-
-                            DbAttribute a = columns[i].getAttribute();
-                            if (a != null && columnMapper.isEncrypted(a)) {
-                                if (decList == null) {
-                                    decList = new ArrayList<MapEntryDecryptor>(len - i);
-                                }
-
-                                decList.add(new MapEntryDecryptor(columns[i].getDataRowKey(), cryptoFactory
-                                        .getDecryptor(a)));
-                            }
-                        }
-
-                    }
-
-                    this.decryptors = decList == null ? EMPTY_DECRYPTORS : decList
-                            .toArray(new MapEntryDecryptor[decList.size()]);
-                    this.len = decryptors.length;
+                if (!decryptorCompiled) {
+                    decryptor = cryptoFactory.createDecryptor(descriptor.getColumns(), row);
+                    decryptorCompiled = true;
                 }
             }
 
@@ -99,33 +66,16 @@ public class CryptoRowReaderFactoryDecor
 
                 ensureDecryptorCompiled(row);
 
-                if (len > 0) {
+                if (decryptor != null) {
+
                     @SuppressWarnings({ "unchecked", "rawtypes" })
                     Map<String, Object> map = (Map) row;
 
-                    for (int i = 0; i < len; i++) {
-
-                        MapEntryDecryptor decryptor = decryptors[i];
-                        Object encrypted = map.get(decryptor.key);
-
-                        if (encrypted != null) {
-                            map.put(decryptor.key, decryptor.decryptor.decrypt(encrypted));
-                        }
-                    }
+                    decryptor.transform(map);
                 }
 
                 return row;
             }
         };
     }
-
-    class MapEntryDecryptor {
-        final String key;
-        final Decryptor decryptor;
-
-        MapEntryDecryptor(String key, Decryptor decryptor) {
-            this.key = key;
-            this.decryptor = decryptor;
-        }
-    }
 }

Modified: cayenne/main/trunk/cayenne-crypto/src/test/java/org/apache/cayenne/crypto/Crypto_InRuntime_Test.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/cayenne-crypto/src/test/java/org/apache/cayenne/crypto/Crypto_InRuntime_Test.java?rev=1582769&r1=1582768&r2=1582769&view=diff
==============================================================================
--- cayenne/main/trunk/cayenne-crypto/src/test/java/org/apache/cayenne/crypto/Crypto_InRuntime_Test.java (original)
+++ cayenne/main/trunk/cayenne-crypto/src/test/java/org/apache/cayenne/crypto/Crypto_InRuntime_Test.java Fri Mar 28 14:56:12 2014
@@ -29,7 +29,7 @@ import org.apache.cayenne.ObjectContext;
 import org.apache.cayenne.configuration.server.ServerRuntime;
 import org.apache.cayenne.crypto.db.Table1;
 import org.apache.cayenne.crypto.map.PatternColumnMapper;
-import org.apache.cayenne.crypto.unit.Rot13CryptoFactory;
+import org.apache.cayenne.crypto.unit.Rot13TransformerFactory;
 import org.apache.cayenne.di.Module;
 import org.apache.cayenne.query.SelectQuery;
 import org.apache.cayenne.test.jdbc.DBHelper;
@@ -44,7 +44,7 @@ public class Crypto_InRuntime_Test exten
     @Override
     protected void setUp() throws Exception {
 
-        Module crypto = new CryptoModuleBuilder().cryptoFactory(Rot13CryptoFactory.class)
+        Module crypto = new CryptoModuleBuilder().valueTransformer(Rot13TransformerFactory.class)
                 .columnMapper(new PatternColumnMapper("^CRYPTO_")).build();
 
         this.runtime = new ServerRuntime("cayenne-crypto.xml", crypto);
@@ -67,7 +67,7 @@ public class Crypto_InRuntime_Test exten
 
         Object[] data = table1.select();
         assertEquals("plain_1", data[1]);
-        assertEquals(Rot13CryptoFactory.rotate("crypto_1"), data[2]);
+        assertEquals(Rot13TransformerFactory.rotate("crypto_1"), data[2]);
     }
 
     public void testInsert_MultipleObjects() throws SQLException {
@@ -92,15 +92,15 @@ public class Crypto_InRuntime_Test exten
             cipherByPlain.put(r[1], r[2]);
         }
 
-        assertEquals(Rot13CryptoFactory.rotate("crypto_1"), cipherByPlain.get("a"));
-        assertEquals(Rot13CryptoFactory.rotate("crypto_2"), cipherByPlain.get("b"));
+        assertEquals(Rot13TransformerFactory.rotate("crypto_1"), cipherByPlain.get("a"));
+        assertEquals(Rot13TransformerFactory.rotate("crypto_2"), cipherByPlain.get("b"));
     }
 
     public void test_SelectQuery() throws SQLException {
 
-        table1.insert(1, "plain_1", Rot13CryptoFactory.rotate("crypto_1"));
-        table1.insert(2, "plain_2", Rot13CryptoFactory.rotate("crypto_2"));
-        table1.insert(3, "plain_3", Rot13CryptoFactory.rotate("crypto_3"));
+        table1.insert(1, "plain_1", Rot13TransformerFactory.rotate("crypto_1"));
+        table1.insert(2, "plain_2", Rot13TransformerFactory.rotate("crypto_2"));
+        table1.insert(3, "plain_3", Rot13TransformerFactory.rotate("crypto_3"));
 
         SelectQuery<Table1> select = SelectQuery.query(Table1.class);
         select.addOrdering(Table1.PLAIN_STRING.asc());

Copied: cayenne/main/trunk/cayenne-crypto/src/test/java/org/apache/cayenne/crypto/unit/Rot13TransformerFactory.java (from r1582631, cayenne/main/trunk/cayenne-crypto/src/test/java/org/apache/cayenne/crypto/unit/Rot13CryptoFactory.java)
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/cayenne-crypto/src/test/java/org/apache/cayenne/crypto/unit/Rot13TransformerFactory.java?p2=cayenne/main/trunk/cayenne-crypto/src/test/java/org/apache/cayenne/crypto/unit/Rot13TransformerFactory.java&p1=cayenne/main/trunk/cayenne-crypto/src/test/java/org/apache/cayenne/crypto/unit/Rot13CryptoFactory.java&r1=1582631&r2=1582769&rev=1582769&view=diff
==============================================================================
--- cayenne/main/trunk/cayenne-crypto/src/test/java/org/apache/cayenne/crypto/unit/Rot13CryptoFactory.java (original)
+++ cayenne/main/trunk/cayenne-crypto/src/test/java/org/apache/cayenne/crypto/unit/Rot13TransformerFactory.java Fri Mar 28 14:56:12 2014
@@ -20,15 +20,14 @@ package org.apache.cayenne.crypto.unit;
 
 import java.io.UnsupportedEncodingException;
 
-import org.apache.cayenne.crypto.cipher.CryptoFactory;
-import org.apache.cayenne.crypto.cipher.Decryptor;
-import org.apache.cayenne.crypto.cipher.Encryptor;
-import org.apache.cayenne.map.DbAttribute;
+import javax.crypto.Cipher;
 
-public class Rot13CryptoFactory implements CryptoFactory {
+import org.apache.cayenne.crypto.cipher.ValueTransformer;
+import org.apache.cayenne.crypto.cipher.ValueTransformerFactory;
 
-    private Encryptor stringEncryptor;
-    private Decryptor stringDecryptor;
+public class Rot13TransformerFactory implements ValueTransformerFactory {
+
+    private ValueTransformer stringTransformer;
 
     public static String rotate(String value) {
         if (value == null) {
@@ -64,31 +63,24 @@ public class Rot13CryptoFactory implemen
         }
     }
 
-    public Rot13CryptoFactory() {
-        this.stringEncryptor = new Encryptor() {
+    public Rot13TransformerFactory() {
+        this.stringTransformer = new ValueTransformer() {
 
             @Override
-            public Object encrypt(Object plaintext) {
-                return plaintext != null ? rotate(plaintext.toString()) : null;
+            public Object transform(Cipher cipher, Object value) {
+                return value != null ? rotate(value.toString()) : null;
             }
         };
 
-        this.stringDecryptor = new Decryptor() {
-
-            @Override
-            public Object decrypt(Object ciphertext) {
-                return ciphertext != null ? rotate(ciphertext.toString()) : null;
-            }
-        };
     }
 
     @Override
-    public Encryptor getEncryptor(DbAttribute column) {
-        return stringEncryptor;
+    public ValueTransformer getDecryptor(int jdbcType) {
+        return stringTransformer;
     }
 
     @Override
-    public Decryptor getDecryptor(DbAttribute column) {
-        return stringDecryptor;
+    public ValueTransformer getEncryptor(int jdbcType) {
+        return stringTransformer;
     }
 }

Copied: cayenne/main/trunk/cayenne-crypto/src/test/java/org/apache/cayenne/crypto/unit/Rot13TransformerFactoryTest.java (from r1582631, cayenne/main/trunk/cayenne-crypto/src/test/java/org/apache/cayenne/crypto/unit/Rot13CryptoFactoryTest.java)
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/cayenne-crypto/src/test/java/org/apache/cayenne/crypto/unit/Rot13TransformerFactoryTest.java?p2=cayenne/main/trunk/cayenne-crypto/src/test/java/org/apache/cayenne/crypto/unit/Rot13TransformerFactoryTest.java&p1=cayenne/main/trunk/cayenne-crypto/src/test/java/org/apache/cayenne/crypto/unit/Rot13CryptoFactoryTest.java&r1=1582631&r2=1582769&rev=1582769&view=diff
==============================================================================
--- cayenne/main/trunk/cayenne-crypto/src/test/java/org/apache/cayenne/crypto/unit/Rot13CryptoFactoryTest.java (original)
+++ cayenne/main/trunk/cayenne-crypto/src/test/java/org/apache/cayenne/crypto/unit/Rot13TransformerFactoryTest.java Fri Mar 28 14:56:12 2014
@@ -18,22 +18,22 @@
  ****************************************************************/
 package org.apache.cayenne.crypto.unit;
 
-import junit.framework.TestCase;
+import java.sql.Types;
 
-import org.apache.cayenne.map.DbAttribute;
+import junit.framework.TestCase;
 
-public class Rot13CryptoFactoryTest extends TestCase {
+public class Rot13TransformerFactoryTest extends TestCase {
 
     public void testEncrypt() {
 
-        Rot13CryptoFactory factory = new Rot13CryptoFactory();
-        assertEquals("nop", factory.getEncryptor(new DbAttribute()).encrypt("abc"));
+        Rot13TransformerFactory factory = new Rot13TransformerFactory();
+        assertEquals("nop", factory.getEncryptor(Types.BINARY).transform(null, "abc"));
     }
 
     public void testDecrypt() {
 
-        Rot13CryptoFactory factory = new Rot13CryptoFactory();
-        assertEquals("nop", factory.getDecryptor(new DbAttribute()).decrypt("abc"));
+        Rot13TransformerFactory factory = new Rot13TransformerFactory();
+        assertEquals("nop", factory.getDecryptor(Types.BINARY).transform(null, "abc"));
     }
 
 }