Skip to content

Commit

Permalink
Merge pull request #29044 from geoand/cache-type-polution
Browse files Browse the repository at this point in the history
  • Loading branch information
geoand authored Nov 4, 2022
2 parents 0516efc + 4334c57 commit b58b24f
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

import javax.interceptor.InvocationContext;

import io.quarkus.arc.AbstractAnnotationLiteral;
import io.quarkus.arc.ArcInvocationContext;

public class InterceptorBindings {
Expand All @@ -13,4 +14,14 @@ public class InterceptorBindings {
public static Set<Annotation> getInterceptorBindings(InvocationContext invocationContext) {
return (Set<Annotation>) invocationContext.getContextData().get(ArcInvocationContext.KEY_INTERCEPTOR_BINDINGS);
}

/**
* This method is just a convenience for getting a hold of {@link AbstractAnnotationLiteral}.
* See the Javadoc of the class for an explanation of the reasons it might be used {@link Annotation}.
*/
@SuppressWarnings("unchecked")
public static Set<AbstractAnnotationLiteral> getInterceptorBindingLiterals(InvocationContext invocationContext) {
return (Set<AbstractAnnotationLiteral>) invocationContext.getContextData()
.get(ArcInvocationContext.KEY_INTERCEPTOR_BINDINGS);
}
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
package io.quarkus.cache.runtime;

import java.lang.annotation.Annotation;
import java.util.Collections;
import java.util.List;
import java.util.Objects;

public class CacheInterceptionContext<T extends Annotation> {
// this should be <T extends Annotation> but that leads to type pollution
public class CacheInterceptionContext<T> {

private final List<T> interceptorBindings;
private final List<Short> cacheKeyParameterPositions;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

import org.jboss.logging.Logger;

import io.quarkus.arc.AbstractAnnotationLiteral;
import io.quarkus.arc.runtime.InterceptorBindings;
import io.quarkus.cache.Cache;
import io.quarkus.cache.CacheException;
Expand Down Expand Up @@ -47,8 +48,10 @@ public abstract class CacheInterceptor {
* interception is managed by another CDI interceptors implementation. It can happen for example while using caching
* annotations on a MicroProfile REST Client method. In that case, we have no other choice but to rely on reflection (with
* underlying synchronized blocks which are bad for performances) to retrieve the interceptor bindings.
*
* IMPORTANT: Normally <T> would be <T extends Annotation>, but that leads to type pollution
*/
protected <T extends Annotation> CacheInterceptionContext<T> getInterceptionContext(InvocationContext invocationContext,
protected <T> CacheInterceptionContext<T> getInterceptionContext(InvocationContext invocationContext,
Class<T> interceptorBindingClass, boolean supportsCacheKey) {
return getArcCacheInterceptionContext(invocationContext, interceptorBindingClass)
.orElseGet(new Supplier<CacheInterceptionContext<T>>() {
Expand All @@ -59,29 +62,31 @@ public CacheInterceptionContext<T> get() {
});
}

private <T extends Annotation> Optional<CacheInterceptionContext<T>> getArcCacheInterceptionContext(
@SuppressWarnings("unchecked")
private <T> Optional<CacheInterceptionContext<T>> getArcCacheInterceptionContext(
InvocationContext invocationContext, Class<T> interceptorBindingClass) {
Set<Annotation> bindings = InterceptorBindings.getInterceptorBindings(invocationContext);
if ((bindings == null) || bindings.isEmpty()) {
Set<AbstractAnnotationLiteral> bindings = InterceptorBindings.getInterceptorBindingLiterals(invocationContext);
if (bindings == null) {
LOGGER.trace("Interceptor bindings not found in ArC");
// This should only happen when the interception is not managed by Arc.
return Optional.empty();
}
List<T> interceptorBindings = new ArrayList<>(bindings.size() / 2); // initial capacity is a heuristic here...
List<Short> cacheKeyParameterPositions = new ArrayList<>(bindings.size() / 2);
for (Annotation binding : bindings) {
if (binding instanceof CacheKeyParameterPositions) {
List<T> interceptorBindings = new ArrayList<>();
List<Short> cacheKeyParameterPositions = new ArrayList<>();
for (AbstractAnnotationLiteral binding : bindings) {
if (binding.annotationType().isAssignableFrom(CacheKeyParameterPositions.class)) {
for (short position : ((CacheKeyParameterPositions) binding).value()) {
cacheKeyParameterPositions.add(position);
}
} else if (interceptorBindingClass.isInstance(binding)) {
interceptorBindings.add(cast(binding, interceptorBindingClass));
} else if (binding.annotationType().isAssignableFrom((interceptorBindingClass))) {
interceptorBindings.add((T) binding);
}
}
return Optional.of(new CacheInterceptionContext<>(interceptorBindings, cacheKeyParameterPositions));
}

private <T extends Annotation> CacheInterceptionContext<T> getNonArcCacheInterceptionContext(
@SuppressWarnings("unchecked")
private <T> CacheInterceptionContext<T> getNonArcCacheInterceptionContext(
InvocationContext invocationContext, Class<T> interceptorBindingClass, boolean supportsCacheKey) {
LOGGER.trace("Retrieving interceptor bindings using reflection");
List<T> interceptorBindings = new ArrayList<>();
Expand All @@ -94,7 +99,7 @@ private <T extends Annotation> CacheInterceptionContext<T> getNonArcCacheInterce
cacheKeyParameterPositions.add(position);
}
} else if (interceptorBindingClass.isInstance(annotation)) {
interceptorBindings.add(cast(annotation, interceptorBindingClass));
interceptorBindings.add((T) annotation);
}
}
if (supportsCacheKey && !cacheKeyParameterPositionsFound) {
Expand Down

0 comments on commit b58b24f

Please sign in to comment.