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/17 14:49:27 UTC

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

Author: aadamchik
Date: Mon Mar 17 13:49:27 2014
New Revision: 1578376

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

select decryption

Added:
    cayenne/main/trunk/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/reader/
    cayenne/main/trunk/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/reader/CryptoRowReaderFactoryDecorator.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/test/java/org/apache/cayenne/crypto/Crypto_InRuntime_Test.java
    cayenne/main/trunk/cayenne-server/src/main/java/org/apache/cayenne/access/jdbc/ColumnDescriptor.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=1578376&r1=1578375&r2=1578376&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 Mon Mar 17 13:49:27 2014
@@ -18,10 +18,12 @@
  ****************************************************************/
 package org.apache.cayenne.crypto;
 
+import org.apache.cayenne.access.jdbc.reader.RowReaderFactory;
 import org.apache.cayenne.access.translator.batch.BatchTranslatorFactory;
 import org.apache.cayenne.crypto.batch.CryptoBatchTranslatorFactoryDecorator;
 import org.apache.cayenne.crypto.cipher.CryptoHandler;
 import org.apache.cayenne.crypto.map.ColumnMapper;
+import org.apache.cayenne.crypto.reader.CryptoRowReaderFactoryDecorator;
 import org.apache.cayenne.di.Binder;
 import org.apache.cayenne.di.Module;
 
@@ -81,8 +83,9 @@ public class CryptoModuleBuilder {
                 } else {
                     binder.bind(ColumnMapper.class).toInstance(columnMapper);
                 }
