/*****************************************************************
* 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.configuration.server.ServerRuntime;
import org.apache.cayenne.crypto.key.KeySource;
import org.apache.cayenne.map.DbAttribute;
import org.apache.cayenne.map.DbEntity;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.sql.Types;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
public class DefaultValueTransformerFactoryIT {
private static DbEntity t1;
private static DbEntity t2;
private static DbEntity t3;
private static DbEntity t5;
private static Map<String, BytesConverter<?>> dbToBytes, objectToBytes;
private DefaultValueTransformerFactory f;
@BeforeClass
public static void beforeClass() throws Exception {
ServerRuntime runtime = ServerRuntime.builder().addConfig("cayenne-crypto.xml").build();
t1 = runtime.getChannel().getEntityResolver().getDbEntity("TABLE1");
t2 = runtime.getChannel().getEntityResolver().getDbEntity("TABLE2");
t3 = runtime.getChannel().getEntityResolver().getDbEntity("TABLE3");
t5 = runtime.getChannel().getEntityResolver().getDbEntity("TABLE5");
dbToBytes = getDefaultDbConverters();
objectToBytes = getDefaultObjectConverters();
}
@Before
public void before() {
f = new DefaultValueTransformerFactory(mock(KeySource.class), dbToBytes, objectToBytes);
}
@Test
public void testGetJavaType() {
DbAttribute t1_ct = t1.getAttribute("CRYPTO_STRING");
assertEquals("java.lang.String", f.getJavaType(t1_ct));
DbAttribute t2_cb = t2.getAttribute("CRYPTO_BYTES");
assertEquals("byte[]", f.getJavaType(t2_cb));
DbEntity fakeEntity = mock(DbEntity.class);
when(fakeEntity.getDataMap()).thenReturn(t1.getDataMap());
DbAttribute fakeA1 = mock(DbAttribute.class);
when(fakeA1.getName()).thenReturn("fake1");
when(fakeA1.getEntity()).thenReturn(fakeEntity);
when(fakeA1.getType()).thenReturn(Types.VARBINARY);
assertEquals("byte[]", f.getJavaType(fakeA1));
DbAttribute fakeA2 = mock(DbAttribute.class);
when(fakeA2.getName()).thenReturn("fake2");
when(fakeA2.getEntity()).thenReturn(fakeEntity);
when(fakeA2.getType()).thenReturn(Types.VARCHAR);
assertEquals("java.lang.String", f.getJavaType(fakeA2));
}
@Test
public void testGetAmbiguousJavaType() {
// this one have two bound ObjAttributes, warn should be in log
DbAttribute a1 = t5.getAttribute("CRYPTO_INT1");
assertEquals("java.lang.String", f.getJavaType(a1));
// this one doesn't have any bindings, warn should be in log
DbAttribute a2 = t5.getAttribute("CRYPTO_INT2");
assertEquals("byte[]", f.getJavaType(a2));
// this one have one binding
DbAttribute a3 = t5.getAttribute("CRYPTO_INT3");
assertEquals("int", f.getJavaType(a3));
// this one have two bindings but with the same int type
DbAttribute a4 = t5.getAttribute("CRYPTO_INT4");
assertEquals("int", f.getJavaType(a4));
}
@Test
public void testCreateEncryptor() {
DbAttribute t1_ct = t1.getAttribute("CRYPTO_STRING");
ValueEncryptor t1 = f.createEncryptor(t1_ct);
assertNotNull(t1);
assertTrue(t1 instanceof DefaultValueEncryptor);
assertSame(Utf8StringConverter.INSTANCE, ((DefaultValueEncryptor) t1).getPreConverter());
assertSame(Base64StringConverter.INSTANCE, ((DefaultValueEncryptor) t1).getPostConverter());
DbAttribute t2_cb = t2.getAttribute("CRYPTO_BYTES");
ValueEncryptor t2 = f.createEncryptor(t2_cb);
assertNotNull(t2);
assertTrue(t2 instanceof DefaultValueEncryptor);
assertSame(BytesToBytesConverter.INSTANCE, ((DefaultValueEncryptor) t2).getPreConverter());
assertSame(BytesToBytesConverter.INSTANCE, ((DefaultValueEncryptor) t2).getPostConverter());
}
@Test
public void testCreateDecryptor() {
DbAttribute t1_ct = t1.getAttribute("CRYPTO_STRING");
ValueDecryptor t1 = f.createDecryptor(t1_ct);
assertNotNull(t1);
assertTrue(t1 instanceof DefaultValueDecryptor);
assertSame(Base64StringConverter.INSTANCE, ((DefaultValueDecryptor) t1).getPreConverter());
assertSame(Utf8StringConverter.INSTANCE, ((DefaultValueDecryptor) t1).getPostConverter());
DbAttribute t2_cb = t2.getAttribute("CRYPTO_BYTES");
ValueDecryptor t2 = f.createDecryptor(t2_cb);
assertNotNull(t2);
assertTrue(t2 instanceof DefaultValueDecryptor);
assertSame(BytesToBytesConverter.INSTANCE, ((DefaultValueDecryptor) t2).getPreConverter());
assertSame(BytesToBytesConverter.INSTANCE, ((DefaultValueDecryptor) t2).getPostConverter());
DbAttribute t3_cb = t3.getAttribute("CRYPTO_BYTES");
ValueDecryptor t3 = f.createDecryptor(t3_cb);
assertNotNull(t3);
assertTrue(t3 instanceof DefaultValueDecryptor);
assertSame(BytesToBytesConverter.INSTANCE, ((DefaultValueDecryptor) t3).getPreConverter());
assertSame(Utf8StringConverter.INSTANCE, ((DefaultValueDecryptor) t3).getPostConverter());
}
@Test
public void testEncryptor() {
DbAttribute t1_ct = t1.getAttribute("CRYPTO_STRING");
ValueEncryptor t1 = f.encryptor(t1_ct);
assertNotNull(t1);
assertSame(t1, f.encryptor(t1_ct));
assertSame(t1, f.encryptor(t1_ct));
DbAttribute t2_cb = t2.getAttribute("CRYPTO_BYTES");
ValueEncryptor t2 = f.encryptor(t2_cb);
assertNotNull(t2);
assertSame(t2, f.encryptor(t2_cb));
assertSame(t2, f.encryptor(t2_cb));
}
@Test
public void testDecryptor() {
DbAttribute t1_ct = t1.getAttribute("CRYPTO_STRING");
ValueDecryptor t1 = f.decryptor(t1_ct);
assertNotNull(t1);
assertSame(t1, f.decryptor(t1_ct));
assertSame(t1, f.decryptor(t1_ct));
DbAttribute t2_cb = t2.getAttribute("CRYPTO_BYTES");
ValueDecryptor t2 = f.decryptor(t2_cb);
assertNotNull(t2);
assertSame(t2, f.decryptor(t2_cb));
assertSame(t2, f.decryptor(t2_cb));
}
private static Map<String, BytesConverter<?>> getDefaultDbConverters() {
Map<String, BytesConverter<?>> dbToBytes = new HashMap<>();
dbToBytes.put(String.valueOf(Types.BINARY), BytesToBytesConverter.INSTANCE);
dbToBytes.put(String.valueOf(Types.BLOB), BytesToBytesConverter.INSTANCE);
dbToBytes.put(String.valueOf(Types.VARBINARY), BytesToBytesConverter.INSTANCE);
dbToBytes.put(String.valueOf(Types.LONGVARBINARY), BytesToBytesConverter.INSTANCE);
dbToBytes.put(String.valueOf(Types.CHAR), Base64StringConverter.INSTANCE);
dbToBytes.put(String.valueOf(Types.NCHAR), Base64StringConverter.INSTANCE);
dbToBytes.put(String.valueOf(Types.CLOB), Base64StringConverter.INSTANCE);
dbToBytes.put(String.valueOf(Types.NCLOB), Base64StringConverter.INSTANCE);
dbToBytes.put(String.valueOf(Types.LONGVARCHAR), Base64StringConverter.INSTANCE);
dbToBytes.put(String.valueOf(Types.LONGNVARCHAR), Base64StringConverter.INSTANCE);
dbToBytes.put(String.valueOf(Types.VARCHAR), Base64StringConverter.INSTANCE);
dbToBytes.put(String.valueOf(Types.NVARCHAR), Base64StringConverter.INSTANCE);
return dbToBytes;
}
private static Map<String, BytesConverter<?>> getDefaultObjectConverters() {
Map<String, BytesConverter<?>> objectToBytes = new HashMap<>();
objectToBytes.put("byte[]", BytesToBytesConverter.INSTANCE);
objectToBytes.put(String.class.getName(), Utf8StringConverter.INSTANCE);
objectToBytes.put(Double.class.getName(), DoubleConverter.INSTANCE);
objectToBytes.put(Double.TYPE.getName(), DoubleConverter.INSTANCE);
objectToBytes.put(Float.class.getName(), FloatConverter.INSTANCE);
objectToBytes.put(Float.TYPE.getName(), FloatConverter.INSTANCE);
objectToBytes.put(Long.class.getName(), LongConverter.INSTANCE);
objectToBytes.put(Long.TYPE.getName(), LongConverter.INSTANCE);
objectToBytes.put(Integer.class.getName(), IntegerConverter.INSTANCE);
objectToBytes.put(Integer.TYPE.getName(), IntegerConverter.INSTANCE);
objectToBytes.put(Short.class.getName(), ShortConverter.INSTANCE);
objectToBytes.put(Short.TYPE.getName(), ShortConverter.INSTANCE);
objectToBytes.put(Byte.class.getName(), ByteConverter.INSTANCE);
objectToBytes.put(Byte.TYPE.getName(), ByteConverter.INSTANCE);
objectToBytes.put(Boolean.class.getName(), BooleanConverter.INSTANCE);
objectToBytes.put(Boolean.TYPE.getName(), BooleanConverter.INSTANCE);
objectToBytes.put(Date.class.getName(), UtilDateConverter.INSTANCE);
objectToBytes.put(BigInteger.class.getName(), BigIntegerConverter.INSTANCE);
objectToBytes.put(BigDecimal.class.getName(), BigDecimalConverter.INSTANCE);
return objectToBytes;
}
}