io.smallrye.jwt.auth.cdi.ProviderExtensionSupport Maven / Gradle / Ivy
package io.smallrye.jwt.auth.cdi;
import java.lang.annotation.Annotation;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.HashSet;
import java.util.Optional;
import java.util.Set;
import jakarta.enterprise.event.Observes;
import jakarta.enterprise.inject.spi.BeanAttributes;
import jakarta.enterprise.inject.spi.InjectionPoint;
import jakarta.enterprise.inject.spi.ProcessBeanAttributes;
import jakarta.enterprise.inject.spi.ProcessInjectionPoint;
import jakarta.inject.Provider;
import org.eclipse.microprofile.jwt.Claim;
import org.eclipse.microprofile.jwt.Claims;
/**
* Support for {@linkplain Provider} injection points annotated with {@linkplain Claim}.
*/
public class ProviderExtensionSupport {
/**
* Replace the general producer method BeanAttributes with one bound to the collected injection site
* types to properly reflect all of the type locations the producer method applies to.
*
* @param pba the ProcessBeanAttributes
* @see ProviderBeanAttributes
*/
public void addTypeToClaimProducer(@Observes ProcessBeanAttributes pba) {
if (!providerOptionalTypes.isEmpty() && pba.getAnnotated().isAnnotationPresent(Claim.class)) {
Claim claim = pba.getAnnotated().getAnnotation(Claim.class);
if (claim.value().length() == 0 && claim.standard() == Claims.UNKNOWN) {
CDILogging.log.addTypeToClaimProducer(pba.getAnnotated());
BeanAttributes delegate = pba.getBeanAttributes();
if (delegate.getTypes().contains(Optional.class)) {
pba.setBeanAttributes(new ProviderBeanAttributes(delegate, providerOptionalTypes, providerQualifiers));
}
}
}
}
/**
* Collect the types of all {@linkplain Provider} injection points annotated with {@linkplain Claim}.
*
* @param pip - the injection point event information
*/
void processClaimProviderInjections(@Observes ProcessInjectionPoint, ? extends Provider> pip) {
CDILogging.log.pip(pip.getInjectionPoint());
final InjectionPoint ip = pip.getInjectionPoint();
if (ip.getAnnotated().isAnnotationPresent(Claim.class)) {
Claim claim = ip.getAnnotated().getAnnotation(Claim.class);
if (claim.value().length() == 0 && claim.standard() == Claims.UNKNOWN) {
pip.addDefinitionError(CDIMessages.msg.claimHasNoNameOrValidStandardEnumSetting(ip));
}
boolean usesEnum = claim.standard() != Claims.UNKNOWN;
final String claimName = usesEnum ? claim.standard().name() : claim.value();
CDILogging.log.checkingProviderClaim(claimName, ip);
Type matchType = ip.getType();
// The T from the Provider injection site
Type actualType = ((ParameterizedType) matchType).getActualTypeArguments()[0];
// Don't add Optional or JsonValue as this is handled specially
if (isOptional(actualType)) {
// Validate that this is not an Optional
Type innerType = ((ParameterizedType) actualType).getActualTypeArguments()[0];
if (!isJson(innerType)) {
providerOptionalTypes.add(actualType);
providerQualifiers.add(claim);
}
}
}
}
private static boolean isOptional(Type type) {
return type.getTypeName().startsWith(Optional.class.getTypeName());
}
private static boolean isJson(Type type) {
return type.getTypeName().startsWith("jakarta.json.Json");
}
private Set providerOptionalTypes = new HashSet<>();
private Set providerQualifiers = new HashSet<>();
/**
* An implementation of BeanAttributes that wraps the generic producer BeanAttributes
*/
public static class ProviderBeanAttributes implements BeanAttributes