context.getRequest().getMethod(),
ReflectionHelper.objectToString(resource)));
}
}
final HttpResponseContext response = context.getResponse();
// Get the list of resource methods for the HTTP method
ResourceMethodListPair methods = map.get(request.getMethod());
if (methods == null) {
// No resource methods are found
response.setResponse(Responses.methodNotAllowed().
header("Allow", allow).build());
// Allow any further matching rules to be processed
return false;
}
// Get the list of matching methods
List<MediaType> accept = getSpecificAcceptableMediaTypes(
request.getAcceptableMediaTypes(),
methods.priorityMediaTypes);
final Matcher m = new Matcher();
final MatchStatus s = m.match(methods, request.getMediaType(), accept);
if (s == MatchStatus.MATCH) {
// If there is a match choose the first method
final ResourceMethod method = m.rmSelected;
if (method instanceof ViewResourceMethod) {
// Set the content type to the most acceptable
if (!m.mSelected.isWildcardType() &&
!m.mSelected.isWildcardSubtype()) {
response.getHttpHeaders().putSingle(HttpHeaders.CONTENT_TYPE, m.mSelected);
}
// Allow the view to be processed by the further matching view rule
return false;
// TODO what about resource specific request and response filters?
// Should the viewable rule be responsible for those declared on
// the class
}
// If a sub-resource method then need to push the resource
// (again) as as to keep in sync with the ancestor URIs
if (isSubResource) {
context.pushResource(resource);
// Set the template values
context.pushMatch(method.getTemplate(), method.getTemplate().getTemplateVariables());
}
if (context.isTracingEnabled()) {
if (isSubResource) {
context.trace(String.format("matched sub-resource method: @Path(\"%s\") %s",
method.getTemplate(),
method.getDispatcher()));
} else {
context.trace(String.format("matched resource method: %s",
method.getDispatcher()));
}
}
// Push the response filters
context.pushContainerResponseFilters(method.getResponseFilters());
ContainerRequest containerRequest = context.getContainerRequest();
// Process the request filter
if (!method.getRequestFilters().isEmpty()) {
for (ContainerRequestFilter f : method.getRequestFilters()) {
containerRequest = f.filter(containerRequest);
context.setContainerRequest(containerRequest);
}
}
context.pushMethod(method.getAbstractResourceMethod());
// Dispatch to the resource method
try {
dispatchingListener.onResourceMethod(Thread.currentThread().getId(), method.getAbstractResourceMethod());
SecurityContext sc = containerRequest.getSecurityContext();
if (sc instanceof SubjectSecurityContext) {
((SubjectSecurityContext) sc).doAsSubject(new PrivilegedAction() {
@Override
public Object run() {
method.getDispatcher().dispatch(resource, context);
return null;
}
});
} else {
method.getDispatcher().dispatch(resource, context);
}
} catch (RuntimeException e) {
if (m.rmSelected.isProducesDeclared() &&
!m.mSelected.isWildcardType() &&
!m.mSelected.isWildcardSubtype()) {
context.getProperties().put(CONTENT_TYPE_PROPERTY, m.mSelected);
}
throw e;
}
// If the content type is not explicitly set then set it
// to the selected media type, if a concrete media type
// and @Produces is declared on the resource method or the resource
// class
Object contentType = response.getHttpHeaders().getFirst(HttpHeaders.CONTENT_TYPE);
if (contentType == null &&
m.rmSelected.isProducesDeclared() &&
!m.mSelected.isWildcardType() &&
!m.mSelected.isWildcardSubtype()) {
response.getHttpHeaders().putSingle(HttpHeaders.CONTENT_TYPE, m.mSelected);
}
return true;
} else if (s == MatchStatus.NO_MATCH_FOR_CONSUME) {
response.setResponse(Responses.unsupportedMediaType().build());
// Allow any further matching rules to be processed
return false;
} else if (s == MatchStatus.NO_MATCH_FOR_PRODUCE) {
response.setResponse(Responses.notAcceptable().build());
// Allow any further matching rules to be processed
return false;
}
return true;