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 2016/08/25 09:49:56 UTC
[1/4] cayenne git commit: CAY-2107 cayenne-crypto: Lazy
initialization of crypto subsystem
Repository: cayenne
Updated Branches:
refs/heads/master a5b833d5f -> aecf9aa31
CAY-2107 cayenne-crypto: Lazy initialization of crypto subsystem
Project: http://git-wip-us.apache.org/repos/asf/cayenne/repo
Commit: http://git-wip-us.apache.org/repos/asf/cayenne/commit/3d96be62
Tree: http://git-wip-us.apache.org/repos/asf/cayenne/tree/3d96be62
Diff: http://git-wip-us.apache.org/repos/asf/cayenne/diff/3d96be62
Branch: refs/heads/master
Commit: 3d96be6237382993a06c35a1071403cb5bd6cad7
Parents: a5b833d
Author: Andrus Adamchik <an...@objectstyle.com>
Authored: Thu Aug 25 11:54:10 2016 +0300
Committer: Andrus Adamchik <an...@objectstyle.com>
Committed: Thu Aug 25 11:54:37 2016 +0300
----------------------------------------------------------------------
.../cayenne/crypto/CryptoModuleBuilder.java | 7 +++
.../bytes/LazyBytesTransformerFactory.java | 62 +++++++++++++++++++
.../value/LazyValueTransformerFactory.java | 64 ++++++++++++++++++++
docs/doc/src/main/resources/RELEASE-NOTES.txt | 3 +-
4 files changed, 135 insertions(+), 1 deletion(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cayenne/blob/3d96be62/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/CryptoModuleBuilder.java
----------------------------------------------------------------------
diff --git a/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/CryptoModuleBuilder.java b/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/CryptoModuleBuilder.java
index 151e320..4162409 100644
--- a/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/CryptoModuleBuilder.java
+++ b/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/CryptoModuleBuilder.java
@@ -32,6 +32,7 @@ import org.apache.cayenne.crypto.transformer.DefaultTransformerFactory;
import org.apache.cayenne.crypto.transformer.TransformerFactory;
import org.apache.cayenne.crypto.transformer.bytes.BytesTransformerFactory;
import org.apache.cayenne.crypto.transformer.bytes.DefaultBytesTransformerFactory;
+import org.apache.cayenne.crypto.transformer.bytes.LazyBytesTransformerFactory;
import org.apache.cayenne.crypto.transformer.value.Base64StringConverter;
import org.apache.cayenne.crypto.transformer.value.BigDecimalConverter;
import org.apache.cayenne.crypto.transformer.value.BigIntegerConverter;
@@ -43,6 +44,7 @@ import org.apache.cayenne.crypto.transformer.value.DefaultValueTransformerFactor
import org.apache.cayenne.crypto.transformer.value.DoubleConverter;
import org.apache.cayenne.crypto.transformer.value.FloatConverter;
import org.apache.cayenne.crypto.transformer.value.IntegerConverter;
+import org.apache.cayenne.crypto.transformer.value.LazyValueTransformerFactory;
import org.apache.cayenne.crypto.transformer.value.LongConverter;
import org.apache.cayenne.crypto.transformer.value.ShortConverter;
import org.apache.cayenne.crypto.transformer.value.Utf8StringConverter;
@@ -380,6 +382,11 @@ public class CryptoModuleBuilder {
binder.decorate(BatchTranslatorFactory.class).before(CryptoBatchTranslatorFactoryDecorator.class);
binder.decorate(RowReaderFactory.class).before(CryptoRowReaderFactoryDecorator.class);
+
+ // decorate our own services to allow Cayenne to operate over plaintext entities
+ // even if crypto keys are not available.
+ binder.decorate(ValueTransformerFactory.class).after(LazyValueTransformerFactory.class);
+ binder.decorate(BytesTransformerFactory.class).after(LazyBytesTransformerFactory.class);
}
};
}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/3d96be62/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/transformer/bytes/LazyBytesTransformerFactory.java
----------------------------------------------------------------------
diff --git a/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/transformer/bytes/LazyBytesTransformerFactory.java b/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/transformer/bytes/LazyBytesTransformerFactory.java
new file mode 100644
index 0000000..ee7a3ad
--- /dev/null
+++ b/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/transformer/bytes/LazyBytesTransformerFactory.java
@@ -0,0 +1,62 @@
+/*****************************************************************
+ * 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.transformer.bytes;
+
+import org.apache.cayenne.di.Inject;
+import org.apache.cayenne.di.Provider;
+
+/**
+ * A decorator of {@link BytesTransformerFactory} that allows to defer its initialization and hence allows Cayenne stack
+ * to operate without crypto keys over a subset of entities that do not require encryption. Useful e.g. when the crypto
+ * keys are supplied at a later point after startup.
+ *
+ * @since 4.0
+ */
+public class LazyBytesTransformerFactory implements BytesTransformerFactory {
+
+ private Provider<BytesTransformerFactory> delegateProvider;
+ private volatile BytesTransformerFactory delegate;
+
+ public LazyBytesTransformerFactory(@Inject Provider<BytesTransformerFactory> delegateProvider) {
+ this.delegateProvider = delegateProvider;
+ }
+
+ @Override
+ public BytesEncryptor encryptor() {
+ return ensureInit().encryptor();
+ }
+
+ @Override
+ public BytesDecryptor decryptor() {
+ return ensureInit().decryptor();
+ }
+
+ protected BytesTransformerFactory ensureInit() {
+
+ if (delegate == null) {
+ synchronized (this) {
+ if (delegate == null) {
+ delegate = delegateProvider.get();
+ }
+ }
+ }
+
+ return delegate;
+ }
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/3d96be62/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/transformer/value/LazyValueTransformerFactory.java
----------------------------------------------------------------------
diff --git a/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/transformer/value/LazyValueTransformerFactory.java b/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/transformer/value/LazyValueTransformerFactory.java
new file mode 100644
index 0000000..62c4529
--- /dev/null
+++ b/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/transformer/value/LazyValueTransformerFactory.java
@@ -0,0 +1,64 @@
+/*****************************************************************
+ * 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.transformer.value;
+
+import org.apache.cayenne.di.Inject;
+import org.apache.cayenne.di.Provider;
+import org.apache.cayenne.map.DbAttribute;
+
+/**
+ * A {@link ValueTransformerFactory} that allows to defer its initialization and hence allows Cayenne stack
+ * to operate without cryto keys over a subset of entities that do not require encryption. Useful e.g. when the
+ * crypto keys are supplied at a later point after startup.
+ *
+ * @since 4.0
+ */
+public class LazyValueTransformerFactory implements ValueTransformerFactory {
+
+ private Provider<ValueTransformerFactory> delegateProvider;
+ private volatile ValueTransformerFactory delegate;
+
+ public LazyValueTransformerFactory(@Inject Provider<ValueTransformerFactory> delegateProvider) {
+ this.delegateProvider = delegateProvider;
+ }
+
+ @Override
+ public ValueEncryptor encryptor(DbAttribute a) {
+ return ensureInit().encryptor(a);
+ }
+
+ @Override
+ public ValueDecryptor decryptor(DbAttribute a) {
+ return ensureInit().decryptor(a);
+ }
+
+ protected ValueTransformerFactory ensureInit() {
+
+ if (delegate == null) {
+ synchronized (this) {
+ if (delegate == null) {
+ delegate = delegateProvider.get();
+ }
+ }
+ }
+
+ return delegate;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/3d96be62/docs/doc/src/main/resources/RELEASE-NOTES.txt
----------------------------------------------------------------------
diff --git a/docs/doc/src/main/resources/RELEASE-NOTES.txt b/docs/doc/src/main/resources/RELEASE-NOTES.txt
index cd3d28a..e65f57c 100644
--- a/docs/doc/src/main/resources/RELEASE-NOTES.txt
+++ b/docs/doc/src/main/resources/RELEASE-NOTES.txt
@@ -27,7 +27,8 @@ CAY-2090 Untangle HttpRemoteService from ServiceContext thread local setup
CAY-2100 Add supporting generated keys for PostgreSQL
CAY-2102 EJBQL: db: path not supported in select columns
CAY-2103 cayenne-crypto: support for mapping non-String and non-binary types
-CAY-2106: cayenne-crypto: allow DI contribution of type converters inside ValueTransformerFactory
+CAY-2106 cayenne-crypto: allow DI contribution of type converters inside ValueTransformerFactory
+CAY-2107 cayenne-crypto: Lazy initialization of crypto subsystem
Bug Fixes:
[3/4] cayenne git commit: CAY-2107 cayenne-crypto: Lazy
initialization of crypto subsystem
Posted by aa...@apache.org.
CAY-2107 cayenne-crypto: Lazy initialization of crypto subsystem
Project: http://git-wip-us.apache.org/repos/asf/cayenne/repo
Commit: http://git-wip-us.apache.org/repos/asf/cayenne/commit/37c7e0fb
Tree: http://git-wip-us.apache.org/repos/asf/cayenne/tree/37c7e0fb
Diff: http://git-wip-us.apache.org/repos/asf/cayenne/diff/37c7e0fb
Branch: refs/heads/master
Commit: 37c7e0fbd382456acb361c1f49fe7fbc3ee3323d
Parents: 023d5f1
Author: Andrus Adamchik <an...@objectstyle.com>
Authored: Thu Aug 25 12:45:36 2016 +0300
Committer: Andrus Adamchik <an...@objectstyle.com>
Committed: Thu Aug 25 12:45:36 2016 +0300
----------------------------------------------------------------------
.../cayenne/crypto/Runtime_AES128_Base.java | 39 ++++--
.../cayenne/crypto/Runtime_LazyInit_IT.java | 139 +++++++++++++++++++
.../org/apache/cayenne/crypto/db/Table4.java | 9 ++
.../apache/cayenne/crypto/db/auto/_Table4.java | 36 +++++
.../src/test/resources/datamap.map.xml | 9 ++
5 files changed, 220 insertions(+), 12 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cayenne/blob/37c7e0fb/cayenne-crypto/src/test/java/org/apache/cayenne/crypto/Runtime_AES128_Base.java
----------------------------------------------------------------------
diff --git a/cayenne-crypto/src/test/java/org/apache/cayenne/crypto/Runtime_AES128_Base.java b/cayenne-crypto/src/test/java/org/apache/cayenne/crypto/Runtime_AES128_Base.java
index 8703c4a..4b5774c 100644
--- a/cayenne-crypto/src/test/java/org/apache/cayenne/crypto/Runtime_AES128_Base.java
+++ b/cayenne-crypto/src/test/java/org/apache/cayenne/crypto/Runtime_AES128_Base.java
@@ -25,29 +25,24 @@ import org.apache.cayenne.test.jdbc.DBHelper;
import org.apache.cayenne.test.jdbc.TableHelper;
import java.net.URL;
+import java.sql.SQLException;
public class Runtime_AES128_Base {
protected ServerRuntime runtime;
protected TableHelper table1;
protected TableHelper table2;
+ protected TableHelper table4;
protected void setUp(boolean compress) throws Exception {
- URL keyStoreUrl = JceksKeySourceTest.class.getResource(JceksKeySourceTest.KS1_JCEKS);
-
- CryptoModuleBuilder builder = new CryptoModuleBuilder().keyStore(keyStoreUrl, JceksKeySourceTest.TEST_KEY_PASS,
- "k3");
-
- if (compress) {
- builder.compress();
- }
-
- Module crypto = builder.build();
+ Module crypto = createCryptoModule(compress);
+ this.runtime = createRuntime(crypto);
- this.runtime = new ServerRuntime("cayenne-crypto.xml", crypto);
+ setupTestTables(new DBHelper(runtime.getDataSource(null)));
+ }
- DBHelper dbHelper = new DBHelper(runtime.getDataSource(null));
+ protected void setupTestTables(DBHelper dbHelper) throws SQLException {
this.table2 = new TableHelper(dbHelper, "TABLE2").setColumns("ID", "PLAIN_BYTES", "CRYPTO_BYTES");
table2.deleteAll();
@@ -55,6 +50,26 @@ public class Runtime_AES128_Base {
this.table1 = new TableHelper(dbHelper, "TABLE1").setColumns("ID", "PLAIN_STRING", "CRYPTO_STRING",
"PLAIN_INT", "CRYPTO_INT");
table1.deleteAll();
+
+ this.table4 = new TableHelper(dbHelper, "TABLE4").setColumns("ID", "PLAIN_STRING", "PLAIN_INT");
+ table4.deleteAll();
+ }
+
+ protected ServerRuntime createRuntime(Module crypto) {
+ return new ServerRuntime("cayenne-crypto.xml", crypto);
+ }
+
+ protected Module createCryptoModule(boolean compress) {
+ URL keyStoreUrl = JceksKeySourceTest.class.getResource(JceksKeySourceTest.KS1_JCEKS);
+
+ CryptoModuleBuilder builder = new CryptoModuleBuilder().keyStore(keyStoreUrl, JceksKeySourceTest.TEST_KEY_PASS,
+ "k3");
+
+ if (compress) {
+ builder.compress();
+ }
+
+ return builder.build();
}
}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/37c7e0fb/cayenne-crypto/src/test/java/org/apache/cayenne/crypto/Runtime_LazyInit_IT.java
----------------------------------------------------------------------
diff --git a/cayenne-crypto/src/test/java/org/apache/cayenne/crypto/Runtime_LazyInit_IT.java b/cayenne-crypto/src/test/java/org/apache/cayenne/crypto/Runtime_LazyInit_IT.java
new file mode 100644
index 0000000..bf79489
--- /dev/null
+++ b/cayenne-crypto/src/test/java/org/apache/cayenne/crypto/Runtime_LazyInit_IT.java
@@ -0,0 +1,139 @@
+/*****************************************************************
+ * 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;
+
+import org.apache.cayenne.CayenneRuntimeException;
+import org.apache.cayenne.configuration.server.ServerRuntime;
+import org.apache.cayenne.crypto.db.Table1;
+import org.apache.cayenne.crypto.db.Table4;
+import org.apache.cayenne.crypto.key.KeySource;
+import org.apache.cayenne.di.Binder;
+import org.apache.cayenne.di.Inject;
+import org.apache.cayenne.di.Module;
+import org.apache.cayenne.query.ObjectSelect;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.security.Key;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.fail;
+
+public class Runtime_LazyInit_IT extends Runtime_AES128_Base {
+
+
+ protected static boolean UNLOCKED;
+
+ @Before
+ public void before() throws Exception {
+ setUp(false);
+ UNLOCKED = false;
+ }
+
+ @Override
+ protected ServerRuntime createRuntime(final Module crypto) {
+ Module cryptoWrapper = new Module() {
+ @Override
+ public void configure(Binder binder) {
+
+ crypto.configure(binder);
+
+ binder.decorate(KeySource.class).after(LockingKeySourceDecorator.class);
+ }
+ };
+
+ return super.createRuntime(cryptoWrapper);
+ }
+
+ @Test
+ public void testCryptoLocked() {
+
+ assertFalse(UNLOCKED);
+
+ Table4 t4 = runtime.newContext().newObject(Table4.class);
+ t4.setPlainInt(56);
+ t4.setPlainString("XX");
+ t4.getObjectContext().commitChanges();
+
+ assertEquals(t4.getObjectId(), ObjectSelect.query(Table4.class).selectOne(runtime.newContext()).getObjectId());
+ }
+
+ @Test
+ public void testCryptoLocked_Unlocked() {
+
+
+ assertFalse(UNLOCKED);
+
+ try {
+ Table1 t1 = runtime.newContext().newObject(Table1.class);
+ t1.setPlainInt(56);
+ t1.setCryptoInt(77);
+ t1.setPlainString("XX");
+ t1.setCryptoString("YY");
+ t1.getObjectContext().commitChanges();
+
+ fail("Must have thrown on crypto access");
+ } catch (CayenneRuntimeException e) {
+ // expected
+ }
+
+ UNLOCKED = true;
+
+ Table1 t1 = runtime.newContext().newObject(Table1.class);
+ t1.setPlainInt(56);
+ t1.setCryptoInt(77);
+ t1.setPlainString("XX");
+ t1.setCryptoString("YY");
+ t1.getObjectContext().commitChanges();
+
+ assertEquals(t1.getObjectId(), ObjectSelect.query(Table1.class).selectOne(runtime.newContext()).getObjectId());
+
+ }
+
+
+ public static class LockingKeySourceDecorator implements KeySource {
+
+ private KeySource keySource;
+
+ public LockingKeySourceDecorator(@Inject KeySource keySource) {
+ this.keySource = keySource;
+ }
+
+ @Override
+ public Key getKey(String alias) {
+ return ensureKeySource().getKey(alias);
+ }
+
+ @Override
+ public String getDefaultKeyAlias() {
+ return ensureKeySource().getDefaultKeyAlias();
+ }
+
+ private KeySource ensureKeySource() {
+
+ if (!UNLOCKED) {
+ throw new IllegalStateException("Crypto is locked");
+ }
+
+ return keySource;
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/37c7e0fb/cayenne-crypto/src/test/java/org/apache/cayenne/crypto/db/Table4.java
----------------------------------------------------------------------
diff --git a/cayenne-crypto/src/test/java/org/apache/cayenne/crypto/db/Table4.java b/cayenne-crypto/src/test/java/org/apache/cayenne/crypto/db/Table4.java
new file mode 100644
index 0000000..89ffe67
--- /dev/null
+++ b/cayenne-crypto/src/test/java/org/apache/cayenne/crypto/db/Table4.java
@@ -0,0 +1,9 @@
+package org.apache.cayenne.crypto.db;
+
+import org.apache.cayenne.crypto.db.auto._Table4;
+
+public class Table4 extends _Table4 {
+
+ private static final long serialVersionUID = 1L;
+
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/37c7e0fb/cayenne-crypto/src/test/java/org/apache/cayenne/crypto/db/auto/_Table4.java
----------------------------------------------------------------------
diff --git a/cayenne-crypto/src/test/java/org/apache/cayenne/crypto/db/auto/_Table4.java b/cayenne-crypto/src/test/java/org/apache/cayenne/crypto/db/auto/_Table4.java
new file mode 100644
index 0000000..3f825bc
--- /dev/null
+++ b/cayenne-crypto/src/test/java/org/apache/cayenne/crypto/db/auto/_Table4.java
@@ -0,0 +1,36 @@
+package org.apache.cayenne.crypto.db.auto;
+
+import org.apache.cayenne.CayenneDataObject;
+import org.apache.cayenne.exp.Property;
+
+/**
+ * Class _Table4 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 _Table4 extends CayenneDataObject {
+
+ private static final long serialVersionUID = 1L;
+
+ public static final String ID_PK_COLUMN = "ID";
+
+ public static final Property<Integer> PLAIN_INT = new Property<Integer>("plainInt");
+ public static final Property<String> PLAIN_STRING = new Property<String>("plainString");
+
+ public void setPlainInt(int plainInt) {
+ writeProperty("plainInt", plainInt);
+ }
+ public int getPlainInt() {
+ Object value = readProperty("plainInt");
+ return (value != null) ? (Integer) value : 0;
+ }
+
+ public void setPlainString(String plainString) {
+ writeProperty("plainString", plainString);
+ }
+ public String getPlainString() {
+ return (String)readProperty("plainString");
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/37c7e0fb/cayenne-crypto/src/test/resources/datamap.map.xml
----------------------------------------------------------------------
diff --git a/cayenne-crypto/src/test/resources/datamap.map.xml b/cayenne-crypto/src/test/resources/datamap.map.xml
index 2ea6a80..b71de41 100644
--- a/cayenne-crypto/src/test/resources/datamap.map.xml
+++ b/cayenne-crypto/src/test/resources/datamap.map.xml
@@ -20,6 +20,11 @@
<db-attribute name="CRYPTO_BYTES" type="VARBINARY"/>
<db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
</db-entity>
+ <db-entity name="TABLE4">
+ <db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
+ <db-attribute name="PLAIN_INT" type="INTEGER"/>
+ <db-attribute name="PLAIN_STRING" type="VARCHAR" length="200"/>
+ </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"/>
@@ -33,4 +38,8 @@
<obj-entity name="Table3" className="org.apache.cayenne.crypto.db.Table3" dbEntityName="TABLE3">
<obj-attribute name="cryptoString" type="java.lang.String" db-attribute-path="CRYPTO_BYTES"/>
</obj-entity>
+ <obj-entity name="Table4" className="org.apache.cayenne.crypto.db.Table4" dbEntityName="TABLE4">
+ <obj-attribute name="plainInt" type="int" db-attribute-path="PLAIN_INT"/>
+ <obj-attribute name="plainString" type="java.lang.String" db-attribute-path="PLAIN_STRING"/>
+ </obj-entity>
</data-map>
[4/4] cayenne git commit: CAY-2108 cayenne-di: StackOverflow for
decorator that takes Provider of the delegate
Posted by aa...@apache.org.
CAY-2108 cayenne-di: StackOverflow for decorator that takes Provider of the delegate
Project: http://git-wip-us.apache.org/repos/asf/cayenne/repo
Commit: http://git-wip-us.apache.org/repos/asf/cayenne/commit/aecf9aa3
Tree: http://git-wip-us.apache.org/repos/asf/cayenne/tree/aecf9aa3
Diff: http://git-wip-us.apache.org/repos/asf/cayenne/diff/aecf9aa3
Branch: refs/heads/master
Commit: aecf9aa318484ecc1e349c00f717add94accb9f8
Parents: 37c7e0f
Author: Andrus Adamchik <an...@objectstyle.com>
Authored: Thu Aug 25 12:46:26 2016 +0300
Committer: Andrus Adamchik <an...@objectstyle.com>
Committed: Thu Aug 25 12:46:26 2016 +0300
----------------------------------------------------------------------
docs/doc/src/main/resources/RELEASE-NOTES.txt | 1 +
1 file changed, 1 insertion(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cayenne/blob/aecf9aa3/docs/doc/src/main/resources/RELEASE-NOTES.txt
----------------------------------------------------------------------
diff --git a/docs/doc/src/main/resources/RELEASE-NOTES.txt b/docs/doc/src/main/resources/RELEASE-NOTES.txt
index e65f57c..1d302c8 100644
--- a/docs/doc/src/main/resources/RELEASE-NOTES.txt
+++ b/docs/doc/src/main/resources/RELEASE-NOTES.txt
@@ -45,6 +45,7 @@ CAY-2089 HTTP connections aren't always closed in new ROP implementation
CAY-2097 NullPointerException while updating relationships for entities with vertical inheritance
CAY-2101 DataContext.currentSnapshot() doesn't set snapshot entity name
CAY-2105 Add missing elements to the reverseEngineering.xsd
+CAY-2108 cayenne-di: StackOverflow for decorator that takes Provider of the delegate
----------------------------------
Release: 4.0.M3
[2/4] cayenne git commit: CAY-2108 cayenne-di: StackOverflow for
decorator that takes Provider of the delegate
Posted by aa...@apache.org.
CAY-2108 cayenne-di: StackOverflow for decorator that takes Provider of the delegate
Project: http://git-wip-us.apache.org/repos/asf/cayenne/repo
Commit: http://git-wip-us.apache.org/repos/asf/cayenne/commit/023d5f18
Tree: http://git-wip-us.apache.org/repos/asf/cayenne/tree/023d5f18
Diff: http://git-wip-us.apache.org/repos/asf/cayenne/diff/023d5f18
Branch: refs/heads/master
Commit: 023d5f18f8fb97f66b23bc13accf015c6d4f11b4
Parents: 3d96be6
Author: Andrus Adamchik <an...@objectstyle.com>
Authored: Thu Aug 25 12:38:06 2016 +0300
Committer: Andrus Adamchik <an...@objectstyle.com>
Committed: Thu Aug 25 12:43:59 2016 +0300
----------------------------------------------------------------------
.../ConstructorInjectingDecoratorProvider.java | 21 +++++++++--
.../di/spi/FieldInjectingDecoratorProvider.java | 23 ++++++++++--
.../di/mock/MockInterface1_Decorator4.java | 36 ++++++++++++++++++
.../di/mock/MockInterface1_Decorator5.java | 33 +++++++++++++++++
.../di/spi/DefaultInjectorDecorationTest.java | 39 ++++++++++++++++++++
5 files changed, 146 insertions(+), 6 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cayenne/blob/023d5f18/cayenne-di/src/main/java/org/apache/cayenne/di/spi/ConstructorInjectingDecoratorProvider.java
----------------------------------------------------------------------
diff --git a/cayenne-di/src/main/java/org/apache/cayenne/di/spi/ConstructorInjectingDecoratorProvider.java b/cayenne-di/src/main/java/org/apache/cayenne/di/spi/ConstructorInjectingDecoratorProvider.java
index 4ad974f..a235847 100644
--- a/cayenne-di/src/main/java/org/apache/cayenne/di/spi/ConstructorInjectingDecoratorProvider.java
+++ b/cayenne-di/src/main/java/org/apache/cayenne/di/spi/ConstructorInjectingDecoratorProvider.java
@@ -18,11 +18,11 @@
****************************************************************/
package org.apache.cayenne.di.spi;
-import java.lang.reflect.Type;
-
import org.apache.cayenne.di.DIRuntimeException;
import org.apache.cayenne.di.Provider;
+import java.lang.reflect.Type;
+
/**
* @since 4.0
*/
@@ -43,7 +43,22 @@ public class ConstructorInjectingDecoratorProvider<T> implements DecoratorProvid
@Override
protected Object value(Class<?> parameter, Type genericType, String bindingName, InjectionStack stack) {
- if (parameter.isAssignableFrom(implementation)) {
+ // delegate (possibly) injected as Provider
+ if (Provider.class.equals(parameter)) {
+
+ Class<?> objectClass = DIUtil.parameterClass(genericType);
+
+ if (objectClass == null) {
+ throw new DIRuntimeException("Constructor provider parameter %s must be "
+ + "parameterized to be usable for injection", parameter.getName());
+ }
+
+ if(objectClass.isAssignableFrom(implementation)) {
+ return undecorated;
+ }
+ }
+ // delegate injected as value
+ else if (parameter.isAssignableFrom(implementation)) {
return undecorated.get();
}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/023d5f18/cayenne-di/src/main/java/org/apache/cayenne/di/spi/FieldInjectingDecoratorProvider.java
----------------------------------------------------------------------
diff --git a/cayenne-di/src/main/java/org/apache/cayenne/di/spi/FieldInjectingDecoratorProvider.java b/cayenne-di/src/main/java/org/apache/cayenne/di/spi/FieldInjectingDecoratorProvider.java
index e6c072b..6cbbad0 100644
--- a/cayenne-di/src/main/java/org/apache/cayenne/di/spi/FieldInjectingDecoratorProvider.java
+++ b/cayenne-di/src/main/java/org/apache/cayenne/di/spi/FieldInjectingDecoratorProvider.java
@@ -18,11 +18,11 @@
****************************************************************/
package org.apache.cayenne.di.spi;
-import java.lang.reflect.Field;
-
import org.apache.cayenne.di.DIRuntimeException;
import org.apache.cayenne.di.Provider;
+import java.lang.reflect.Field;
+
/**
* @since 4.0
*/
@@ -45,7 +45,24 @@ class FieldInjectingDecoratorProvider<T> implements DecoratorProvider<T> {
@Override
protected Object value(Field field, String bindingName) {
- if (field.getType().isAssignableFrom(implementation)) {
+ Class<?> fieldType = field.getType();
+
+ // delegate (possibly) injected as Provider
+ if (Provider.class.equals(fieldType)) {
+
+ Class<?> objectClass = DIUtil.parameterClass(field.getGenericType());
+
+ if (objectClass == null) {
+ throw new DIRuntimeException("Provider field %s.%s of type %s must be "
+ + "parameterized to be usable for injection", field.getDeclaringClass().getName(),
+ field.getName(), fieldType.getName());
+ }
+
+ if(objectClass.isAssignableFrom(implementation)) {
+ return undecorated;
+ }
+ }
+ else if (fieldType.isAssignableFrom(implementation)) {
return undecorated.get();
}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/023d5f18/cayenne-di/src/test/java/org/apache/cayenne/di/mock/MockInterface1_Decorator4.java
----------------------------------------------------------------------
diff --git a/cayenne-di/src/test/java/org/apache/cayenne/di/mock/MockInterface1_Decorator4.java b/cayenne-di/src/test/java/org/apache/cayenne/di/mock/MockInterface1_Decorator4.java
new file mode 100644
index 0000000..d30f358
--- /dev/null
+++ b/cayenne-di/src/test/java/org/apache/cayenne/di/mock/MockInterface1_Decorator4.java
@@ -0,0 +1,36 @@
+/*****************************************************************
+ * 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.di.mock;
+
+import org.apache.cayenne.di.Inject;
+import org.apache.cayenne.di.Provider;
+
+public class MockInterface1_Decorator4 implements MockInterface1 {
+
+ private Provider<MockInterface1> delegate;
+
+ public MockInterface1_Decorator4(@Inject Provider<MockInterface1> delegate) {
+ this.delegate = delegate;
+ }
+
+ @Override
+ public String getName() {
+ return "[4" + delegate.get().getName() + "4]";
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/cayenne/blob/023d5f18/cayenne-di/src/test/java/org/apache/cayenne/di/mock/MockInterface1_Decorator5.java
----------------------------------------------------------------------
diff --git a/cayenne-di/src/test/java/org/apache/cayenne/di/mock/MockInterface1_Decorator5.java b/cayenne-di/src/test/java/org/apache/cayenne/di/mock/MockInterface1_Decorator5.java
new file mode 100644
index 0000000..0b3cd35
--- /dev/null
+++ b/cayenne-di/src/test/java/org/apache/cayenne/di/mock/MockInterface1_Decorator5.java
@@ -0,0 +1,33 @@
+/*****************************************************************
+ * 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.di.mock;
+
+import org.apache.cayenne.di.Inject;
+import org.apache.cayenne.di.Provider;
+
+public class MockInterface1_Decorator5 implements MockInterface1 {
+
+ @Inject
+ private Provider<MockInterface1> delegate;
+
+ @Override
+ public String getName() {
+ return "[5" + delegate.get().getName() + "5]";
+ }
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/023d5f18/cayenne-di/src/test/java/org/apache/cayenne/di/spi/DefaultInjectorDecorationTest.java
----------------------------------------------------------------------
diff --git a/cayenne-di/src/test/java/org/apache/cayenne/di/spi/DefaultInjectorDecorationTest.java b/cayenne-di/src/test/java/org/apache/cayenne/di/spi/DefaultInjectorDecorationTest.java
index 266ade2..dfe34ff 100644
--- a/cayenne-di/src/test/java/org/apache/cayenne/di/spi/DefaultInjectorDecorationTest.java
+++ b/cayenne-di/src/test/java/org/apache/cayenne/di/spi/DefaultInjectorDecorationTest.java
@@ -25,6 +25,8 @@ import org.apache.cayenne.di.mock.MockInterface1;
import org.apache.cayenne.di.mock.MockInterface1_Decorator1;
import org.apache.cayenne.di.mock.MockInterface1_Decorator2;
import org.apache.cayenne.di.mock.MockInterface1_Decorator3;
+import org.apache.cayenne.di.mock.MockInterface1_Decorator4;
+import org.apache.cayenne.di.mock.MockInterface1_Decorator5;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
@@ -92,4 +94,41 @@ public class DefaultInjectorDecorationTest {
assertEquals("<[{MyName}]>", service.getName());
}
+ @Test
+ public void testSingleDecorator_Provider_ConstructorInjection() {
+
+ Module module = new Module() {
+
+ @Override
+ public void configure(Binder binder) {
+ binder.bind(MockInterface1.class).to(MockImplementation1.class);
+ binder.decorate(MockInterface1.class).before(MockInterface1_Decorator4.class);
+ }
+ };
+
+ DefaultInjector injector = new DefaultInjector(module);
+
+ MockInterface1 service = injector.getInstance(MockInterface1.class);
+ assertNotNull(service);
+ assertEquals("[4MyName4]", service.getName());
+ }
+
+ @Test
+ public void testSingleDecorator_Provider_FieldInjection() {
+
+ Module module = new Module() {
+
+ @Override
+ public void configure(Binder binder) {
+ binder.bind(MockInterface1.class).to(MockImplementation1.class);
+ binder.decorate(MockInterface1.class).before(MockInterface1_Decorator5.class);
+ }
+ };
+
+ DefaultInjector injector = new DefaultInjector(module);
+
+ MockInterface1 service = injector.getInstance(MockInterface1.class);
+ assertNotNull(service);
+ assertEquals("[5MyName5]", service.getName());
+ }
}