// Path: core/src/main/java/org/pac4j/jax/rs/helpers/RequestUserProfile.java
// public class RequestUserProfile {
// 
//     private final RequestPac4JSecurityContext context;
// 
//     public RequestUserProfile(RequestPac4JSecurityContext context) {
//         this.context = context;
//     }
// 
//     public Optional<UserProfile> profile() {
//         return context.context()
//                 .flatMap(Pac4JSecurityContext::getProfiles)
//                 .flatMap(ps -> ProfileHelper.flatIntoOneProfile(ps));
//     }
// }
// 
// Path: core/src/main/java/org/pac4j/jax/rs/helpers/RequestJaxRsContext.java
// public class RequestJaxRsContext {
// 
//     private final ProvidersContext providers;
//     private final ContainerRequestContext context;
// 
//     public RequestJaxRsContext(Providers providers, ContainerRequestContext context) {
//         this.providers = new ProvidersContext(providers);
//         this.context = context;
//     }
// 
//     public Optional<JaxRsContext> context() {
//         return new RequestPac4JSecurityContext(context).context().map(Pac4JSecurityContext::getContext);
//     }
// 
//     public JaxRsContext contextOrNew() {
//         return context().orElse(providers.resolveNotNull(JaxRsContextFactory.class).provides(context));
//     }
// }
// 
// Path: core/src/main/java/org/pac4j/jax/rs/helpers/RequestPac4JSecurityContext.java
// public class RequestPac4JSecurityContext {
// 
//     private final SecurityContext securityContext;
// 
//     public RequestPac4JSecurityContext(JaxRsContext context) {
//         this(context.getRequestContext());
//     }
// 
//     public RequestPac4JSecurityContext(ContainerRequestContext request) {
//         this(request.getSecurityContext());
//     }
// 
//     public RequestPac4JSecurityContext(SecurityContext securityContext) {
//         this.securityContext = securityContext;
//     }
// 
//     public Optional<Pac4JSecurityContext> context() {
//         if (securityContext instanceof Pac4JSecurityContext) {
//             return Optional.of((Pac4JSecurityContext) securityContext);
//         } else {
//             return Optional.empty();
//         }
//     }
// }
// 
// Path: core/src/main/java/org/pac4j/jax/rs/helpers/RequestProfileManager.java
// public class RequestProfileManager {
// 
//     private final RequestJaxRsContext context;
// 
//     public RequestProfileManager(RequestJaxRsContext context) {
//         this.context = context;
//     }
// 
//     public JaxRsProfileManager profileManager() {
//         return new JaxRsProfileManager(context.contextOrNew());
//     }
// }
// 
// Path: resteasy/src/main/java/org/pac4j/jax/rs/resteasy/helpers/RestEasyRequestContext.java
// public class RestEasyRequestContext extends RequestJaxRsContext {
// 
//     public RestEasyRequestContext(Providers providers) {
//         this(providers, ResteasyProviderFactory.getContextData(HttpRequest.class));
//     }
// 
//     public RestEasyRequestContext(Providers providers, HttpRequest request) {
//         super(providers,
//                 new RequestPac4JSecurityContext(ResteasyProviderFactory.getContextData(SecurityContext.class)).context()
//                         // if we went through a pac4j security filter
//                         .map(sc -> sc.getContext().getRequestContext())
//                         // if not, we create a new ContainerRequestContext
//                         .orElse(new PreMatchContainerRequestContext(request)));
//     }
// }


