Skip to content

Commit

Permalink
cleanup. bump versions.
Browse files Browse the repository at this point in the history
  • Loading branch information
agoston committed Mar 16, 2022
1 parent 9d962cd commit e5541e2
Show file tree
Hide file tree
Showing 10 changed files with 120 additions and 141 deletions.
12 changes: 6 additions & 6 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -48,27 +48,27 @@
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongodb-driver-sync</artifactId>
<version>4.1.1</version>
<version>4.5.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb</artifactId>
<version>3.1.1</version>
<version>3.3.2</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
<version>2.4.0</version>
<version>2.6.4</version>
<scope>provided</scope>
</dependency>

<!-- test -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<version>2.4.0</version>
<version>2.6.4</version>
<scope>test</scope>
</dependency>
<!-- <dependency>-->
Expand All @@ -86,13 +86,13 @@
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.1</version>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<version>3.18.1</version>
<version>3.22.0</version>
<scope>test</scope>
</dependency>
</dependencies>
Expand Down
1 change: 0 additions & 1 deletion src/main/java/com/bol/config/EncryptAutoConfiguration.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
import com.bol.secure.CachedEncryptionEventListener;
import com.bol.secure.ReflectionEncryptionEventListener;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.ConfigurationProperties;
Expand Down
53 changes: 22 additions & 31 deletions src/main/java/com/bol/reflection/ReflectionCache.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,26 +12,19 @@
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

import static com.bol.secure.FieldEncryptedPredicate.ANNOTATION_PRESENT;