-                
-                binder.decorate(BatchTranslatorFactory.class).after(CryptoBatchTranslatorFactoryDecorator.class);
+
+                binder.decorate(BatchTranslatorFactory.class).before(CryptoBatchTranslatorFactoryDecorator.class);
+                binder.decorate(RowReaderFactory.class).before(CryptoRowReaderFactoryDecorator.class);
             }
         };
     }

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=1578376&r1=1578375&r2=1578376&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 Mon Mar 17 13:49:27 2014
@@ -36,15 +36,15 @@ import org.apache.cayenne.query.BatchQue
  */
 public class CryptoBatchTranslatorFactoryDecorator implements BatchTranslatorFactory {
 
-    private CryptoHandler cipherService;
+    private CryptoHandler cryptoHandler;
     private ColumnMapper columnMapper;
     private BatchTranslatorFactory delegate;
 
     public CryptoBatchTranslatorFactoryDecorator(@Inject BatchTranslatorFactory delegate,
-            @Inject CryptoHandler cipherService, @Inject ColumnMapper columnMapper) {
+            @Inject CryptoHandler cryptoHandler, @Inject ColumnMapper columnMapper) {
 
         this.columnMapper = columnMapper;
-        this.cipherService = cipherService;
+        this.cryptoHandler = cryptoHandler;
         this.delegate = delegate;
     }
 
@@ -70,7 +70,7 @@ public class CryptoBatchTranslatorFactor
 
                 for (BatchParameterBinding b : bindings) {
                     if (columnMapper.isEncrypted(b.getAttribute())) {
-                        Object encrypted = cipherService.encrypt(b.getValue(), b.getAttribute().getType());
+                        Object encrypted = cryptoHandler.encrypt(b.getValue(), b.getAttribute().getType());
                         b.setValue(encrypted);
                     }
                 }

Added: 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=1578376&view=auto
==============================================================================
--- cayenne/main/trunk/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/reader/CryptoRowReaderFactoryDecorator.java (added)
+++ cayenne/main/trunk/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/reader/CryptoRowReaderFactoryDecorator.java Mon Mar 17 13:49:27 2014
@@ -0,0 +1,113 @@
+/*****************************************************************
+ *   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.reader;
+
+import java.sql.ResultSet;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.cayenne.access.jdbc.ColumnDescriptor;
+import org.apache.cayenne.access.jdbc.RowDescriptor;
+import org.apache.cayenne.access.jdbc.reader.RowReader;
+import org.apache.cayenne.access.jdbc.reader.RowReaderFactory;
+import org.apache.cayenne.crypto.cipher.CryptoHandler;
+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.map.ObjAttribute;
+import org.apache.cayenne.query.QueryMetadata;
+
+public class CryptoRowReaderFactoryDecorator implements RowReaderFactory {
+
+    private RowReaderFactory delegate;
+    private ColumnMapper columnMapper;
+    private CryptoHandler cryptoHandler;
+
+    public CryptoRowReaderFactoryDecorator(@Inject RowReaderFactory delegate, @Inject CryptoHandler cryptoHandler,
+            @Inject ColumnMapper columnMapper) {
+        this.delegate = delegate;
+        this.columnMapper = columnMapper;
+        this.cryptoHandler = cryptoHandler;
+    }
+
+    @Override
+    public RowReader<?> rowReader(RowDescriptor descriptor, QueryMetadata queryMetadata, DbAdapter adapter,
+            Map<ObjAttribute, ColumnDescriptor> attributeOverrides) {
+
+        List<ColumnDescriptor> encryptedColumns = null;
+
+        for (ColumnDescriptor cd : descriptor.getColumns()) {
+
+            DbAttribute attribute = cd.getAttribute();
+            if (attribute != null && columnMapper.isEncrypted(attribute)) {
+                if (encryptedColumns == null) {
+                    encryptedColumns = new ArrayList<ColumnDescriptor>();
+                }
+
+                encryptedColumns.add(cd);
+            }
+        }
+
+        final RowReader<?> delegateReader = delegate.rowReader(descriptor, queryMetadata, adapter, attributeOverrides);
+
+        if (encryptedColumns == null) {
+            return delegateReader;
+        }
+
+        final int len = encryptedColumns.size();
+        final String[] labels = new String[len];
+        final int[] types = new int[len];
+
+        for (int i = 0; i < len; i++) {
+            labels[i] = encryptedColumns.get(i).getDataRowKey();
+            types[i] = encryptedColumns.get(i).getJdbcType();
+        }
+
+        return new RowReader<Object>() {
+            private Boolean canDecrypt;
+
+            @Override
+            public Object readRow(ResultSet resultSet) {
+                Object row = delegateReader.readRow(resultSet);
+
+                if (canDecrypt == null) {
+                    canDecrypt = row instanceof Map;
+                }
+
+                if (canDecrypt) {
+                    @SuppressWarnings({ "unchecked", "rawtypes" })
+                    Map<String, Object> map = (Map) row;
+
+                    for (int i = 0; i < len; i++) {
+                        Object encrypted = map.get(labels[i]);
+
+                        if (encrypted != null) {
+                            map.put(labels[i], cryptoHandler.decrypt(encrypted, types[i]));
+                        }
+                    }
+                }
+
+                return row;
+            }
+        };
+    }
+
+}

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=1578376&r1=1578375&r2=1578376&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 Mon Mar 17 13:49:27 2014
@@ -31,6 +31,7 @@ import org.apache.cayenne.crypto.db.Tabl
 import org.apache.cayenne.crypto.map.PatternColumnMapper;
 import org.apache.cayenne.crypto.unit.Rot13CryptoHandler;
 import org.apache.cayenne.di.Module;
+import org.apache.cayenne.query.SelectQuery;
 import org.apache.cayenne.test.jdbc.DBHelper;
 import org.apache.cayenne.test.jdbc.TableHelper;
 
@@ -95,4 +96,21 @@ public class Crypto_InRuntime_Test exten
         assertEquals(Rot13CryptoHandler.rotate("crypto_2"), cipherByPlain.get("b"));
     }
 
+    public void test_SelectQuery() throws SQLException {
+
+        table1.insert(1, "plain_1", Rot13CryptoHandler.rotate("crypto_1"));
+        table1.insert(2, "plain_2", Rot13CryptoHandler.rotate("crypto_2"));
+        table1.insert(3, "plain_3", Rot13CryptoHandler.rotate("crypto_3"));
+
+        SelectQuery<Table1> select = SelectQuery.query(Table1.class);
+        select.addOrdering(Table1.PLAIN_STRING.asc());
+
+        List<Table1> result = runtime.newContext().select(select);
+
+        assertEquals(3, result.size());
+        assertEquals("crypto_1", result.get(0).getCryptoString());
+        assertEquals("crypto_2", result.get(1).getCryptoString());
+        assertEquals("crypto_3", result.get(2).getCryptoString());
+    }
+
 }

Modified: cayenne/main/trunk/cayenne-server/src/main/java/org/apache/cayenne/access/jdbc/ColumnDescriptor.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/cayenne-server/src/main/java/org/apache/cayenne/access/jdbc/ColumnDescriptor.java?rev=1578376&r1=1578375&r2=1578376&view=diff
==============================================================================
--- cayenne/main/trunk/cayenne-server/src/main/java/org/apache/cayenne/access/jdbc/ColumnDescriptor.java (original)
+++ cayenne/main/trunk/cayenne-server/src/main/java/org/apache/cayenne/access/jdbc/ColumnDescriptor.java Mon Mar 17 13:49:27 2014
@@ -37,6 +37,7 @@ import org.apache.cayenne.util.ToStringB
  */
 public class ColumnDescriptor {
 
+    protected DbAttribute attribute;
     protected String tableName;
     protected String procedureName;
 
@@ -75,6 +76,8 @@ public class ColumnDescriptor {
      */
     public ColumnDescriptor(DbAttribute attribute, String tableAlias) {
         this(attribute.getName(), attribute.getType());
+
+        this.attribute = attribute;
         this.namePrefix = tableAlias;
 
         if (attribute.getEntity() != null) {
@@ -135,6 +138,17 @@ public class ColumnDescriptor {
     }
 
     /**
+     * Returns a DbAttribute for this column. Since columns descriptors can be
+     * initialized in a context where a DbAttribite is unknown, this method may
+     * return null.
+     * 
+     * @since 3.2
+     */
+    public DbAttribute getAttribute() {
+        return attribute;
+    }
+
+    /**
      * Returns true if another object is a ColumnDescriptor with the same name,
      * name prefix, table and procedure names. Other fields are ignored in the
      * equality test.