import java.lang.annotation.Annotation;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Type;
import java.util.Optional;
import java.util.function.Function;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.ext.Provider;
import org.jboss.resteasy.core.InjectorFactoryImpl;
import org.jboss.resteasy.core.ValueInjector;
import org.jboss.resteasy.spi.HttpRequest;
import org.jboss.resteasy.spi.HttpResponse;
import org.jboss.resteasy.spi.ResteasyProviderFactory;
import org.jboss.resteasy.spi.metadata.Parameter;
import org.jboss.resteasy.util.FindAnnotation;
import org.pac4j.jax.rs.annotations.Pac4JProfile;
import org.pac4j.jax.rs.annotations.Pac4JProfileManager;
import org.pac4j.jax.rs.helpers.RequestUserProfile;
import org.pac4j.jax.rs.helpers.RequestJaxRsContext;
import org.pac4j.jax.rs.helpers.RequestPac4JSecurityContext;
import org.pac4j.jax.rs.helpers.RequestProfileManager;
import org.pac4j.jax.rs.resteasy.helpers.RestEasyRequestContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
    public ValueInjector createParameterExtractor(Class injectTargetClass, AccessibleObject injectTarget, Class type,
            Type genericType, Annotation[] annotations, ResteasyProviderFactory factory) {
        final ValueInjector injector = getValueInjector(type, annotations, factory);
        if (injector != null)
            return injector;
        return super.createParameterExtractor(injectTargetClass, injectTarget, type, genericType, annotations, factory);
    }

    @Override
    public ValueInjector createParameterExtractor(Parameter parameter, ResteasyProviderFactory providerFactory) {
        final ValueInjector injector = getValueInjector(parameter.getType(), parameter.getAnnotations(),
                providerFactory);
        if (injector != null)
            return injector;
        return super.createParameterExtractor(parameter, providerFactory);
    }

    private ValueInjector getValueInjector(Class type, Annotation[] annotations,
            ResteasyProviderFactory providerFactory) {
        if (FindAnnotation.findAnnotation(annotations, Pac4JProfile.class) != null) {
            if (type.equals(Optional.class)) {
                return new Pac4JValueInjector(providerFactory, rc -> rc.context()
                        .flatMap(c -> new RequestUserProfile(new RequestPac4JSecurityContext(c)).profile()));
            } else {
                return new Pac4JValueInjector(providerFactory,
                        rc -> rc.context()
                                .flatMap(c -> new RequestUserProfile(new RequestPac4JSecurityContext(c)).profile())
                                .orElseThrow(() -> {
                                    LOG.debug(
                                            "Cannot inject a Pac4j profile into an unauthenticated request, responding with 401");
// Path: core/src/main/java/org/pac4j/jax/rs/helpers/RequestUserProfile.java
// public class RequestUserProfile {
// 
//     private final RequestPac4JSecurityContext context;
// 
//     public RequestUserProfile(RequestPac4JSecurityContext context) {
//         this.context = context;
//     }
// 
//     public Optional<UserProfile> profile() {
//         return context.context()
//                 .flatMap(Pac4JSecurityContext::getProfiles)
//                 .flatMap(ps -> ProfileHelper.flatIntoOneProfile(ps));
//     }
// }
// 
// Path: core/src/main/java/org/pac4j/jax/rs/helpers/RequestJaxRsContext.java
// public class RequestJaxRsContext {
// 
//     private final ProvidersContext providers;
//     private final ContainerRequestContext context;
// 
//     public RequestJaxRsContext(Providers providers, ContainerRequestContext context) {
//         this.providers = new ProvidersContext(providers);
//         this.context = context;
//     }
// 
//     public Optional<JaxRsContext> context() {
//         return new RequestPac4JSecurityContext(context).context().map(Pac4JSecurityContext::getContext);
//     }
// 
//     public JaxRsContext contextOrNew() {
//         return context().orElse(providers.resolveNotNull(JaxRsContextFactory.class).provides(context));
//     }
// }
// 
// Path: core/src/main/java/org/pac4j/jax/rs/helpers/RequestPac4JSecurityContext.java
// public class RequestPac4JSecurityContext {
// 
//     private final SecurityContext securityContext;
// 
//     public RequestPac4JSecurityContext(JaxRsContext context) {
//         this(context.getRequestContext());
//     }
// 
//     public RequestPac4JSecurityContext(ContainerRequestContext request) {
//         this(request.getSecurityContext());
//     }
// 
//     public RequestPac4JSecurityContext(SecurityContext securityContext) {
//         this.securityContext = securityContext;
//     }
// 
//     public Optional<Pac4JSecurityContext> context() {
//         if (securityContext instanceof Pac4JSecurityContext) {
//             return Optional.of((Pac4JSecurityContext) securityContext);
//         } else {
//             return Optional.empty();
//         }
//     }
// }
// 
// Path: core/src/main/java/org/pac4j/jax/rs/helpers/RequestProfileManager.java
// public class RequestProfileManager {
// 
//     private final RequestJaxRsContext context;
// 
//     public RequestProfileManager(RequestJaxRsContext context) {
//         this.context = context;
//     }
// 
//     public JaxRsProfileManager profileManager() {
//         return new JaxRsProfileManager(context.contextOrNew());
//     }
// }
// 
// Path: resteasy/src/main/java/org/pac4j/jax/rs/resteasy/helpers/RestEasyRequestContext.java
// public class RestEasyRequestContext extends RequestJaxRsContext {
// 
//     public RestEasyRequestContext(Providers providers) {
//         this(providers, ResteasyProviderFactory.getContextData(HttpRequest.class));
//     }
// 
//     public RestEasyRequestContext(Providers providers, HttpRequest request) {
//         super(providers,
//                 new RequestPac4JSecurityContext(ResteasyProviderFactory.getContextData(SecurityContext.class)).context()
//                         // if we went through a pac4j security filter
//                         .map(sc -> sc.getContext().getRequestContext())
//                         // if not, we create a new ContainerRequestContext
//                         .orElse(new PreMatchContainerRequestContext(request)));
//     }
// }


// Path: resteasy/src/main/java/org/pac4j/jax/rs/resteasy/features/Pac4JProfileInjectorFactory.java
import java.lang.annotation.Annotation;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Type;
import java.util.Optional;
import java.util.function.Function;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.ext.Provider;
import org.jboss.resteasy.core.InjectorFactoryImpl;
import org.jboss.resteasy.core.ValueInjector;
import org.jboss.resteasy.spi.HttpRequest;
import org.jboss.resteasy.spi.HttpResponse;
import org.jboss.resteasy.spi.ResteasyProviderFactory;
import org.jboss.resteasy.spi.metadata.Parameter;
import org.jboss.resteasy.util.FindAnnotation;
import org.pac4j.jax.rs.annotations.Pac4JProfile;
import org.pac4j.jax.rs.annotations.Pac4JProfileManager;
import org.pac4j.jax.rs.helpers.RequestUserProfile;
import org.pac4j.jax.rs.helpers.RequestJaxRsContext;
import org.pac4j.jax.rs.helpers.RequestPac4JSecurityContext;
import org.pac4j.jax.rs.helpers.RequestProfileManager;
import org.pac4j.jax.rs.resteasy.helpers.RestEasyRequestContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

    public ValueInjector createParameterExtractor(Class injectTargetClass, AccessibleObject injectTarget, Class type,
            Type genericType, Annotation[] annotations, ResteasyProviderFactory factory) {
        final ValueInjector injector = getValueInjector(type, annotations, factory);
        if (injector != null)
            return injector;
        return super.createParameterExtractor(injectTargetClass, injectTarget, type, genericType, annotations, factory);
    }

    @Override
    public ValueInjector createParameterExtractor(Parameter parameter, ResteasyProviderFactory providerFactory) {
        final ValueInjector injector = getValueInjector(parameter.getType(), parameter.getAnnotations(),
                providerFactory);
        if (injector != null)
            return injector;
        return super.createParameterExtractor(parameter, providerFactory);
    }

    private ValueInjector getValueInjector(Class type, Annotation[] annotations,
            ResteasyProviderFactory providerFactory) {
        if (FindAnnotation.findAnnotation(annotations, Pac4JProfile.class) != null) {
            if (type.equals(Optional.class)) {
                return new Pac4JValueInjector(providerFactory, rc -> rc.context()
                        .flatMap(c -> new RequestUserProfile(new RequestPac4JSecurityContext(c)).profile()));
            } else {
                return new Pac4JValueInjector(providerFactory,
                        rc -> rc.context()
                                .flatMap(c -> new RequestUserProfile(new RequestPac4JSecurityContext(c)).profile())
                                .orElseThrow(() -> {
                                    LOG.debug(
                                            "Cannot inject a Pac4j profile into an unauthenticated request, responding with 401");
                                    return new WebApplicationException(401);