public class ReflectionCache {

private static final Logger LOG = LoggerFactory.getLogger(ReflectionCache.class);

private final ConcurrentHashMap<Class, List<Node>> reflectionCache = new ConcurrentHashMap<>();

private final ConcurrentHashMap<Class<?>, List<Node>> reflectionCache = new ConcurrentHashMap<>();
private final FieldEncryptedPredicate fieldEncryptedPredicate;

public ReflectionCache() {
this(ANNOTATION_PRESENT);
}

public ReflectionCache(FieldEncryptedPredicate fieldEncryptedPredicate) {
this.fieldEncryptedPredicate = fieldEncryptedPredicate;
}

// used by CachedEncryptionEventListener to gather metadata of a class and all it fields, recursively.
public List<Node> reflectRecursive(Class objectClass) {
public List<Node> reflectRecursive(Class<?> objectClass) {
List<Node> nodes = reflectionCache.get(objectClass);
if (nodes != null) return nodes;

Expand All @@ -41,7 +34,7 @@ public List<Node> reflectRecursive(Class objectClass) {
}

// building is necessary to avoid putting half-processed data in `reflectionCache` (where it would be returned to other threads)
private List<Node> buildRecursive(Class objectClass, HashMap<Class, List<Node>> building) {
private List<Node> buildRecursive(Class<?> objectClass, HashMap<Class<?>, List<Node>> building) {
if (isPrimitive(objectClass)) return Collections.emptyList();

List<Node> processed = reflectionCache.get(objectClass);
Expand Down Expand Up @@ -94,12 +87,12 @@ private List<Node> buildRecursive(Class objectClass, HashMap<Class, List<Node>>
}

// used by ReflectionEncryptionEventListener to map a single Document
public List<Node> reflectSingle(Class objectClass) {
public List<Node> reflectSingle(Class<?> objectClass) {
return reflectionCache.computeIfAbsent(objectClass, this::buildSingle);
}

// FIXME: this is a slimmed down copy-paste of buildRecursive(); find a way to bring Cached and Reflective listener closer together!
private List<Node> buildSingle(Class objectClass) {
private List<Node> buildSingle(Class<?> objectClass) {
if (isPrimitive(objectClass)) return Collections.emptyList();

List<Node> nodes = new ArrayList<>();
Expand Down Expand Up @@ -137,14 +130,14 @@ private List<Node> buildSingle(Class objectClass) {
return nodes;
}

List<Node> processParameterizedTypes(Type type, HashMap<Class, List<Node>> building) {
List<Node> processParameterizedTypes(Type type, HashMap<Class<?>, List<Node>> building) {
if (type instanceof Class) {
List<Node> children = buildRecursive((Class) type, building);
List<Node> children = buildRecursive((Class<?>) type, building);
if (!children.isEmpty()) return Collections.singletonList(new Node(null, children, Node.Type.DOCUMENT));

} else if (type instanceof ParameterizedType) {
ParameterizedType subType = (ParameterizedType) type;
Class rawType = (Class) subType.getRawType();
Class<?> rawType = (Class<?>) subType.getRawType();

if (Collection.class.isAssignableFrom(rawType)) {
List<Node> children = processParameterizedTypes(subType.getActualTypeArguments()[0], building);
Expand All @@ -155,7 +148,7 @@ List<Node> processParameterizedTypes(Type type, HashMap<Class, List<Node>> build
if (!children.isEmpty()) return Collections.singletonList(new Node(null, children, Node.Type.MAP));

} else {
throw new IllegalArgumentException("Unknown reflective raw type class " + rawType.getClass());
throw new IllegalArgumentException("Unknown reflective raw type class " + rawType);
}

} else {
Expand Down Expand Up @@ -190,22 +183,20 @@ static String parseFieldAnnotation(java.lang.reflect.Field field, String fieldNa
}

// same as ClassUtils.isPrimitiveOrWrapper(), but also includes String
public static boolean isPrimitive(Class clazz) {
public static boolean isPrimitive(Class<?> clazz) {
return clazz.isPrimitive() || primitiveClasses.contains(clazz);
}

private static Set<Class> primitiveClasses = new HashSet<>();

static {
primitiveClasses.add(Boolean.class);
primitiveClasses.add(Byte.class);
primitiveClasses.add(Character.class);
primitiveClasses.add(Double.class);
primitiveClasses.add(Float.class);
primitiveClasses.add(Integer.class);
primitiveClasses.add(Long.class);
primitiveClasses.add(Short.class);
primitiveClasses.add(Void.class);
primitiveClasses.add(String.class);
}
private static final Set<Class<?>> primitiveClasses = new HashSet<>(Arrays.asList(
Boolean.class,
Byte.class,
Character.class,
Double.class,
Float.class,
Integer.class,
Long.class,
Short.class,
Void.class,
String.class
));
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public CachedEncryptionEventListener(CryptVault cryptVault, FieldEncryptedPredic
reflectionCache = new ReflectionCache(fieldEncryptedPredicate);
}

Node node(Class clazz) {
Node node(Class<?> clazz) {
List<Node> children = reflectionCache.reflectRecursive(clazz);
if (!children.isEmpty()) return new Node("", children, Node.Type.DOCUMENT);
return Node.EMPTY;
Expand Down Expand Up @@ -77,7 +77,7 @@ void cryptFields(Object o, Node node, Function<Object, Object> crypt) {
break;

case LIST:
cryptList((List) o, node, crypt);
cryptList((List<?>) o, node, crypt);
break;

default:
Expand All @@ -88,7 +88,7 @@ void cryptFields(Object o, Node node, Function<Object, Object> crypt) {
}
}

void cryptList(List list, Node node, Function<Object, Object> crypt) {
void cryptList(List<?> list, Node node, Function<Object, Object> crypt) {
if (node.type != Node.Type.LIST) throw new IllegalArgumentException("Expected list for " + node.fieldName + ", got " + node.type);

Node mapChildren = node.children.get(0);
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/com/bol/secure/FieldEncryptedPredicate.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@

public interface FieldEncryptedPredicate extends Predicate<Field> {

FieldEncryptedPredicate ANNOTATION_PRESENT = field -> field.isAnnotationPresent(Encrypted.class);
FieldEncryptedPredicate ANNOTATION_PRESENT = field -> field.isAnnotationPresent(Encrypted.class);

}
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,10 @@ public ReflectionEncryptionEventListener(CryptVault cryptVault) {

public ReflectionEncryptionEventListener(CryptVault cryptVault, FieldEncryptedPredicate fieldEncryptedPredicate) {
super(cryptVault);
this.reflectionCache = new ReflectionCache(fieldEncryptedPredicate);
reflectionCache = new ReflectionCache(fieldEncryptedPredicate);
}

void cryptDocument(Document document, Class clazz, Function<Object, Object> crypt) {
void cryptDocument(Document document, Class<?> clazz, Function<Object, Object> crypt) {
List<Node> nodes = reflectionCache.reflectSingle(clazz);

for (Map.Entry<String, Object> field : document.entrySet()) {
Expand Down Expand Up @@ -71,23 +71,23 @@ void diveInto(Object value, Type type, Function<Object, Object> crypt) {
// java primitive type; ignore
if (isPrimitive(value.getClass())) return;

Class reflectiveClass = null;
Class<?> reflectiveClass = null;
Type[] typeArguments = null;
if (type instanceof Class) reflectiveClass = (Class) type;
if (type instanceof Class) reflectiveClass = (Class<?>) type;
else if (type instanceof ParameterizedType) {
ParameterizedType parameterizedType = (ParameterizedType) type;
Type rawType = parameterizedType.getRawType();
typeArguments = parameterizedType.getActualTypeArguments();
if (!(rawType instanceof Class)) throw new IllegalArgumentException("Unknown reflective type class " + type);
reflectiveClass = (Class) rawType;
reflectiveClass = (Class<?>) rawType;
} else throw new IllegalArgumentException("Unknown reflective type class " + type);

if (value instanceof Document) {
// Document could be a Map OR a Document; decide based on reflectiveClass
if (Map.class.isAssignableFrom(reflectiveClass)) {
Type subFieldType = typeArguments[1];

for (Map.Entry entry : ((Map<?, ?>) value).entrySet()) {
for (Map.Entry<?, ?> entry : ((Map<?, ?>) value).entrySet()) {
try {
diveInto(entry.getValue(), subFieldType, crypt);
} catch (FieldCryptException e) {
Expand All @@ -106,7 +106,7 @@ else if (type instanceof ParameterizedType) {
} else if (value instanceof List) {
if (Collection.class.isAssignableFrom(reflectiveClass)) {
Type subFieldType = typeArguments[0];
List list = (List) value;
List<?> list = (List<?>) value;

for (int i = 0; i < list.size(); i++) {
try {
Expand Down
60 changes: 30 additions & 30 deletions src/test/java/com/bol/system/CryptAssert.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,35 +7,35 @@

public class CryptAssert {

private final CryptVault cryptVault;

public CryptAssert(CryptVault cryptVault) {
this.cryptVault = cryptVault;
}

/**
* simplistic mongodb BSON serialization lengths:
* - 10 bytes for wrapping BSONObject prefix
* - 1 byte prefix before field name
* - field name (1 byte/char)
* - 1 byte 0-terminator after field name
* - 4 byte prefix before field value
* - field value (1byte/char)
* - 1 byte 0-terminator after field value
* - 2 bytes 0 terminator for wrapping BSONObject
* <p>
* (e.g. for a single primitive string, 12 extra bytes are added above its own length)
*/
public void assertCryptLength(Object cryptedSecretBinary, int serializedLength) {
assertThat(cryptedSecretBinary).isInstanceOf(Binary.class);

Object cryptedSecretBytes = ((Binary) cryptedSecretBinary).getData();

assertThat(cryptedSecretBytes).isInstanceOf(byte[].class);
byte[] cryptedBytes = (byte[]) cryptedSecretBytes;

int expectedCryptedLength = cryptVault.expectedCryptedLength(serializedLength);
assertThat(cryptedBytes.length).isEqualTo(expectedCryptedLength);
}
private final CryptVault cryptVault;

public CryptAssert(CryptVault cryptVault) {
this.cryptVault = cryptVault;
}

/**
* simplistic mongodb BSON serialization lengths:
* - 10 bytes for wrapping BSONObject prefix
* - 1 byte prefix before field name
* - field name (1 byte/char)
* - 1 byte 0-terminator after field name
* - 4 byte prefix before field value
* - field value (1byte/char)
* - 1 byte 0-terminator after field value
* - 2 bytes 0 terminator for wrapping BSONObject
* <p>
* (e.g. for a single primitive string, 12 extra bytes are added above its own length)
*/
public void assertCryptLength(Object cryptedSecretBinary, int serializedLength) {
assertThat(cryptedSecretBinary).isInstanceOf(Binary.class);

Object cryptedSecretBytes = ((Binary) cryptedSecretBinary).getData();

assertThat(cryptedSecretBytes).isInstanceOf(byte[].class);
byte[] cryptedBytes = (byte[]) cryptedSecretBytes;

int expectedCryptedLength = cryptVault.expectedCryptedLength(serializedLength);
assertThat(cryptedBytes.length).isEqualTo(expectedCryptedLength);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,7 @@
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import java.util.Arrays;

import static org.assertj.core.api.Assertions.assertThat;
import static org.springframework.data.mongodb.core.query.Criteria.where;
import static org.springframework.data.mongodb.core.query.Query.query;

@RunWith(SpringRunner.class)
@SpringBootTest(classes = {CachedMongoDBConfiguration.class})
Expand Down
Loading

0 comments on commit e5541e2

Please sign in to comment.