}
@SuppressWarnings("unchecked")
public Object invoke(Exchange exchange, Object request, Object resourceObject) {
final OperationResourceInfo ori = exchange.get(OperationResourceInfo.class);
final ClassResourceInfo cri = ori.getClassResourceInfo();
final Message inMessage = exchange.getInMessage();
final ProviderFactory providerFactory = ProviderFactory.getInstance(inMessage);
boolean wasSuspended = exchange.remove(REQUEST_WAS_SUSPENDED) != null;
if (!wasSuspended) {
pushOntoStack(ori, ClassHelper.getRealClass(resourceObject), inMessage);
}
final boolean contextsAvailable = cri.contextsAvailable();
final boolean paramsAvailable = cri.paramsAvailable();
if (contextsAvailable || paramsAvailable) {
Object realResourceObject = ClassHelper.getRealObject(resourceObject);
if (paramsAvailable) {
JAXRSUtils.injectParameters(ori, realResourceObject, inMessage);
}
if (contextsAvailable) {
InjectionUtils.injectContexts(realResourceObject, cri, inMessage);
}
}
if (cri.isRoot()) {
ProviderInfo<?> appProvider =
(ProviderInfo<?>)exchange.getEndpoint().get(Application.class.getName());
if (appProvider != null) {
InjectionUtils.injectContexts(appProvider.getProvider(),
appProvider,
inMessage);
}
}
Method resourceMethod = cri.getMethodDispatcher().getMethod(ori);
Method methodToInvoke = null;
if (Proxy.class.isInstance(resourceObject)) {
methodToInvoke = cri.getMethodDispatcher().getProxyMethod(resourceMethod);
if (methodToInvoke == null) {
methodToInvoke = InjectionUtils.checkProxy(resourceMethod, resourceObject);
cri.getMethodDispatcher().addProxyMethod(resourceMethod, methodToInvoke);
}
} else {
methodToInvoke = resourceMethod;
}
List<Object> params = null;
if (request instanceof List) {
params = CastUtils.cast((List<?>)request);
} else if (request != null) {
params = new MessageContentsList(request);
}
Object result = null;
ClassLoaderHolder contextLoader = null;
try {
if (setServiceLoaderAsContextLoader(inMessage)) {
contextLoader = ClassLoaderUtils
.setThreadContextClassloader(resourceObject.getClass().getClassLoader());
}
AsyncResponseImpl asyncResponse = null;
if (!ori.isSubResourceLocator()) {
asyncResponse = (AsyncResponseImpl)inMessage.get(AsyncResponse.class);
}
result = invoke(exchange, resourceObject, methodToInvoke, params);
if (asyncResponse != null) {
if (!asyncResponse.isSuspended() && !asyncResponse.isResumedByApplication()) {
asyncResponse.suspendContinuation();
providerFactory.clearThreadLocalProxies();
} else {
result = handleAsyncResponse(exchange, asyncResponse.getResponseObject());
}
}
} catch (Fault ex) {
return handleFault(ex, inMessage, cri, methodToInvoke);
} finally {
exchange.put(LAST_SERVICE_OBJECT, resourceObject);
if (contextLoader != null) {
contextLoader.reset();
}
}
ClassResourceInfo subCri = null;
if (ori.isSubResourceLocator()) {
try {
MultivaluedMap<String, String> values = getTemplateValues(inMessage);
String subResourcePath = values.getFirst(URITemplate.FINAL_MATCH_GROUP);
String httpMethod = (String)inMessage.get(Message.HTTP_REQUEST_METHOD);
String contentType = (String)inMessage.get(Message.CONTENT_TYPE);
if (contentType == null) {
contentType = "*/*";
}
List<MediaType> acceptContentType =
(List<MediaType>)exchange.get(Message.ACCEPT_CONTENT_TYPE);
result = checkResultObject(result, subResourcePath);
subCri = cri.getSubResource(methodToInvoke.getReturnType(),
ClassHelper.getRealClass(result), result);
if (subCri == null) {
org.apache.cxf.common.i18n.Message errorM =
new org.apache.cxf.common.i18n.Message("NO_SUBRESOURCE_FOUND",
BUNDLE,
subResourcePath);
LOG.severe(errorM.toString());
throw ExceptionUtils.toNotFoundException(null, null);
}
OperationResourceInfo subOri = JAXRSUtils.findTargetMethod(subCri,
inMessage,
httpMethod,
values,
contentType,
acceptContentType,
true);
exchange.put(OperationResourceInfo.class, subOri);
inMessage.put(URITemplate.TEMPLATE_PARAMETERS, values);
if (JAXRSUtils.runContainerRequestFilters(providerFactory,
inMessage,
false, subOri.getNameBindings())) {
return new MessageContentsList(exchange.get(Response.class));
}
// work out request parameters for the sub-resource class. Here we
// presume InputStream has not been consumed yet by the root resource class.