fix: refines the provider caching logic (#34220)
closes: #34219 Signed-off-by: Steve Hawkins <shawkins@redhat.com>
This commit is contained in:
parent
e520c71a1a
commit
964f6b9aac
1 changed files with 15 additions and 33 deletions
|
@ -60,9 +60,11 @@ import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
import java.util.function.Supplier;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -71,7 +73,7 @@ import java.util.stream.Collectors;
|
||||||
public abstract class DefaultKeycloakSession implements KeycloakSession {
|
public abstract class DefaultKeycloakSession implements KeycloakSession {
|
||||||
|
|
||||||
private final DefaultKeycloakSessionFactory factory;
|
private final DefaultKeycloakSessionFactory factory;
|
||||||
private final Map<Integer, Provider> providers = new HashMap<>();
|
private final Map<List<String>, Provider> providers = new HashMap<>();
|
||||||
private final List<Provider> closable = new LinkedList<>();
|
private final List<Provider> closable = new LinkedList<>();
|
||||||
private final DefaultKeycloakTransactionManager transactionManager;
|
private final DefaultKeycloakTransactionManager transactionManager;
|
||||||
private final Map<String, Object> attributes = new HashMap<>();
|
private final Map<String, Object> attributes = new HashMap<>();
|
||||||
|
@ -167,16 +169,20 @@ public abstract class DefaultKeycloakSession implements KeycloakSession {
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
@Override
|
@Override
|
||||||
public <T extends Provider> T getProvider(Class<T> clazz) {
|
public <T extends Provider> T getProvider(Class<T> clazz) {
|
||||||
Integer hash = clazz.hashCode();
|
List<String> key = List.of(clazz.getName());
|
||||||
T provider = (T) providers.get(hash);
|
return getOrCreateProvider(key, () -> factory.getProviderFactory(clazz));
|
||||||
|
}
|
||||||
|
|
||||||
|
private <T extends Provider> T getOrCreateProvider(List<String> key, Supplier<ProviderFactory<T>> supplier) {
|
||||||
|
T provider = (T) providers.get(key);
|
||||||
// KEYCLOAK-11890 - Avoid using HashMap.computeIfAbsent() to implement logic in outer if() block below,
|
// KEYCLOAK-11890 - Avoid using HashMap.computeIfAbsent() to implement logic in outer if() block below,
|
||||||
// since per JDK-8071667 the remapping function should not modify the map during computation. While
|
// since per JDK-8071667 the remapping function should not modify the map during computation. While
|
||||||
// allowed on JDK 1.8, attempt of such a modification throws ConcurrentModificationException with JDK 9+
|
// allowed on JDK 1.8, attempt of such a modification throws ConcurrentModificationException with JDK 9+
|
||||||
if (provider == null) {
|
if (provider == null) {
|
||||||
ProviderFactory<T> providerFactory = factory.getProviderFactory(clazz);
|
ProviderFactory<T> providerFactory = supplier.get();
|
||||||
if (providerFactory != null) {
|
if (providerFactory != null) {
|
||||||
provider = providerFactory.create(DefaultKeycloakSession.this);
|
provider = providerFactory.create(DefaultKeycloakSession.this);
|
||||||
providers.put(hash, provider);
|
providers.put(key, provider);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return provider;
|
return provider;
|
||||||
|
@ -185,19 +191,8 @@ public abstract class DefaultKeycloakSession implements KeycloakSession {
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
@Override
|
@Override
|
||||||
public <T extends Provider> T getProvider(Class<T> clazz, String id) {
|
public <T extends Provider> T getProvider(Class<T> clazz, String id) {
|
||||||
Integer hash = clazz.hashCode() + id.hashCode();
|
List<String> key = List.of(clazz.getName(), id);
|
||||||
T provider = (T) providers.get(hash);
|
return getOrCreateProvider(key, () -> factory.getProviderFactory(clazz, id));
|
||||||
// KEYCLOAK-11890 - Avoid using HashMap.computeIfAbsent() to implement logic in outer if() block below,
|
|
||||||
// since per JDK-8071667 the remapping function should not modify the map during computation. While
|
|
||||||
// allowed on JDK 1.8, attempt of such a modification throws ConcurrentModificationException with JDK 9+
|
|
||||||
if (provider == null) {
|
|
||||||
ProviderFactory<T> providerFactory = factory.getProviderFactory(clazz, id);
|
|
||||||
if (providerFactory != null) {
|
|
||||||
provider = providerFactory.create(DefaultKeycloakSession.this);
|
|
||||||
providers.put(hash, provider);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return provider;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -214,22 +209,9 @@ public abstract class DefaultKeycloakSession implements KeycloakSession {
|
||||||
@Override
|
@Override
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public <T extends Provider> T getComponentProvider(Class<T> clazz, String componentId, Function<KeycloakSessionFactory, ComponentModel> modelGetter) {
|
public <T extends Provider> T getComponentProvider(Class<T> clazz, String componentId, Function<KeycloakSessionFactory, ComponentModel> modelGetter) {
|
||||||
Integer hash = clazz.hashCode() + componentId.hashCode();
|
List<String> key = List.of("component", clazz.getName(), componentId);
|
||||||
T provider = (T) providers.get(hash);
|
|
||||||
final RealmModel realm = getContext().getRealm();
|
final RealmModel realm = getContext().getRealm();
|
||||||
|
return getOrCreateProvider(key, () -> factory.getProviderFactory(clazz, Optional.ofNullable(realm.getId()).orElse(null), componentId, modelGetter));
|
||||||
// KEYCLOAK-11890 - Avoid using HashMap.computeIfAbsent() to implement logic in outer if() block below,
|
|
||||||
// since per JDK-8071667 the remapping function should not modify the map during computation. While
|
|
||||||
// allowed on JDK 1.8, attempt of such a modification throws ConcurrentModificationException with JDK 9+
|
|
||||||
if (provider == null) {
|
|
||||||
final String realmId = realm == null ? null : realm.getId();
|
|
||||||
ProviderFactory<T> providerFactory = factory.getProviderFactory(clazz, realmId, componentId, modelGetter);
|
|
||||||
if (providerFactory != null) {
|
|
||||||
provider = providerFactory.create(this);
|
|
||||||
providers.put(hash, provider);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return provider;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
Loading…
Reference in a new issue