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 acdfa178dc75e52be39540b2269ba41e2ec03f75 Author: Arseni Bulatski <ancars...@gmail.com> AuthorDate: Fri Jun 21 11:28:14 2019 +0300 CAY-2584 Crypto: can't use ColumnSelect with encrypted columns --- RELEASE-NOTES.txt | 1 + .../crypto/transformer/DefaultMapTransformer.java | 6 ++ .../apache/cayenne/crypto/Runtime_AES128_IT.java | 105 +++++++++++++++++++-- .../java/org/apache/cayenne/crypto/db/Table7.java | 9 ++ .../org/apache/cayenne/crypto/db/auto/_Table1.java | 25 +++++ .../crypto/db/auto/{_Table1.java => _Table7.java} | 54 ++++------- .../src/test/resources/cayenne-crypto.xml | 2 + cayenne-crypto/src/test/resources/datamap.map.xml | 20 +++- .../cayenne/access/jdbc/ColumnDescriptor.java | 7 -- 9 files changed, 177 insertions(+), 52 deletions(-) diff --git a/RELEASE-NOTES.txt b/RELEASE-NOTES.txt index 1fa3317..337e6e0 100644 --- a/RELEASE-NOTES.txt +++ b/RELEASE-NOTES.txt @@ -60,6 +60,7 @@ CAY-2577 Between property with extended type failure CAY-2578 Wrong bindings in select of related entity by compound FK CAY-2580 Cgen: Can't use custom templates for client mode CAY-2582 Double insert of manyToMany relationship mapped to Set +CAY-2584 Crypto: can't use ColumnSelect with encrypted columns ---------------------------------- Release: 4.1.B1 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 5c778b0..622d8d7 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,6 +18,7 @@ ****************************************************************/ package org.apache.cayenne.crypto.transformer; +import java.util.Arrays; import java.util.Map; import org.apache.cayenne.crypto.transformer.bytes.BytesDecryptor; @@ -41,6 +42,7 @@ 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++) { @@ -52,4 +54,8 @@ 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 338e9d8..6dddecd 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 @@ -18,25 +18,28 @@ ****************************************************************/ package org.apache.cayenne.crypto; +import java.sql.SQLException; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + import org.apache.cayenne.ObjectContext; import org.apache.cayenne.crypto.db.Table1; 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; import org.junit.Before; import org.junit.Test; -import java.sql.SQLException; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; public class Runtime_AES128_IT extends Runtime_AES128_Base { @@ -207,10 +210,11 @@ public class Runtime_AES128_IT extends Runtime_AES128_Base { t1.setCryptoInt(1); t1.setPlainInt(2); t1.setCryptoString("test"); + t1.setPlainString("Test"); context.commitChanges(); List<Object[]> result = ObjectSelect - .columnQuery(Table1.class, Property.createSelf(Table1.class), Table1.CRYPTO_INT) + .columnQuery(Table1.class, PropertyFactory.createSelf(Table1.class), Table1.CRYPTO_INT) .select(context); assertEquals(1, result.size()); @@ -220,6 +224,95 @@ public class Runtime_AES128_IT extends Runtime_AES128_Base { } @Test + public void testColumnQueryWithRelationshipWithTheSameNames() { + ObjectContext context = runtime.newContext(); + + Table1 t1 = context.newObject(Table1.class); + t1.setCryptoInt(1); + t1.setPlainInt(3); + t1.setCryptoString("test"); + t1.setPlainString("Test"); + + Table7 t7 = context.newObject(Table7.class); + t7.setCryptoInt(2); + t7.setCryptoString("string"); + + t1.addToTable7s(t7); + + context.commitChanges(); + + List<Object[]> result = ObjectSelect + .columnQuery(Table1.class, + 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]); + } + + @Test + public void testSelectWith2Objects() { + ObjectContext context = runtime.newContext(); + + Table1 t1 = context.newObject(Table1.class); + t1.setCryptoInt(1); + t1.setPlainInt(3); + t1.setCryptoString("test"); + t1.setPlainString("Test"); + + Table7 t7 = context.newObject(Table7.class); + t7.setCryptoInt(2); + t7.setCryptoString("string"); + + t1.addToTable7s(t7); + + context.commitChanges(); + + List<Object[]> result = ObjectSelect + .columnQuery(Table1.class, + PropertyFactory.createSelf(Table1.class), + Table1.TABLE7S.flat()) + .select(context); + assertEquals(1, result.size()); + assertEquals("test", ((Table1)result.get(0)[0]).getCryptoString()); + assertTrue(result.get(0)[1] instanceof Table7); + assertEquals(2, ((Table7)result.get(0)[1]).getCryptoInt()); + } + + @Test + public void testObjectSelectWithPrefetch() { + ObjectContext context = runtime.newContext(); + + Table1 t1 = context.newObject(Table1.class); + t1.setCryptoInt(1); + t1.setPlainInt(3); + t1.setCryptoString("test"); + t1.setPlainString("Test"); + + Table7 t7 = context.newObject(Table7.class); + t7.setCryptoInt(2); + t7.setCryptoString("string"); + + t1.addToTable7s(t7); + + context.commitChanges(); + + List<Table1> table1s = ObjectSelect.query(Table1.class) + .prefetch(Table1.TABLE7S.disjoint()) + .select(context); + + assertEquals(1, table1s.size()); + assertEquals("test", table1s.get(0).getCryptoString()); + assertEquals("string", table1s.get(0).getTable7s().get(0).getCryptoString()); + } + + @Test public void test_ColumnQuerySingleScalar() { ObjectContext context = runtime.newContext(); diff --git a/cayenne-crypto/src/test/java/org/apache/cayenne/crypto/db/Table7.java b/cayenne-crypto/src/test/java/org/apache/cayenne/crypto/db/Table7.java new file mode 100644 index 0000000..2d65080 --- /dev/null +++ b/cayenne-crypto/src/test/java/org/apache/cayenne/crypto/db/Table7.java @@ -0,0 +1,9 @@ +package org.apache.cayenne.crypto.db; + +import org.apache.cayenne.crypto.db.auto._Table7; + +public class Table7 extends _Table7 { + + private static final long serialVersionUID = 1L; + +} diff --git a/cayenne-crypto/src/test/java/org/apache/cayenne/crypto/db/auto/_Table1.java b/cayenne-crypto/src/test/java/org/apache/cayenne/crypto/db/auto/_Table1.java index 0d32a17..71855de 100644 --- a/cayenne-crypto/src/test/java/org/apache/cayenne/crypto/db/auto/_Table1.java +++ b/cayenne-crypto/src/test/java/org/apache/cayenne/crypto/db/auto/_Table1.java @@ -3,8 +3,11 @@ package org.apache.cayenne.crypto.db.auto; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; +import java.util.List; import org.apache.cayenne.BaseDataObject; +import org.apache.cayenne.crypto.db.Table7; +import org.apache.cayenne.exp.property.ListProperty; import org.apache.cayenne.exp.property.NumericProperty; import org.apache.cayenne.exp.property.PropertyFactory; import org.apache.cayenne.exp.property.StringProperty; @@ -25,12 +28,14 @@ public abstract class _Table1 extends BaseDataObject { public static final StringProperty<String> CRYPTO_STRING = PropertyFactory.createString("cryptoString", String.class); public static final NumericProperty<Integer> PLAIN_INT = PropertyFactory.createNumeric("plainInt", Integer.class); public static final StringProperty<String> PLAIN_STRING = PropertyFactory.createString("plainString", String.class); + public static final ListProperty<Table7> TABLE7S = PropertyFactory.createList("table7s", Table7.class); protected Integer cryptoInt; protected String cryptoString; protected Integer plainInt; protected String plainString; + protected Object table7s; public void setCryptoInt(int cryptoInt) { beforePropertyWrite("cryptoInt", this.cryptoInt, cryptoInt); @@ -78,6 +83,19 @@ public abstract class _Table1 extends BaseDataObject { return this.plainString; } + public void addToTable7s(Table7 obj) { + addToManyTarget("table7s", obj, true); + } + + public void removeFromTable7s(Table7 obj) { + removeToManyTarget("table7s", obj, true); + } + + @SuppressWarnings("unchecked") + public List<Table7> getTable7s() { + return (List<Table7>)readProperty("table7s"); + } + @Override public Object readPropertyDirectly(String propName) { if(propName == null) { @@ -93,6 +111,8 @@ public abstract class _Table1 extends BaseDataObject { return this.plainInt; case "plainString": return this.plainString; + case "table7s": + return this.table7s; default: return super.readPropertyDirectly(propName); } @@ -117,6 +137,9 @@ public abstract class _Table1 extends BaseDataObject { case "plainString": this.plainString = (String)val; break; + case "table7s": + this.table7s = val; + break; default: super.writePropertyDirectly(propName, val); } @@ -137,6 +160,7 @@ public abstract class _Table1 extends BaseDataObject { out.writeObject(this.cryptoString); out.writeObject(this.plainInt); out.writeObject(this.plainString); + out.writeObject(this.table7s); } @Override @@ -146,6 +170,7 @@ public abstract class _Table1 extends BaseDataObject { this.cryptoString = (String)in.readObject(); this.plainInt = (Integer)in.readObject(); this.plainString = (String)in.readObject(); + this.table7s = in.readObject(); } } diff --git a/cayenne-crypto/src/test/java/org/apache/cayenne/crypto/db/auto/_Table1.java b/cayenne-crypto/src/test/java/org/apache/cayenne/crypto/db/auto/_Table7.java similarity index 68% copy from cayenne-crypto/src/test/java/org/apache/cayenne/crypto/db/auto/_Table1.java copy to cayenne-crypto/src/test/java/org/apache/cayenne/crypto/db/auto/_Table7.java index 0d32a17..3964c74 100644 --- a/cayenne-crypto/src/test/java/org/apache/cayenne/crypto/db/auto/_Table1.java +++ b/cayenne-crypto/src/test/java/org/apache/cayenne/crypto/db/auto/_Table7.java @@ -5,17 +5,19 @@ import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import org.apache.cayenne.BaseDataObject; +import org.apache.cayenne.crypto.db.Table1; +import org.apache.cayenne.exp.property.EntityProperty; import org.apache.cayenne.exp.property.NumericProperty; import org.apache.cayenne.exp.property.PropertyFactory; import org.apache.cayenne.exp.property.StringProperty; /** - * Class _Table1 was generated by Cayenne. + * Class _Table7 was generated by Cayenne. * It is probably a good idea to avoid changing this class manually, * since it may be overwritten next time code is regenerated. * If you need to make any customizations, please use subclass. */ -public abstract class _Table1 extends BaseDataObject { +public abstract class _Table7 extends BaseDataObject { private static final long serialVersionUID = 1L; @@ -23,14 +25,12 @@ public abstract class _Table1 extends BaseDataObject { public static final NumericProperty<Integer> CRYPTO_INT = PropertyFactory.createNumeric("cryptoInt", Integer.class); public static final StringProperty<String> CRYPTO_STRING = PropertyFactory.createString("cryptoString", String.class); - public static final NumericProperty<Integer> PLAIN_INT = PropertyFactory.createNumeric("plainInt", Integer.class); - public static final StringProperty<String> PLAIN_STRING = PropertyFactory.createString("plainString", String.class); + public static final EntityProperty<Table1> TO_TABLE1 = PropertyFactory.createEntity("toTable1", Table1.class); protected Integer cryptoInt; protected String cryptoString; - protected Integer plainInt; - protected String plainString; + protected Object toTable1; public void setCryptoInt(int cryptoInt) { beforePropertyWrite("cryptoInt", this.cryptoInt, cryptoInt); @@ -55,27 +55,12 @@ public abstract class _Table1 extends BaseDataObject { return this.cryptoString; } - public void setPlainInt(int plainInt) { - beforePropertyWrite("plainInt", this.plainInt, plainInt); - this.plainInt = plainInt; + public void setToTable1(Table1 toTable1) { + setToOneTarget("toTable1", toTable1, true); } - public int getPlainInt() { - beforePropertyRead("plainInt"); - if(this.plainInt == null) { - return 0; - } - return this.plainInt; - } - - public void setPlainString(String plainString) { - beforePropertyWrite("plainString", this.plainString, plainString); - this.plainString = plainString; - } - - public String getPlainString() { - beforePropertyRead("plainString"); - return this.plainString; + public Table1 getToTable1() { + return (Table1)readProperty("toTable1"); } @Override @@ -89,10 +74,8 @@ public abstract class _Table1 extends BaseDataObject { return this.cryptoInt; case "cryptoString": return this.cryptoString; - case "plainInt": - return this.plainInt; - case "plainString": - return this.plainString; + case "toTable1": + return this.toTable1; default: return super.readPropertyDirectly(propName); } @@ -111,11 +94,8 @@ public abstract class _Table1 extends BaseDataObject { case "cryptoString": this.cryptoString = (String)val; break; - case "plainInt": - this.plainInt = (Integer)val; - break; - case "plainString": - this.plainString = (String)val; + case "toTable1": + this.toTable1 = val; break; default: super.writePropertyDirectly(propName, val); @@ -135,8 +115,7 @@ public abstract class _Table1 extends BaseDataObject { super.writeState(out); out.writeObject(this.cryptoInt); out.writeObject(this.cryptoString); - out.writeObject(this.plainInt); - out.writeObject(this.plainString); + out.writeObject(this.toTable1); } @Override @@ -144,8 +123,7 @@ public abstract class _Table1 extends BaseDataObject { super.readState(in); this.cryptoInt = (Integer)in.readObject(); this.cryptoString = (String)in.readObject(); - this.plainInt = (Integer)in.readObject(); - this.plainString = (String)in.readObject(); + this.toTable1 = in.readObject(); } } diff --git a/cayenne-crypto/src/test/resources/cayenne-crypto.xml b/cayenne-crypto/src/test/resources/cayenne-crypto.xml index 1680c10..dea206b 100644 --- a/cayenne-crypto/src/test/resources/cayenne-crypto.xml +++ b/cayenne-crypto/src/test/resources/cayenne-crypto.xml @@ -1,5 +1,7 @@ <?xml version="1.0" encoding="utf-8"?> <domain xmlns="http://cayenne.apache.org/schema/10/domain" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://cayenne.apache.org/schema/10/domain https://cayenne.apache.org/schema/10/domain.xsd" project-version="10"> <map name="datamap"/> <node name="datanode" diff --git a/cayenne-crypto/src/test/resources/datamap.map.xml b/cayenne-crypto/src/test/resources/datamap.map.xml index fd572a8..6c40f2c 100644 --- a/cayenne-crypto/src/test/resources/datamap.map.xml +++ b/cayenne-crypto/src/test/resources/datamap.map.xml @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="utf-8"?> <data-map xmlns="http://cayenne.apache.org/schema/10/modelMap" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap http://cayenne.apache.org/schema/10/modelMap.xsd" + xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap https://cayenne.apache.org/schema/10/modelMap.xsd" project-version="10"> <property name="defaultPackage" value="org.apache.cayenne.crypto.db"/> <db-entity name="TABLE1"> @@ -32,6 +32,12 @@ <db-attribute name="CRYPTO_INT4" type="BLOB"/> <db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/> </db-entity> + <db-entity name="TABLE7"> + <db-attribute name="CRYPTO_INT" type="BLOB"/> + <db-attribute name="CRYPTO_STRING" type="CLOB"/> + <db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/> + <db-attribute name="TABLE1_ID" type="INTEGER"/> + </db-entity> <obj-entity name="Table1" className="org.apache.cayenne.crypto.db.Table1" dbEntityName="TABLE1"> <obj-attribute name="cryptoInt" type="int" db-attribute-path="CRYPTO_INT"/> <obj-attribute name="cryptoString" type="java.lang.String" db-attribute-path="CRYPTO_STRING"/> @@ -58,4 +64,16 @@ <obj-attribute name="cryptoInt1" type="long" db-attribute-path="CRYPTO_INT1"/> <obj-attribute name="cryptoInt4" type="int" db-attribute-path="CRYPTO_INT4"/> </obj-entity> + <obj-entity name="Table7" className="org.apache.cayenne.crypto.db.Table7" dbEntityName="TABLE7"> + <obj-attribute name="cryptoInt" type="int" db-attribute-path="CRYPTO_INT"/> + <obj-attribute name="cryptoString" type="java.lang.String" db-attribute-path="CRYPTO_STRING"/> + </obj-entity> + <db-relationship name="table7s" source="TABLE1" target="TABLE7" toMany="true"> + <db-attribute-pair source="ID" target="TABLE1_ID"/> + </db-relationship> + <db-relationship name="toTable1" source="TABLE7" target="TABLE1"> + <db-attribute-pair source="TABLE1_ID" target="ID"/> + </db-relationship> + <obj-relationship name="table7s" source="Table1" target="Table7" deleteRule="Deny" db-relationship-path="table7s"/> + <obj-relationship name="toTable1" source="Table7" target="Table1" deleteRule="Nullify" db-relationship-path="toTable1"/> </data-map> diff --git a/cayenne-server/src/main/java/org/apache/cayenne/access/jdbc/ColumnDescriptor.java b/cayenne-server/src/main/java/org/apache/cayenne/access/jdbc/ColumnDescriptor.java index a2eeed9..ea30eb9 100644 --- a/cayenne-server/src/main/java/org/apache/cayenne/access/jdbc/ColumnDescriptor.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/access/jdbc/ColumnDescriptor.java @@ -149,10 +149,6 @@ public class ColumnDescriptor { return name; } - public void setAttribute(DbAttribute attribute) { - this.attribute = attribute; - } - /** * Returns a DbAttribute for this column. Since columns descriptors can be * initialized in a context where a DbAttribite is unknown, this method may @@ -164,9 +160,6 @@ public class ColumnDescriptor { return attribute; } - /** - * @since 4.2 - */ public void setAttribute(DbAttribute attribute) { this.attribute = attribute; }