From 1ecbc028b8d88a1a26fa77c55aeadbd9686986e1 Mon Sep 17 00:00:00 2001 From: Jan Supol Date: Tue, 2 Jul 2019 23:12:32 +0200 Subject: [PATCH] Prevent race condition in entity filtering Signed-off-by: Jan Supol --- .../message/filtering/EntityGraphProviderImpl.java | 8 +++++++- .../message/filtering/EntityInspectorImpl.java | 12 ++++++++---- .../message/filtering/spi/EntityGraphProvider.java | 13 ++++++++++++- 3 files changed, 27 insertions(+), 6 deletions(-) diff --git a/ext/entity-filtering/src/main/java/org/glassfish/jersey/message/filtering/EntityGraphProviderImpl.java b/ext/entity-filtering/src/main/java/org/glassfish/jersey/message/filtering/EntityGraphProviderImpl.java index ee07977e7e..f80a25098e 100644 --- a/ext/entity-filtering/src/main/java/org/glassfish/jersey/message/filtering/EntityGraphProviderImpl.java +++ b/ext/entity-filtering/src/main/java/org/glassfish/jersey/message/filtering/EntityGraphProviderImpl.java @@ -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 @@ -82,4 +82,10 @@ public ObjectGraph createObjectGraph(final Class entityClass, final Set entityClass, EntityGraph entityGraph, boolean forWriter) { + final ConcurrentMap, EntityGraph> classToGraph = forWriter ? writerClassToGraph : readerClassToGraph; + return classToGraph.putIfAbsent(entityClass, entityGraph); + } } diff --git a/ext/entity-filtering/src/main/java/org/glassfish/jersey/message/filtering/EntityInspectorImpl.java b/ext/entity-filtering/src/main/java/org/glassfish/jersey/message/filtering/EntityInspectorImpl.java index 76af833843..0e353f4e82 100644 --- a/ext/entity-filtering/src/main/java/org/glassfish/jersey/message/filtering/EntityInspectorImpl.java +++ b/ext/entity-filtering/src/main/java/org/glassfish/jersey/message/filtering/EntityInspectorImpl.java @@ -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 @@ -50,7 +50,6 @@ */ @Singleton final class EntityInspectorImpl implements EntityInspector { - private final List entityProcessors; @Inject @@ -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> inspect = new HashSet<>(); // Class. if (!inspectEntityClass(entityClass, graph, forWriter)) { // Properties. - final Map unmatchedAccessors = inspectEntityProperties(entityClass, graph, inspect, forWriter); + final Map 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); } } } diff --git a/ext/entity-filtering/src/main/java/org/glassfish/jersey/message/filtering/spi/EntityGraphProvider.java b/ext/entity-filtering/src/main/java/org/glassfish/jersey/message/filtering/spi/EntityGraphProvider.java index 1f67159d8b..d13d35916d 100644 --- a/ext/entity-filtering/src/main/java/org/glassfish/jersey/message/filtering/spi/EntityGraphProvider.java +++ b/ext/entity-filtering/src/main/java/org/glassfish/jersey/message/filtering/spi/EntityGraphProvider.java @@ -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 @@ -66,4 +66,15 @@ public interface EntityGraphProvider { * @return an entity-filtering object graph instance. */ public ObjectGraph createObjectGraph(final Class entityClass, final Set 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); }