You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cayenne.apache.org by ab...@apache.org on 2019/06/27 11:10:18 UTC

[cayenne] 04/05: CAY-2584 Crypto: can't use ColumnSelect with encrypted columns

This is an automated email from the ASF dual-hosted git repository.

abulatski pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/cayenne.git

commit 734cae4d7cceb20b7c6182b6a2bd55d427636ec0
Author: Arseni Bulatski <an...@gmail.com>
AuthorDate: Thu Jun 27 13:47:28 2019 +0300

    CAY-2584 Crypto: can't use ColumnSelect with encrypted columns
---
 .../reader/CryptoRowReaderFactoryDecorator.java    | 73 ++++++++++++++++++----
 .../crypto/transformer/DefaultMapTransformer.java  |  6 --
 .../apache/cayenne/crypto/Runtime_AES128_IT.java   | 23 ++++---
 3 files changed, 74 insertions(+), 28 deletions(-)

diff --git a/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/reader/CryptoRowReaderFactoryDecorator.java b/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/reader/CryptoRowReaderFactoryDecorator.java
index 688d787..bb818a8 100644
--- a/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/reader/CryptoRowReaderFactoryDecorator.java
+++ b/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/reader/CryptoRowReaderFactoryDecorator.java
@@ -81,7 +81,7 @@ public class CryptoRowReaderFactoryDecorator extends DefaultRowReaderFactory {
                                                  PostprocessorFactory postProcessorFactory) {
         RowReader<?> entityRowReader = super
                 .createEntityRowReader(descriptor, queryMetadata, resultMetadata, postProcessorFactory);
-        return new DecoratedFullRowReader(descriptor, entityRowReader);
+        return new DecoratedEntityRowReader(descriptor, entityRowReader, resultMetadata);
     }
 
     @Override
@@ -166,24 +166,23 @@ public class CryptoRowReaderFactoryDecorator extends DefaultRowReaderFactory {
         }
     }
 
