This is an automated email from the ASF dual-hosted git repository. ntimofeev pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/cayenne.git
commit 11ea4681a14c743ce9294aa4bb78575cf472e1f4 Author: Mikhail Dzianishchyts <mikhail.dzianishch...@gmail.com> AuthorDate: Wed Nov 16 12:31:09 2022 +0300 update CryptoModuleExtender --- .../org/apache/cayenne/crypto/CryptoModule.java | 176 +++++--------- .../cayenne/crypto/CryptoModuleExtender.java | 253 +++++++-------------- ...lderTest.java => CryptoModuleExtenderTest.java} | 7 +- .../apache/cayenne/crypto/Runtime_AES128_Base.java | 24 +- 4 files changed, 158 insertions(+), 302 deletions(-) diff --git a/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/CryptoModule.java b/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/CryptoModule.java index 631b7b74e..d4e8de7a5 100644 --- a/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/CryptoModule.java +++ b/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/CryptoModule.java @@ -18,27 +18,13 @@ */ package org.apache.cayenne.crypto; -import java.math.BigDecimal; -import java.math.BigInteger; -import java.sql.Types; -import java.time.Duration; -import java.time.LocalDate; -import java.time.LocalDateTime; -import java.time.LocalTime; -import java.time.Period; -import java.util.Date; - import org.apache.cayenne.access.jdbc.reader.RowReaderFactory; import org.apache.cayenne.access.translator.batch.BatchTranslatorFactory; import org.apache.cayenne.configuration.DataMapLoader; import org.apache.cayenne.crypto.batch.CryptoBatchTranslatorFactoryDecorator; -import org.apache.cayenne.crypto.cipher.CipherFactory; import org.apache.cayenne.crypto.cipher.DefaultCipherFactory; import org.apache.cayenne.crypto.key.JceksKeySource; -import org.apache.cayenne.crypto.key.KeySource; -import org.apache.cayenne.crypto.map.ColumnMapper; import org.apache.cayenne.crypto.map.CryptoDataMapLoader; -import org.apache.cayenne.crypto.map.PatternColumnMapper; import org.apache.cayenne.crypto.reader.CryptoRowReaderFactoryDecorator; import org.apache.cayenne.crypto.transformer.DefaultTransformerFactory; import org.apache.cayenne.crypto.transformer.TransformerFactory; @@ -50,7 +36,6 @@ import org.apache.cayenne.crypto.transformer.value.BigDecimalConverter; import org.apache.cayenne.crypto.transformer.value.BigIntegerConverter; import org.apache.cayenne.crypto.transformer.value.BooleanConverter; import org.apache.cayenne.crypto.transformer.value.ByteConverter; -import org.apache.cayenne.crypto.transformer.value.BytesConverter; import org.apache.cayenne.crypto.transformer.value.BytesToBytesConverter; import org.apache.cayenne.crypto.transformer.value.DefaultValueTransformerFactory; import org.apache.cayenne.crypto.transformer.value.DoubleConverter; @@ -68,9 +53,18 @@ import org.apache.cayenne.crypto.transformer.value.Utf8StringConverter; import org.apache.cayenne.crypto.transformer.value.UtilDateConverter; import org.apache.cayenne.crypto.transformer.value.ValueTransformerFactory; import org.apache.cayenne.di.Binder; -import org.apache.cayenne.di.MapBuilder; import org.apache.cayenne.di.Module; +import java.math.BigDecimal; +import java.math.BigInteger; +import java.sql.Types; +import java.time.Duration; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.time.Period; +import java.util.Date; + /** * Contains cryptography extensions for Cayenne. * @@ -82,65 +76,75 @@ public class CryptoModule implements Module { private static final String DEFAULT_CIPHER_MODE = "CBC"; private static final String DEFAULT_CIPHER_PADDING = "PKCS5Padding"; // same as default keystore password in java... + // credentials are stored as char[] to potentially allow wiping them clean in memory... private static final char[] DEFAULT_KEY_PASSWORD = "changeit".toCharArray(); private static final String DEFAULT_COLUMN_MAPPER_PATTERN = "^CRYPTO_"; /** - * Returns a new extender that helps to build a custom module that provides required configuration for {@link CryptoModule} + * Returns a new extender that helps to build a custom module that provides required configuration for + * {@link CryptoModule} * as well as custom strategies overriding the defaults defined here. * * @return a new extender that helps to build a custom module that provides required configuration for {@link CryptoModule}. + * @since 5.0 */ - public static CryptoModuleExtender extend() { - return new CryptoModuleExtender(); - } - - static MapBuilder<String> contributeProperties(Binder binder) { - return binder.bindMap(String.class, CryptoConstants.PROPERTIES_MAP); - } - - static MapBuilder<char[]> contributeCredentials(Binder binder) { - return binder.bindMap(char[].class, CryptoConstants.CREDENTIALS_MAP); - } - - @SuppressWarnings("unchecked") - static MapBuilder<BytesConverter<?>> contributeDbToByteConverters(Binder binder) { - MapBuilder mapBuilder = binder.bindMap(BytesConverter.class, DefaultValueTransformerFactory.DB_TO_BYTE_CONVERTERS_KEY); - return (MapBuilder<BytesConverter<?>>) mapBuilder; - } - - @SuppressWarnings("unchecked") - static MapBuilder<BytesConverter<?>> contributeObjectToByteConverters(Binder binder) { - MapBuilder mapBuilder = binder.bindMap(BytesConverter.class, DefaultValueTransformerFactory.OBJECT_TO_BYTE_CONVERTERS_KEY); - return (MapBuilder<BytesConverter<?>>) mapBuilder; + public static CryptoModuleExtender extend(Binder binder) { + return new CryptoModuleExtender(binder); } @Override public void configure(Binder binder) { + extend(binder) + .cipherAlgorithm(DEFAULT_CIPHER_ALGORITHM) + .cipherMode(DEFAULT_CIPHER_MODE) + .cipherPadding(DEFAULT_CIPHER_PADDING) + .cipherFactory(DefaultCipherFactory.class) + + .keyStore((String) null, DEFAULT_KEY_PASSWORD, null) + .keySource(JceksKeySource.class) + + .valueTransformerFactory(DefaultValueTransformerFactory.class) + .bytesTransformerFactory(DefaultBytesTransformerFactory.class) + + .columnMapper(DEFAULT_COLUMN_MAPPER_PATTERN) + + .objectToBytesConverter("byte[]", BytesToBytesConverter.INSTANCE) + .objectToBytesConverter(String.class, Utf8StringConverter.INSTANCE) + + .objectToBytesConverter(Double.class, DoubleConverter.INSTANCE) + .objectToBytesConverter(Float.class, FloatConverter.INSTANCE) + .objectToBytesConverter(Long.class, LongConverter.INSTANCE) + .objectToBytesConverter(Integer.class, IntegerConverter.INSTANCE) + .objectToBytesConverter(Short.class, ShortConverter.INSTANCE) + .objectToBytesConverter(Byte.class, ByteConverter.INSTANCE) + .objectToBytesConverter(Boolean.class, BooleanConverter.INSTANCE) + + .objectToBytesConverter(BigInteger.class, BigIntegerConverter.INSTANCE) + .objectToBytesConverter(BigDecimal.class, BigDecimalConverter.INSTANCE) + .objectToBytesConverter(Date.class, UtilDateConverter.INSTANCE) + .objectToBytesConverter(LocalDate.class, LocalDateConverter.INSTANCE) + .objectToBytesConverter(LocalTime.class, LocalTimeConverter.INSTANCE) + .objectToBytesConverter(LocalDateTime.class, LocalDateTimeConverter.INSTANCE) + .objectToBytesConverter(Duration.class, DurationConverter.INSTANCE) + .objectToBytesConverter(Period.class, PeriodConverter.INSTANCE) + + .dbToBytesConverter(Types.BINARY, BytesToBytesConverter.INSTANCE) + .dbToBytesConverter(Types.BLOB, BytesToBytesConverter.INSTANCE) + .dbToBytesConverter(Types.VARBINARY, BytesToBytesConverter.INSTANCE) + .dbToBytesConverter(Types.LONGVARBINARY, BytesToBytesConverter.INSTANCE) + + .dbToBytesConverter(Types.CHAR, Base64StringConverter.INSTANCE) + .dbToBytesConverter(Types.NCHAR, Base64StringConverter.INSTANCE) + .dbToBytesConverter(Types.CLOB, Base64StringConverter.INSTANCE) + .dbToBytesConverter(Types.NCLOB, Base64StringConverter.INSTANCE) + .dbToBytesConverter(Types.LONGVARCHAR, Base64StringConverter.INSTANCE) + .dbToBytesConverter(Types.LONGNVARCHAR, Base64StringConverter.INSTANCE) + .dbToBytesConverter(Types.VARCHAR, Base64StringConverter.INSTANCE) + .dbToBytesConverter(Types.NVARCHAR, Base64StringConverter.INSTANCE); - contributeProperties(binder) - .put(CryptoConstants.CIPHER_ALGORITHM, DEFAULT_CIPHER_ALGORITHM) - .put(CryptoConstants.CIPHER_MODE, DEFAULT_CIPHER_MODE) - .put(CryptoConstants.CIPHER_PADDING, DEFAULT_CIPHER_PADDING); - - // credentials are stored as char[] to potentially allow wiping them clean in memory... - contributeCredentials(binder).put(CryptoConstants.KEY_PASSWORD, DEFAULT_KEY_PASSWORD); - - binder.bind(CipherFactory.class).to(DefaultCipherFactory.class); binder.bind(TransformerFactory.class).to(DefaultTransformerFactory.class); - binder.bind(ValueTransformerFactory.class).to(DefaultValueTransformerFactory.class); - - MapBuilder<BytesConverter<?>> dbToBytesBinder = contributeDbToByteConverters(binder); - contributeDefaultDbConverters(dbToBytesBinder); - - MapBuilder<BytesConverter<?>> objectToBytesBinder = contributeObjectToByteConverters(binder); - contributeDefaultObjectConverters(objectToBytesBinder); - binder.bind(BytesTransformerFactory.class).to(DefaultBytesTransformerFactory.class); - binder.bind(KeySource.class).to(JceksKeySource.class); - binder.bind(ColumnMapper.class).toInstance(new PatternColumnMapper(DEFAULT_COLUMN_MAPPER_PATTERN)); binder.decorate(DataMapLoader.class).before(CryptoDataMapLoader.class); - binder.decorate(BatchTranslatorFactory.class).before(CryptoBatchTranslatorFactoryDecorator.class); binder.bind(RowReaderFactory.class).to(CryptoRowReaderFactoryDecorator.class); @@ -149,58 +153,4 @@ public class CryptoModule implements Module { binder.decorate(ValueTransformerFactory.class).after(LazyValueTransformerFactory.class); binder.decorate(BytesTransformerFactory.class).after(LazyBytesTransformerFactory.class); } - - private static void contributeDefaultDbConverters(MapBuilder<BytesConverter<?>> mapBuilder) { - - mapBuilder.put(String.valueOf(Types.BINARY), BytesToBytesConverter.INSTANCE); - mapBuilder.put(String.valueOf(Types.BLOB), BytesToBytesConverter.INSTANCE); - mapBuilder.put(String.valueOf(Types.VARBINARY), BytesToBytesConverter.INSTANCE); - mapBuilder.put(String.valueOf(Types.LONGVARBINARY), BytesToBytesConverter.INSTANCE); - - mapBuilder.put(String.valueOf(Types.CHAR), Base64StringConverter.INSTANCE); - mapBuilder.put(String.valueOf(Types.NCHAR), Base64StringConverter.INSTANCE); - mapBuilder.put(String.valueOf(Types.CLOB), Base64StringConverter.INSTANCE); - mapBuilder.put(String.valueOf(Types.NCLOB), Base64StringConverter.INSTANCE); - mapBuilder.put(String.valueOf(Types.LONGVARCHAR), Base64StringConverter.INSTANCE); - mapBuilder.put(String.valueOf(Types.LONGNVARCHAR), Base64StringConverter.INSTANCE); - mapBuilder.put(String.valueOf(Types.VARCHAR), Base64StringConverter.INSTANCE); - mapBuilder.put(String.valueOf(Types.NVARCHAR), Base64StringConverter.INSTANCE); - } - - private static void contributeDefaultObjectConverters(MapBuilder<BytesConverter<?>> mapBuilder) { - - mapBuilder.put("byte[]", BytesToBytesConverter.INSTANCE); - mapBuilder.put(String.class.getName(), Utf8StringConverter.INSTANCE); - - mapBuilder.put(Double.class.getName(), DoubleConverter.INSTANCE); - mapBuilder.put(Double.TYPE.getName(), DoubleConverter.INSTANCE); - - mapBuilder.put(Float.class.getName(), FloatConverter.INSTANCE); - mapBuilder.put(Float.TYPE.getName(), FloatConverter.INSTANCE); - - mapBuilder.put(Long.class.getName(), LongConverter.INSTANCE); - mapBuilder.put(Long.TYPE.getName(), LongConverter.INSTANCE); - - mapBuilder.put(Integer.class.getName(), IntegerConverter.INSTANCE); - mapBuilder.put(Integer.TYPE.getName(), IntegerConverter.INSTANCE); - - mapBuilder.put(Short.class.getName(), ShortConverter.INSTANCE); - mapBuilder.put(Short.TYPE.getName(), ShortConverter.INSTANCE); - - mapBuilder.put(Byte.class.getName(), ByteConverter.INSTANCE); - mapBuilder.put(Byte.TYPE.getName(), ByteConverter.INSTANCE); - - mapBuilder.put(Boolean.class.getName(), BooleanConverter.INSTANCE); - mapBuilder.put(Boolean.TYPE.getName(), BooleanConverter.INSTANCE); - - mapBuilder.put(Date.class.getName(), UtilDateConverter.INSTANCE); - mapBuilder.put(BigInteger.class.getName(), BigIntegerConverter.INSTANCE); - mapBuilder.put(BigDecimal.class.getName(), BigDecimalConverter.INSTANCE); - - mapBuilder.put(LocalDate.class.getName(), LocalDateConverter.INSTANCE); - mapBuilder.put(LocalTime.class.getName(), LocalTimeConverter.INSTANCE); - mapBuilder.put(LocalDateTime.class.getName(), LocalDateTimeConverter.INSTANCE); - mapBuilder.put(Duration.class.getName(), DurationConverter.INSTANCE); - mapBuilder.put(Period.class.getName(), PeriodConverter.INSTANCE); - } } diff --git a/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/CryptoModuleExtender.java b/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/CryptoModuleExtender.java index b3720e680..0adfb9213 100644 --- a/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/CryptoModuleExtender.java +++ b/cayenne-crypto/src/main/java/org/apache/cayenne/crypto/CryptoModuleExtender.java @@ -24,15 +24,14 @@ import org.apache.cayenne.crypto.map.ColumnMapper; import org.apache.cayenne.crypto.map.PatternColumnMapper; import org.apache.cayenne.crypto.transformer.bytes.BytesTransformerFactory; import org.apache.cayenne.crypto.transformer.value.BytesConverter; +import org.apache.cayenne.crypto.transformer.value.DefaultValueTransformerFactory; import org.apache.cayenne.crypto.transformer.value.ValueTransformerFactory; +import org.apache.cayenne.di.Binder; import org.apache.cayenne.di.MapBuilder; -import org.apache.cayenne.di.Module; import java.io.File; import java.net.MalformedURLException; import java.net.URL; -import java.util.HashMap; -import java.util.Map; import java.util.Objects; /** @@ -42,91 +41,75 @@ import java.util.Objects; */ public class CryptoModuleExtender { - private Class<? extends ValueTransformerFactory> valueTransformerFactoryType; - private Class<? extends BytesTransformerFactory> bytesTransformerFactoryType; + private final Binder binder; - private Map<String, BytesConverter<?>> extraObjectToBytes; - private Map<Integer, BytesConverter<?>> extraDbToBytes; + private MapBuilder<String> properties; + private MapBuilder<char[]> credentials; + private MapBuilder<BytesConverter<?>> dbToByteConverters; + private MapBuilder<BytesConverter<?>> objectToByteConverters; - private String columnMapperPattern; - private ColumnMapper columnMapper; - private Class<? extends ColumnMapper> columnMapperType; - - private String cipherAlgorithm; - private String cipherMode; - private Class<? extends CipherFactory> cipherFactoryType; - - private URL keyStoreUrl; - private String keyStoreUrlString; - private File keyStoreFile; - private Class<? extends KeySource> keySourceType; - private KeySource keySource; - - private String encryptionKeyAlias; - private char[] keyPassword; - - private boolean compress; - private boolean useHMAC; - - // use CryptoModule.builder() to create the builder... - protected CryptoModuleExtender() { - this.extraDbToBytes = new HashMap<>(); - this.extraObjectToBytes = new HashMap<>(); + protected CryptoModuleExtender(Binder binder) { + this.binder = binder; } public CryptoModuleExtender cipherAlgorithm(String algorithm) { - this.cipherAlgorithm = Objects.requireNonNull(algorithm); + contributeProperties(binder).put(CryptoConstants.CIPHER_ALGORITHM, algorithm); return this; } public CryptoModuleExtender cipherMode(String mode) { - this.cipherMode = Objects.requireNonNull(mode); + contributeProperties(binder).put(CryptoConstants.CIPHER_MODE, mode); + return this; + } + + public CryptoModuleExtender cipherPadding(String padding) { + contributeProperties(binder).put(CryptoConstants.CIPHER_PADDING, padding); return this; } public CryptoModuleExtender cipherFactory(Class<? extends CipherFactory> factoryType) { - this.cipherFactoryType = Objects.requireNonNull(factoryType); + binder.bind(CipherFactory.class).to(factoryType); + return this; + } + + public CryptoModuleExtender valueTransformerFactory(Class<? extends ValueTransformerFactory> factoryType) { + binder.bind(ValueTransformerFactory.class).to(factoryType); return this; } - public CryptoModuleExtender valueTransformer(Class<? extends ValueTransformerFactory> factoryType) { - this.valueTransformerFactoryType = Objects.requireNonNull(factoryType); + public CryptoModuleExtender bytesTransformerFactory(Class<? extends BytesTransformerFactory> factoryType) { + binder.bind(BytesTransformerFactory.class).to(factoryType); return this; } public <T> CryptoModuleExtender objectToBytesConverter(Class<T> objectType, BytesConverter<T> converter) { - extraObjectToBytes.put(objectType.getName(), Objects.requireNonNull(converter)); + contributeObjectToByteConverters(binder).put(objectType.getName(), Objects.requireNonNull(converter)); return this; } - public CryptoModuleExtender dbToBytesConverter(int sqlType, BytesConverter<?> converter) { - extraDbToBytes.put(sqlType, Objects.requireNonNull(converter)); + // workaround for byte[] + CryptoModuleExtender objectToBytesConverter(String objectTypeName, BytesConverter<Object> converter) { + contributeObjectToByteConverters(binder).put(objectTypeName, Objects.requireNonNull(converter)); return this; } - public CryptoModuleExtender bytesTransformer(Class<? extends BytesTransformerFactory> factoryType) { - this.bytesTransformerFactoryType = Objects.requireNonNull(factoryType); + public CryptoModuleExtender dbToBytesConverter(int sqlType, BytesConverter<?> converter) { + contributeDbToByteConverters(binder).put(String.valueOf(sqlType), Objects.requireNonNull(converter)); return this; } public CryptoModuleExtender columnMapper(Class<? extends ColumnMapper> columnMapperType) { - this.columnMapperPattern = null; - this.columnMapperType = Objects.requireNonNull(columnMapperType); - this.columnMapper = null; + binder.bind(ColumnMapper.class).to(columnMapperType); return this; } public CryptoModuleExtender columnMapper(ColumnMapper columnMapper) { - this.columnMapperPattern = null; - this.columnMapperType = null; - this.columnMapper = Objects.requireNonNull(columnMapper); + binder.bind(ColumnMapper.class).toInstance(columnMapper); return this; } public CryptoModuleExtender columnMapper(String pattern) { - this.columnMapperPattern = Objects.requireNonNull(pattern); - this.columnMapperType = null; - this.columnMapper = null; + binder.bind(ColumnMapper.class).toInstance(new PatternColumnMapper(pattern)); return this; } @@ -135,13 +118,13 @@ public class CryptoModuleExtender { * encryption by default. */ public CryptoModuleExtender encryptionKeyAlias(String encryptionKeyAlias) { - this.encryptionKeyAlias = Objects.requireNonNull(encryptionKeyAlias); + contributeProperties(binder).put(CryptoConstants.ENCRYPTION_KEY_ALIAS, encryptionKeyAlias); return this; } /** * Configures keystore parameters. The KeyStore must be of "jceks" type and - * contain all needed secret keys for the target database. Currently all + * contain all needed secret keys for the target database. Currently, all * keys must be protected with the same password. * * @param file A file to load keystore from. @@ -150,17 +133,17 @@ public class CryptoModuleExtender { * encryption by default. */ public CryptoModuleExtender keyStore(File file, char[] passwordForAllKeys, String encryptionKeyAlias) { - this.encryptionKeyAlias = encryptionKeyAlias; - this.keyPassword = passwordForAllKeys; - this.keyStoreUrl = null; - this.keyStoreUrlString = null; - this.keyStoreFile = Objects.requireNonNull(file); - return this; + try { + String fileUrl = file.toURI().toURL().toExternalForm(); + return keyStore(fileUrl, passwordForAllKeys, encryptionKeyAlias); + } catch (MalformedURLException e) { + throw new IllegalArgumentException("Invalid keyStore file", e); + } } /** * Configures keystore parameters. The KeyStore must be of "jceks" type and - * contain all needed secret keys for the target database. Currently all + * contain all needed secret keys for the target database. Currently, all * keys must be protected with the same password. * * @param url A URL to load keystore from. @@ -168,18 +151,13 @@ public class CryptoModuleExtender { * @param encryptionKeyAlias The name of the key in the keystore that should be used for * encryption by default. */ - public CryptoModuleExtender keyStore(String url, char[] passwordForAllKeys, String encryptionKeyAlias) { - this.encryptionKeyAlias = encryptionKeyAlias; - this.keyPassword = passwordForAllKeys; - this.keyStoreUrl = null; - this.keyStoreUrlString = Objects.requireNonNull(url); - this.keyStoreFile = null; - return this; + public CryptoModuleExtender keyStore(URL url, char[] passwordForAllKeys, String encryptionKeyAlias) { + return keyStore(url.toExternalForm(), passwordForAllKeys, encryptionKeyAlias); } /** * Configures keystore parameters. The KeyStore must be of "jceks" type and - * contain all needed secret keys for the target database. Currently all + * contain all needed secret keys for the target database. Currently, all * keys must be protected with the same password. * * @param url A URL to load keystore from. @@ -187,29 +165,26 @@ public class CryptoModuleExtender { * @param encryptionKeyAlias The name of the key in the keystore that should be used for * encryption by default. */ - public CryptoModuleExtender keyStore(URL url, char[] passwordForAllKeys, String encryptionKeyAlias) { - this.encryptionKeyAlias = encryptionKeyAlias; - this.keyPassword = passwordForAllKeys; - this.keyStoreUrl = Objects.requireNonNull(url); - this.keyStoreUrlString = null; - this.keyStoreFile = null; + public CryptoModuleExtender keyStore(String url, char[] passwordForAllKeys, String encryptionKeyAlias) { + MapBuilder<String> propertiesBuilder = contributeProperties(binder); + propertiesBuilder.put(CryptoConstants.KEYSTORE_URL, url); + propertiesBuilder.put(CryptoConstants.ENCRYPTION_KEY_ALIAS, encryptionKeyAlias); + contributeCredentials(binder).put(CryptoConstants.KEY_PASSWORD, passwordForAllKeys); return this; } - public CryptoModuleExtender keySource(Class<? extends KeySource> type) { - this.keySourceType = Objects.requireNonNull(type); - this.keySource = null; + public CryptoModuleExtender keySource(Class<? extends KeySource> keySourceType) { + binder.bind(KeySource.class).to(keySourceType); return this; } public CryptoModuleExtender keySource(KeySource keySource) { - this.keySourceType = null; - this.keySource = Objects.requireNonNull(keySource); + binder.bind(KeySource.class).toInstance(keySource); return this; } public CryptoModuleExtender compress() { - this.compress = true; + contributeProperties(binder).put(CryptoConstants.COMPRESSION, "true"); return this; } @@ -217,109 +192,41 @@ public class CryptoModuleExtender { * Enable authentication codes */ public CryptoModuleExtender useHMAC() { - this.useHMAC = true; + contributeProperties(binder).put(CryptoConstants.USE_HMAC, "true"); return this; } - /** - * Produces a module that can be used to start Cayenne runtime. - */ - public Module module() { - - return binder -> { - - MapBuilder<String> props = CryptoModule.contributeProperties(binder); - - if (cipherAlgorithm != null) { - props.put(CryptoConstants.CIPHER_ALGORITHM, cipherAlgorithm); - } - - if (cipherMode != null) { - props.put(CryptoConstants.CIPHER_MODE, cipherMode); - } - - String keyStoreUrl = keyStoreUrl(); - if (keyStoreUrl != null) { - props.put(CryptoConstants.KEYSTORE_URL, keyStoreUrl); - } - - if (encryptionKeyAlias != null) { - props.put(CryptoConstants.ENCRYPTION_KEY_ALIAS, encryptionKeyAlias); - } - - if (compress) { - props.put(CryptoConstants.COMPRESSION, "true"); - } - - if (useHMAC) { - props.put(CryptoConstants.USE_HMAC, "true"); - } - - if (keyPassword != null) { - CryptoModule.contributeCredentials(binder).put(CryptoConstants.KEY_PASSWORD, keyPassword); - } - - if (cipherFactoryType != null) { - binder.bind(CipherFactory.class).to(cipherFactoryType); - } - - if (valueTransformerFactoryType != null) { - binder.bind(ValueTransformerFactory.class).to(valueTransformerFactoryType); - } - - if (!extraDbToBytes.isEmpty()) { - MapBuilder<BytesConverter<?>> dbToBytesBinder = CryptoModule.contributeDbToByteConverters(binder); - for (Map.Entry<Integer, BytesConverter<?>> extraConverter : extraDbToBytes.entrySet()) { - dbToBytesBinder.put(extraConverter.getKey().toString(), extraConverter.getValue()); - } - } - - if (!extraObjectToBytes.isEmpty()) { - MapBuilder<BytesConverter<?>> objectToBytesBinder = CryptoModule.contributeObjectToByteConverters(binder); - for (Map.Entry<String, BytesConverter<?>> extraConverter : extraObjectToBytes.entrySet()) { - objectToBytesBinder.put(extraConverter.getKey(), extraConverter.getValue()); - } - } - - if (bytesTransformerFactoryType != null) { - binder.bind(BytesTransformerFactory.class).to(bytesTransformerFactoryType); - } - - if (keySource != null) { - binder.bind(KeySource.class).toInstance(keySource); - } else if (keySourceType != null) { - binder.bind(KeySource.class).to(keySourceType); - } - - if (columnMapperPattern != null) { - binder.bind(ColumnMapper.class).toInstance(new PatternColumnMapper(columnMapperPattern)); - } else if (columnMapperType != null) { - binder.bind(ColumnMapper.class).to(columnMapperType); - } else if (columnMapper != null) { - binder.bind(ColumnMapper.class).toInstance(columnMapper); - } - }; + private MapBuilder<String> contributeProperties(Binder binder) { + if (properties == null) { + properties = binder.bindMap(String.class, CryptoConstants.PROPERTIES_MAP); + } + return properties; } - protected String keyStoreUrl() { - if (this.keyStoreUrl != null) { - return this.keyStoreUrl.toExternalForm(); + private MapBuilder<char[]> contributeCredentials(Binder binder) { + if (credentials == null) { + credentials = binder.bindMap(char[].class, CryptoConstants.CREDENTIALS_MAP); } + return credentials; + } - if (this.keyStoreUrlString != null) { - return this.keyStoreUrlString; + @SuppressWarnings({"rawtypes", "unchecked"}) + private MapBuilder<BytesConverter<?>> contributeDbToByteConverters(Binder binder) { + if (dbToByteConverters == null) { + MapBuilder mapBuilder = binder.bindMap(BytesConverter.class, + DefaultValueTransformerFactory.DB_TO_BYTE_CONVERTERS_KEY); + dbToByteConverters = mapBuilder; } + return dbToByteConverters; + } - if (keyStoreFile != null) { - try { - return keyStoreFile.toURI().toURL().toExternalForm(); - } catch (MalformedURLException e) { - throw new IllegalStateException("Invalid keyStore file", e); - } + @SuppressWarnings({"rawtypes", "unchecked"}) + private MapBuilder<BytesConverter<?>> contributeObjectToByteConverters(Binder binder) { + if (objectToByteConverters == null) { + MapBuilder mapBuilder = binder.bindMap(BytesConverter.class, + DefaultValueTransformerFactory.OBJECT_TO_BYTE_CONVERTERS_KEY); + objectToByteConverters = mapBuilder; } - - return null; + return objectToByteConverters; } - - } diff --git a/cayenne-crypto/src/test/java/org/apache/cayenne/crypto/CryptoModuleBuilderTest.java b/cayenne-crypto/src/test/java/org/apache/cayenne/crypto/CryptoModuleExtenderTest.java similarity index 89% rename from cayenne-crypto/src/test/java/org/apache/cayenne/crypto/CryptoModuleBuilderTest.java rename to cayenne-crypto/src/test/java/org/apache/cayenne/crypto/CryptoModuleExtenderTest.java index 4e79817d9..20e03a900 100644 --- a/cayenne-crypto/src/test/java/org/apache/cayenne/crypto/CryptoModuleBuilderTest.java +++ b/cayenne-crypto/src/test/java/org/apache/cayenne/crypto/CryptoModuleExtenderTest.java @@ -32,14 +32,13 @@ import java.security.Key; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; -public class CryptoModuleBuilderTest { +public class CryptoModuleExtenderTest { @Test public void testBuild_KeySource() { - URL ksUrl = JceksKeySourceTest.class.getResource(JceksKeySourceTest.KS1_JCEKS); - Module m = new CryptoModuleExtender().keyStore(ksUrl, JceksKeySourceTest.TEST_KEY_PASS, "k1") - .valueTransformer(DefaultValueTransformerFactory.class).module(); + Module m = b -> new CryptoModuleExtender(b).keyStore(ksUrl, JceksKeySourceTest.TEST_KEY_PASS, "k1") + .valueTransformerFactory(DefaultValueTransformerFactory.class); Injector injector = DIBootstrap.createInjector(new CryptoModule(), m); 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 8eb9b16d8..43c6873a3 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 @@ -66,18 +66,18 @@ public class Runtime_AES128_Base { protected Module createCryptoModule(boolean compress, boolean useHMAC) { URL keyStoreUrl = JceksKeySourceTest.class.getResource(JceksKeySourceTest.KS1_JCEKS); - CryptoModuleExtender builder = CryptoModule - .extend() - .keyStore(keyStoreUrl, JceksKeySourceTest.TEST_KEY_PASS, "k3"); - - if (compress) { - builder.compress(); - } - if(useHMAC) { - builder.useHMAC(); - } - - return builder.module(); + Module module = b -> { + CryptoModuleExtender moduleExtender = CryptoModule.extend(b) + .keyStore(keyStoreUrl, JceksKeySourceTest.TEST_KEY_PASS, "k3"); + if (compress) { + moduleExtender.compress(); + } + if(useHMAC) { + moduleExtender.useHMAC(); + } + }; + + return module; } }