mirror of
https://github.com/keycloak/keycloak.git
synced 2026-01-09 23:12:06 -03:30
Managed resource not injected if a dependency is incompatibl (#38196)
Closes #38193 Signed-off-by: stianst <stianst@gmail.com>
This commit is contained in:
parent
c9b88c6bf6
commit
80e5c37969
@ -1,6 +1,5 @@
|
||||
package org.keycloak.testframework.injection;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
@ -9,7 +8,6 @@ public abstract class AbstractInterceptorHelper<I, V> {
|
||||
private final Registry registry;
|
||||
private final Class<?> interceptorClass;
|
||||
private final List<Interception> interceptions = new LinkedList<>();
|
||||
private final InterceptedBy interceptedBy = new InterceptedBy();
|
||||
|
||||
public AbstractInterceptorHelper(Registry registry, Class<I> interceptorClass) {
|
||||
this.registry = registry;
|
||||
@ -17,21 +15,18 @@ public abstract class AbstractInterceptorHelper<I, V> {
|
||||
|
||||
registry.getDeployedInstances().stream().filter(i -> isInterceptor(i.getSupplier())).forEach(i -> interceptions.add(new Interception(i)));
|
||||
registry.getRequestedInstances().stream().filter(r -> isInterceptor(r.getSupplier())).forEach(r -> interceptions.add(new Interception(r)));
|
||||
|
||||
interceptions.forEach(i -> interceptedBy.put(i.supplier, i.instanceId));
|
||||
}
|
||||
|
||||
public boolean sameInterceptors(InstanceContext<?, ?> instanceContext) {
|
||||
InterceptedBy previousInterceptedBy = instanceContext.getNote("InterceptedBy", InterceptedBy.class);
|
||||
return interceptedBy.equals(previousInterceptedBy);
|
||||
}
|
||||
|
||||
public V intercept(V value, InstanceContext<?, ?> instanceContext) {
|
||||
for (Interception interception : interceptions) {
|
||||
value = intercept(value, interception.supplier, interception.existingInstance);
|
||||
registry.getLogger().logIntercepted(value, interception.supplier);
|
||||
if (interception.existingInstance != null) {
|
||||
interception.existingInstance.registerDependency(instanceContext);
|
||||
} else {
|
||||
interception.requestedInstance.registerDependency(instanceContext);
|
||||
}
|
||||
}
|
||||
instanceContext.addNote("InterceptedBy", interceptedBy);
|
||||
return value;
|
||||
}
|
||||
|
||||
@ -41,24 +36,21 @@ public abstract class AbstractInterceptorHelper<I, V> {
|
||||
return interceptorClass.isAssignableFrom(supplier.getClass());
|
||||
}
|
||||
|
||||
public static class InterceptedBy extends HashMap<Supplier<?, ?>, Integer> {
|
||||
}
|
||||
|
||||
private static class Interception {
|
||||
|
||||
private final int instanceId;
|
||||
private final Supplier<?, ?> supplier;
|
||||
private final RequestedInstance<?, ?> requestedInstance;
|
||||
private final InstanceContext<?, ?> existingInstance;
|
||||
|
||||
public Interception(InstanceContext<?, ?> existingInstance) {
|
||||
this.supplier = existingInstance.getSupplier();
|
||||
this.instanceId = existingInstance.getInstanceId();
|
||||
this.requestedInstance = null;
|
||||
this.existingInstance = existingInstance;
|
||||
}
|
||||
|
||||
public Interception(RequestedInstance<?, ?> requestedInstance) {
|
||||
this.supplier = requestedInstance.getSupplier();
|
||||
this.instanceId = requestedInstance.getInstanceId();
|
||||
this.requestedInstance = requestedInstance;
|
||||
this.existingInstance = null;
|
||||
}
|
||||
}
|
||||
|
||||
@ -12,7 +12,7 @@ public class InstanceContext<T, A extends Annotation> {
|
||||
private final Registry registry;
|
||||
private final Supplier<T, A> supplier;
|
||||
private final A annotation;
|
||||
private final Set<InstanceContext<T, A>> dependencies = new HashSet<>();
|
||||
private final Set<InstanceContext<?, ?>> dependencies = new HashSet<>();
|
||||
private T value;
|
||||
private Class<? extends T> requestedValueType;
|
||||
private LifeCycle lifeCycle;
|
||||
@ -73,11 +73,11 @@ public class InstanceContext<T, A extends Annotation> {
|
||||
return annotation;
|
||||
}
|
||||
|
||||
public Set<InstanceContext<T, A>> getDependencies() {
|
||||
public Set<InstanceContext<?, ?>> getDependencies() {
|
||||
return dependencies;
|
||||
}
|
||||
|
||||
public void registerDependency(InstanceContext<T, A> instanceContext) {
|
||||
public void registerDependency(InstanceContext<?, ?> instanceContext) {
|
||||
dependencies.add(instanceContext);
|
||||
}
|
||||
|
||||
|
||||
@ -114,6 +114,7 @@ public class Registry implements ExtensionContext.Store.CloseableResource {
|
||||
|
||||
public void beforeEach(Object testInstance) {
|
||||
findRequestedInstances(testInstance);
|
||||
destroyIncompatibleInstances();
|
||||
matchDeployedInstancesWithRequestedInstances();
|
||||
deployRequestedInstances();
|
||||
injectFields(testInstance);
|
||||
@ -145,6 +146,19 @@ public class Registry implements ExtensionContext.Store.CloseableResource {
|
||||
logger.logRequestedInstances(requestedInstances);
|
||||
}
|
||||
|
||||
private void destroyIncompatibleInstances() {
|
||||
for (RequestedInstance<?, ?> requestedInstance : requestedInstances) {
|
||||
InstanceContext deployedInstance = getDeployedInstance(requestedInstance);
|
||||
if (deployedInstance != null) {
|
||||
boolean compatible = requestedInstance.getLifeCycle().equals(deployedInstance.getLifeCycle()) && deployedInstance.getSupplier().compatible(deployedInstance, requestedInstance);
|
||||
if (!compatible) {
|
||||
logger.logDestroyIncompatible(deployedInstance);
|
||||
destroy(deployedInstance);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void matchDeployedInstancesWithRequestedInstances() {
|
||||
Iterator<RequestedInstance<?, ?>> itr = requestedInstances.iterator();
|
||||
while (itr.hasNext()) {
|
||||
@ -154,9 +168,6 @@ public class Registry implements ExtensionContext.Store.CloseableResource {
|
||||
if (requestedInstance.getLifeCycle().equals(deployedInstance.getLifeCycle()) && deployedInstance.getSupplier().compatible(deployedInstance, requestedInstance)) {
|
||||
logger.logReusingCompatibleInstance(deployedInstance);
|
||||
itr.remove();
|
||||
} else {
|
||||
logger.logDestroyIncompatible(deployedInstance);
|
||||
destroy(deployedInstance);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -172,6 +183,11 @@ public class Registry implements ExtensionContext.Store.CloseableResource {
|
||||
instance.setValue(requestedInstance.getSupplier().getValue(instance));
|
||||
deployedInstances.add(instance);
|
||||
|
||||
if (!requestedInstance.getDependencies().isEmpty()) {
|
||||
Set<InstanceContext<?,?>> dependencies = requestedInstance.getDependencies();
|
||||
dependencies.forEach(instance::registerDependency);
|
||||
}
|
||||
|
||||
logger.logCreatedInstance(requestedInstance, instance);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,12 +1,15 @@
|
||||
package org.keycloak.testframework.injection;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
public class RequestedInstance<T, A extends Annotation> {
|
||||
|
||||
private final int instanceId;
|
||||
private final Supplier<T, A> supplier;
|
||||
private final A annotation;
|
||||
private final Set<InstanceContext<?, ?>> dependencies = new HashSet<>();
|
||||
private final Class<? extends T> valueType;
|
||||
private final LifeCycle lifeCycle;
|
||||
private final String ref;
|
||||
@ -44,4 +47,11 @@ public class RequestedInstance<T, A extends Annotation> {
|
||||
return ref;
|
||||
}
|
||||
|
||||
public void registerDependency(InstanceContext<?, ?> instanceContext) {
|
||||
dependencies.add(instanceContext);
|
||||
}
|
||||
|
||||
public Set<InstanceContext<?, ?>> getDependencies() {
|
||||
return dependencies;
|
||||
}
|
||||
}
|
||||
|
||||
@ -58,12 +58,7 @@ public class RealmSupplier implements Supplier<ManagedRealm, InjectRealm> {
|
||||
|
||||
@Override
|
||||
public boolean compatible(InstanceContext<ManagedRealm, InjectRealm> a, RequestedInstance<ManagedRealm, InjectRealm> b) {
|
||||
if (!a.getAnnotation().config().equals(b.getAnnotation().config())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
RealmConfigInterceptorHelper interceptor = new RealmConfigInterceptorHelper(a.getRegistry());
|
||||
return interceptor.sameInterceptors(a);
|
||||
return a.getAnnotation().config().equals(b.getAnnotation().config());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -59,12 +59,7 @@ public abstract class AbstractKeycloakServerSupplier implements Supplier<Keycloa
|
||||
|
||||
@Override
|
||||
public boolean compatible(InstanceContext<KeycloakServer, KeycloakIntegrationTest> a, RequestedInstance<KeycloakServer, KeycloakIntegrationTest> b) {
|
||||
if (!a.getAnnotation().config().equals(b.getAnnotation().config())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ServerConfigInterceptorHelper interceptor = new ServerConfigInterceptorHelper(a.getRegistry());
|
||||
return interceptor.sameInterceptors(a);
|
||||
return a.getAnnotation().config().equals(b.getAnnotation().config());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -274,6 +274,28 @@ public class RegistryTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIncompatibleParent() {
|
||||
MockParentSupplier.COMPATIBLE = false;
|
||||
RealmIncompatibleParentTest test = new RealmIncompatibleParentTest();
|
||||
registry.beforeEach(test);
|
||||
|
||||
MockParentValue parent1 = test.parent;
|
||||
MockChildValue child1 = test.child;
|
||||
|
||||
Assertions.assertNotNull(test.parent);
|
||||
Assertions.assertNotNull(test.child);
|
||||
|
||||
registry.afterEach();
|
||||
|
||||
registry.beforeEach(test);
|
||||
|
||||
Assertions.assertNotNull(test.parent);
|
||||
Assertions.assertNotEquals(parent1, test.parent);
|
||||
Assertions.assertNotNull(test.child);
|
||||
Assertions.assertNotEquals(child1, test.child);
|
||||
}
|
||||
|
||||
public static void assertRunning(Object... values) {
|
||||
MatcherAssert.assertThat(MockInstances.INSTANCES, Matchers.hasItems(values));
|
||||
MatcherAssert.assertThat(MockInstances.INSTANCES, Matchers.hasSize(values.length));
|
||||
@ -334,4 +356,15 @@ public class RegistryTest {
|
||||
@MockChildAnnotation(ref = "ABC", parentRef = "ABC")
|
||||
MockChildValue childABC;
|
||||
}
|
||||
|
||||
public static final class RealmIncompatibleParentTest {
|
||||
|
||||
@MockChildAnnotation
|
||||
MockChildValue child;
|
||||
|
||||
@MockParentAnnotation
|
||||
MockParentValue parent;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user