-    private class DecoratedFullRowReader implements RowReader<Object> {
+    private abstract class DecoratedEntityFullRowReader implements RowReader<Object> {
 
-        private final RowDescriptor descriptor;
-        private final RowReader<?> delegateReader;
-        private boolean decryptorCompiled;
-        private MapTransformer decryptor;
+        final RowDescriptor descriptor;
+        final RowReader<?> delegateReader;
+        final EntityResultSegment resultMetadata;
+        boolean decryptorCompiled;
+        MapTransformer decryptor;
 
-        DecoratedFullRowReader(RowDescriptor descriptor, RowReader<?> delegateReader) {
+        DecoratedEntityFullRowReader(RowDescriptor descriptor,
+                                 RowReader<?> delegateReader,
+                                 EntityResultSegment resultMetadata) {
             this.descriptor = descriptor;
             this.delegateReader = delegateReader;
+            this.resultMetadata = resultMetadata;
         }
 
-        private void ensureDecryptorCompiled(Object row) {
-            if (!decryptorCompiled) {
-                decryptor = transformerFactory.decryptor(descriptor.getColumns(), row);
-                decryptorCompiled = true;
-            }
-        }
+        abstract void ensureDecryptorCompiled(Object row);
 
         @Override
         public Object readRow(ResultSet resultSet) {
@@ -200,4 +199,52 @@ public class CryptoRowReaderFactoryDecorator extends DefaultRowReaderFactory {
             return row;
         }
     }
+
+    private class DecoratedEntityRowReader extends DecoratedEntityFullRowReader {
+
+        DecoratedEntityRowReader(RowDescriptor descriptor,
+                                 RowReader<?> delegateReader,
+                                 EntityResultSegment resultMetadata) {
+            super(descriptor, delegateReader, resultMetadata);
+        }
+
+        void ensureDecryptorCompiled(Object row) {
+            if (!decryptorCompiled) {
+                int offset = resultMetadata.getColumnOffset();
+                int fieldsSize = resultMetadata.getFields().size();
+                ColumnDescriptor[] columnDescriptors =
+                        new ColumnDescriptor[fieldsSize];
+                for(int i = offset, j = 0; i < offset + fieldsSize; i++) {
+                    columnDescriptors[j++] = descriptor.getColumns()[i];
+                }
+                decryptor = transformerFactory.decryptor(columnDescriptors, row);
+                decryptorCompiled = true;
+            }
+        }
+
+        @Override
+        public Object readRow(ResultSet resultSet) {
+            return super.readRow(resultSet);
+        }
+    }
+
+    private class DecoratedFullRowReader extends DecoratedEntityFullRowReader {
+
+        DecoratedFullRowReader(RowDescriptor descriptor,
+                               RowReader<?> delegateReader) {
+            super(descriptor, delegateReader, null);
+        }
+
+        void ensureDecryptorCompiled(Object row) {
+            if (!decryptorCompiled) {
+                decryptor = transformerFactory.decryptor(descriptor.getColumns(), row);
+                decryptorCompiled = true;
+            }
+        }
+
+        @Override
+        public Object readRow(ResultSet resultSet) {
+            return super.readRow(resultSet);
+        }
+    }
 }
diff --git a/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/transformer/DefaultMapTransformer.java b/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/transformer/DefaultMapTransformer.java
index 622d8d7..5c778b0 100644
--- a/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/transformer/DefaultMapTransformer.java
+++ b/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/transformer/DefaultMapTransformer.java
@@ -18,7 +18,6 @@
  ****************************************************************/
 package org.apache.cayenne.crypto.transformer;
 
-import java.util.Arrays;
 import java.util.Map;
 
 import org.apache.cayenne.crypto.transformer.bytes.BytesDecryptor;
@@ -42,7 +41,6 @@ public class DefaultMapTransformer implements MapTransformer {
     @Override
     public void transform(Map<String, Object> map) {
 
-        mapKeys = mergeSameKeys(mapKeys);
         int len = mapKeys.length;
 
         for (int i = 0; i < len; i++) {
@@ -54,8 +52,4 @@ public class DefaultMapTransformer implements MapTransformer {
             }
         }
     }
-
-    private String[] mergeSameKeys(String[] keys) {
-        return Arrays.stream(keys).distinct().toArray(String[]::new);
-    }
 }
diff --git a/cayenne-crypto/src/test/java/org/apache/cayenne/crypto/Runtime_AES128_IT.java b/cayenne-crypto/src/test/java/org/apache/cayenne/crypto/Runtime_AES128_IT.java
index 6dddecd..88b3072 100644
--- a/cayenne-crypto/src/test/java/org/apache/cayenne/crypto/Runtime_AES128_IT.java
+++ b/cayenne-crypto/src/test/java/org/apache/cayenne/crypto/Runtime_AES128_IT.java
@@ -29,7 +29,6 @@ import org.apache.cayenne.crypto.db.Table2;
 import org.apache.cayenne.crypto.db.Table7;
 import org.apache.cayenne.crypto.transformer.value.IntegerConverter;
 import org.apache.cayenne.crypto.unit.CryptoUnitUtils;
-import org.apache.cayenne.exp.Property;
 import org.apache.cayenne.exp.property.PropertyFactory;
 import org.apache.cayenne.query.ObjectSelect;
 import org.apache.cayenne.query.SelectQuery;
@@ -172,7 +171,7 @@ public class Runtime_AES128_IT extends Runtime_AES128_Base {
         context.commitChanges();
 
         List<Table1> result = ObjectSelect
-                .columnQuery(Table1.class, Property.createSelf(Table1.class))
+                .columnQuery(Table1.class, PropertyFactory.createSelf(Table1.class))
                 .select(context);
 
         assertEquals(1, result.size());
@@ -192,7 +191,9 @@ public class Runtime_AES128_IT extends Runtime_AES128_Base {
         context.commitChanges();
 
         List<Object[]> result = ObjectSelect
-                .columnQuery(Table1.class, Property.createSelf(Table1.class), Table1.PLAIN_INT)
+                .columnQuery(Table1.class,
+                        PropertyFactory.createSelf(Table1.class),
+                        Table1.PLAIN_INT)
                 .select(context);
 
         assertEquals(1, result.size());
@@ -214,7 +215,9 @@ public class Runtime_AES128_IT extends Runtime_AES128_Base {
         context.commitChanges();
 
         List<Object[]> result = ObjectSelect
-                .columnQuery(Table1.class, PropertyFactory.createSelf(Table1.class), Table1.CRYPTO_INT)
+                .columnQuery(Table1.class,
+                        PropertyFactory.createSelf(Table1.class),
+                        Table1.CRYPTO_INT)
                 .select(context);
 
         assertEquals(1, result.size());
@@ -243,17 +246,19 @@ public class Runtime_AES128_IT extends Runtime_AES128_Base {
 
         List<Object[]> result = ObjectSelect
                 .columnQuery(Table1.class,
+                        Table1.CRYPTO_INT,
                         PropertyFactory.createSelf(Table1.class),
                         Table1.CRYPTO_INT,
                         Table1.TABLE7S.dot(Table7.CRYPTO_INT),
                         Table1.TABLE7S.dot(Table7.CRYPTO_STRING))
                 .select(context);
         assertEquals(1, result.size());
-        assertEquals(1, ((Table1)result.get(0)[0]).getCryptoInt());
-        assertEquals("test", ((Table1)result.get(0)[0]).getCryptoString());
-        assertEquals(1, result.get(0)[1]);
-        assertEquals(2, result.get(0)[2]);
-        assertEquals("string", result.get(0)[3]);
+        assertEquals(1, result.get(0)[0]);
+        assertEquals(1, ((Table1)result.get(0)[1]).getCryptoInt());
+        assertEquals("test", ((Table1)result.get(0)[1]).getCryptoString());
+        assertEquals(1, result.get(0)[2]);
+        assertEquals(2, result.get(0)[3]);
+        assertEquals("string", result.get(0)[4]);
     }
 
     @Test