Skip to content

Commit

Permalink
Prevent race condition in entity filtering (eclipse-ee4j#4204)
Browse files Browse the repository at this point in the history
Signed-off-by: Jan Supol <[email protected]>
  • Loading branch information
jansupol authored and pa314159 committed Aug 28, 2019
1 parent 72a300e commit 8af5e69
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 6 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2013, 2019 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
Expand Down Expand Up @@ -82,4 +82,10 @@ public ObjectGraph createObjectGraph(final Class<?> entityClass, final Set<Strin
? new EmptyObjectGraph(entityClass)
: new ObjectGraphImpl(classToGraph, entityGraph, filteringScopes);
}

@Override
public EntityGraph putIfAbsent(Class<?> entityClass, EntityGraph entityGraph, boolean forWriter) {
final ConcurrentMap<Class<?>, EntityGraph> classToGraph = forWriter ? writerClassToGraph : readerClassToGraph;
return classToGraph.putIfAbsent(entityClass, entityGraph);
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2013, 2019 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
Expand Down Expand Up @@ -50,7 +50,6 @@
*/
@Singleton
final class EntityInspectorImpl implements EntityInspector {

private final List<EntityProcessor> entityProcessors;

@Inject
Expand All @@ -71,21 +70,26 @@ public EntityInspectorImpl(final InjectionManager injectionManager) {
@Override
public void inspect(final Class<?> entityClass, final boolean forWriter) {
if (!graphProvider.containsEntityGraph(entityClass, forWriter)) {
final EntityGraph graph = graphProvider.getOrCreateEntityGraph(entityClass, forWriter);
final EntityGraph graph = new EntityGraphImpl(entityClass);
final Set<Class<?>> inspect = new HashSet<>();

// Class.
if (!inspectEntityClass(entityClass, graph, forWriter)) {
// Properties.
final Map<String, Method> unmatchedAccessors = inspectEntityProperties(entityClass, graph, inspect, forWriter);
final Map<String, Method> unmatchedAccessors =
inspectEntityProperties(entityClass, graph, inspect, forWriter);

// Setters/Getters without fields.
inspectStandaloneAccessors(unmatchedAccessors, graph, forWriter);

graphProvider.putIfAbsent(entityClass, graph, forWriter);

// Inspect new classes.
for (final Class<?> clazz : inspect) {
inspect(clazz, forWriter);
}
} else {
graphProvider.putIfAbsent(entityClass, graph, forWriter);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, 2018 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2013, 2019 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
Expand Down Expand Up @@ -66,4 +66,15 @@ public interface EntityGraphProvider {
* @return an entity-filtering object graph instance.
*/
public ObjectGraph createObjectGraph(final Class<?> entityClass, final Set<String> filteringScopes, final boolean forWriter);

/**
* Store an {@code EntityGraph} for a given entity if not already stored
* @param entityClass entity class which the object graph should be created for.
* @param entityGraph an entity graph to be stored
* @param forWriter flag determining whether the graph should be created for writer/reader.
* @return the previous value associated with the {@code entityClass, forWriter} key,
* or {@code null} if there was no previous mapping for the key. This behavior is inherited from
* {@link java.util.Map#putIfAbsent(Object, Object)}.
*/
public EntityGraph putIfAbsent(final Class<?> entityClass, EntityGraph entityGraph, final boolean forWriter);
}

0 comments on commit 8af5e69

Please sign in to comment.