org.jboss.resteasy.reactive.server.handlers.ResourceLocatorHandler Maven / Gradle / Ivy
package org.jboss.resteasy.reactive.server.handlers;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import jakarta.ws.rs.HttpMethod;
import jakarta.ws.rs.WebApplicationException;
import jakarta.ws.rs.container.CompletionCallback;
import jakarta.ws.rs.core.Response;
import org.jboss.resteasy.reactive.server.core.ResteasyReactiveRequestContext;
import org.jboss.resteasy.reactive.server.mapping.RequestMapper;
import org.jboss.resteasy.reactive.server.mapping.RuntimeResource;
import org.jboss.resteasy.reactive.server.spi.ServerRestHandler;
import org.jboss.resteasy.reactive.spi.BeanFactory;
public class ResourceLocatorHandler implements ServerRestHandler {
private final Map, Map>> resourceLocatorHandlers = new ConcurrentHashMap<>();
private final Function, BeanFactory.BeanInstance>> instantiator;
public ResourceLocatorHandler(Function, BeanFactory.BeanInstance>> instantiator) {
this.instantiator = instantiator;
}
@Override
public void handle(ResteasyReactiveRequestContext requestContext) throws Exception {
Object locator = requestContext.getResult();
if (locator == null) {
return;
}
Class> locatorClass;
if (locator instanceof Class) {
locatorClass = (Class>) locator;
BeanFactory.BeanInstance> instance = instantiator.apply(locatorClass);
requestContext.registerCompletionCallback(new CompletionCallback() {
@Override
public void onComplete(Throwable throwable) {
instance.close();
}
});
locator = instance.getInstance();
if (locator == null) {
//TODO: we should make sure ArC always picks up these classes and makes them beans
//but until we get a bug report about it lets not worry for now, as I don't think anyone
//really uses this
locator = locatorClass.getDeclaredConstructor().newInstance();
}
} else {
locatorClass = locator.getClass();
}
Map> target = findTarget(locatorClass);
if (target == null) {
throw new RuntimeException("Resource locator method returned object that was not a resource: " + locator);
}
RequestMapper mapper = target.get(requestContext.getMethod());
boolean hadNullMethodMapper = false;
if (mapper == null) {
String requestMethod = requestContext.getMethod();
if (requestMethod.equals(HttpMethod.HEAD)) {
mapper = target.get(HttpMethod.GET);
} else if (requestMethod.equals(HttpMethod.OPTIONS)) {
Set allowedMethods = new HashSet<>();
for (String method : target.keySet()) {
if (method == null) {
continue;
}
allowedMethods.add(method);
}
allowedMethods.add(HttpMethod.OPTIONS);
allowedMethods.add(HttpMethod.HEAD);
requestContext.abortWith(Response.ok().allow(allowedMethods).build());
return;
}
if (mapper == null) {
mapper = target.get(null); //another layer of resource locators maybe
// we set this without checking if we matched, but we only use it after
// we check for a null mapper, so by the time we use it, it must have meant that
// we had a matcher for a null method
hadNullMethodMapper = true;
}
}
if (mapper == null) {
throw new WebApplicationException(Response.status(Response.Status.METHOD_NOT_ALLOWED.getStatusCode()).build());
}
RequestMapper.RequestMatch res = mapper
.map(requestContext.getRemaining().isEmpty() ? "/" : requestContext.getRemaining());
if (res == null) {
// the TCK checks for both these return statuses
if (hadNullMethodMapper)
throw new WebApplicationException(Response.status(Response.Status.METHOD_NOT_ALLOWED.getStatusCode()).build());
throw new WebApplicationException(Response.status(Response.Status.NOT_FOUND.getStatusCode()).build());
}
requestContext.saveUriMatchState();
requestContext.setRemaining(res.remaining);
requestContext.setEndpointInstance(locator);
requestContext.setResult(null);
requestContext.restart(res.value, true);
requestContext.setMaxPathParams(res.pathParamValues.length);
for (int i = 0; i < res.pathParamValues.length; ++i) {
String pathParamValue = res.pathParamValues[i];
if (pathParamValue == null) {
break;
}
requestContext.setPathParamValue(i, pathParamValue);
}
}
private Map> findTarget(Class> locatorClass) {
if (locatorClass == Object.class || locatorClass == null) {
return null;
}
Map> res = resourceLocatorHandlers.get(locatorClass);
if (res != null) {
return res;
}
//not found, so we need to compute one
//we look through all interfaces and superclasses
//we need to do this as it could implement multiple interfaces
List
© 2015 - 2024 Weber Informatics LLC | Privacy Policy