package io.quarkus.resteasy.runtime;

import java.lang.reflect.Method;
import java.util.concurrent.ExecutionException;

import javax.annotation.Priority;
import javax.ws.rs.Priorities;
import javax.ws.rs.core.Response;
import javax.ws.rs.ext.ExceptionMapper;
import javax.ws.rs.ext.Provider;

import org.jboss.logging.Logger;
import org.jboss.resteasy.core.ResteasyContext;

import io.quarkus.security.UnauthorizedException;
import io.quarkus.vertx.http.runtime.security.ChallengeData;
import io.quarkus.vertx.http.runtime.security.HttpAuthenticator;
import io.vertx.ext.web.RoutingContext;

/**
 * @author Michal Szynkiewicz, michal.l.szynkiewicz@gmail.com
 *         <br>
 *         Date: 05/10/2019
 */
@Provider
@Priority(Priorities.USER + 1)
public class UnauthorizedExceptionMapper implements ExceptionMapper<UnauthorizedException> {

    private static final Logger log = Logger.getLogger(UnauthorizedExceptionMapper.class.getName());

    //Servlet API may not be present
    private static final Class<?> HTTP_SERVLET_REQUEST;
    private static final Class<?> HTTP_SERVLET_RESPONSE;
    private static final Method AUTHENTICATE;

    static {
        Class<?> httpServletReq = null;
        Class<?> httpServletResp = null;
        Method auth = null;
        try {
            httpServletReq = Class.forName("javax.servlet.http.HttpServletRequest");
            httpServletResp = Class.forName("javax.servlet.http.HttpServletResponse");
            auth = httpServletReq.getMethod("authenticate", httpServletResp);
        } catch (Exception ignored) {

        }
        AUTHENTICATE = auth;
        HTTP_SERVLET_REQUEST = httpServletReq;
        HTTP_SERVLET_RESPONSE = httpServletResp;
    }

    @Override
    public Response toResponse(UnauthorizedException exception) {
        if (HTTP_SERVLET_REQUEST != null) {
            Object httpServletRequest = ResteasyContext.getContextData(HTTP_SERVLET_REQUEST);
            if (httpServletRequest != null) {
                Object httpServletResponse = ResteasyContext.getContextData(HTTP_SERVLET_RESPONSE);
                try {
                    AUTHENTICATE.invoke(httpServletRequest, httpServletResponse);
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
            }
        }
        RoutingContext context = ResteasyContext.getContextData(RoutingContext.class);
        if (context != null) {
            HttpAuthenticator authenticator = context.get(HttpAuthenticator.class.getName());
            if (authenticator != null) {
                try {
                    ChallengeData challengeData = authenticator.getChallenge(context)
                            .toCompletableFuture()
                            .get();
                    Response.ResponseBuilder status = Response.status(challengeData.status);
                    if (challengeData.headerName != null) {
                        status.header(challengeData.headerName.toString(), challengeData.headerContent);
                    }
                    return status.build();
                } catch (InterruptedException | ExecutionException e) {
                    log.error("Failed to read challenge data for unauthorized response", e);
                    return Response.status(401).entity("Not authorized").build();
                }
            }
        }
        return Response.status(401).entity("Not authorized").build();
    }
}

@@ -35,41 +35,8 @@
 e;%0A%0A
-import java.lang.reflect.Method;%0A
 impo
@@ -114,16 +114,56 @@
 iority;%0A
+import javax.enterprise.inject.spi.CDI;%0A
 import j
@@ -329,56 +329,8 @@
 ger;
-%0Aimport org.jboss.resteasy.core.ResteasyContext;
 %0A%0Aim
@@ -377,16 +377,74 @@
 eption;%0A
+import io.quarkus.vertx.http.runtime.CurrentVertxRequest;%0A
 import i
@@ -961,759 +961,291 @@
     
-//Servlet API may not be present%0A    private static final Class%3C?%3E HTTP_SERVLET_REQUEST;%0A    private static final Class%3C?%3E HTTP_SERVLET_RESPONSE;%0A    private static final Method AUTHENTICATE;%0A%0A    static %7B%0A        Class%3C?%3E httpServletReq = null;%0A        Class%3C?%3E httpServletResp = null;%0A        Method auth = null;%0A        try %7B%0A            httpServletReq = Class.forName(%22javax.servlet.http.HttpServletRequest%22);%0A            httpServletResp = Class.forName(%22javax.servlet.http.HttpServletResponse%22);%0A            auth = httpServletReq.getMethod(%22authenticate%22, httpServletResp);%0A        %7D catch (Exception ignored) %7B%0A%0A        %7D%0A        AUTHENTICATE = auth;%0A        HTTP_SERVLET_REQUEST = httpServletReq;%0A        HTTP_SERVLET_RESPONSE = httpServletResp
+private volatile CurrentVertxRequest currentVertxRequest;%0A%0A    CurrentVertxRequest currentVertxRequest() %7B%0A        if (currentVertxRequest == null) %7B%0A            currentVertxRequest = CDI.current().select(CurrentVertxRequest.class).get();%0A        %7D%0A        return currentVertxRequest
 ;%0A  
@@ -1341,605 +1341,66 @@
     
-if (HTTP_SERVLET_REQUEST != null) %7B%0A            Object httpServletRequest = ResteasyContext.getContextData(HTTP_SERVLET_REQUEST);%0A            if (httpServletReques
+RoutingContext contex
 t 
-!
 = 
-null) %7B%0A                Object httpServletResponse = ResteasyContext.getContextData(HTTP_SERVLET_RESPONSE);%0A                try %7B%0A                    AUTHENTICATE.invoke(httpServletRequest, httpServletResponse);%0A                %7D catch (Exception e) %7B%0A                    throw new RuntimeException(e);%0A                %7D%0A            %7D%0A        %7D%0A        RoutingContext context = ResteasyContext.getContextData(RoutingContext.class
+currentVertxRequest().getCurrent(
 );%0A 

Remove Servlet specific auth from JAX-RS