use of com.linkedin.restli.internal.server.ServerResourceContext in project rest.li by linkedin.
the class TestRestLiResponseHandler method buildRoutingResult.
private final RoutingResult buildRoutingResult(ResourceMethod resourceMethod, RestRequest request, Map<String, String> acceptHeaders) throws SecurityException, NoSuchMethodException, RestLiSyntaxException {
Method method = ProjectionTestFixture.class.getMethod("batchGet", Set.class);
ResourceModel model = RestLiTestHelper.buildResourceModel(StatusCollectionResource.class);
ResourceMethodDescriptor methodDescriptor = ResourceMethodDescriptor.createForRestful(resourceMethod, method, InterfaceType.SYNC);
model.addResourceMethodDescriptor(methodDescriptor);
ServerResourceContext context = new ResourceContextImpl(new PathKeysImpl(), request, new RequestContext());
RestUtils.validateRequestHeadersAndUpdateResourceContext(acceptHeaders, context);
return new RoutingResult(context, methodDescriptor);
}
use of com.linkedin.restli.internal.server.ServerResourceContext in project rest.li by linkedin.
the class TestRestLiResponseHandler method invokeResponseHandler.
private RestResponse invokeResponseHandler(String uri, ResourceMethodDescriptor methodDescriptor, Object result, Map<String, String> headers, ProtocolVersion protocolVersion) throws IOException, URISyntaxException, RestLiSyntaxException {
RestRequest request = buildRequest(uri, headers, protocolVersion);
ServerResourceContext context = new ResourceContextImpl(new PathKeysImpl(), request, new RequestContext());
RestUtils.validateRequestHeadersAndUpdateResourceContext(headers, context);
RoutingResult routingResult = new RoutingResult(context, methodDescriptor);
RestResponse response;
response = _responseHandler.buildResponse(request, routingResult, result);
return response;
}
use of com.linkedin.restli.internal.server.ServerResourceContext in project rest.li by linkedin.
the class RestLiServer method handleResourceRequest.
private void handleResourceRequest(final RestRequest request, final RequestContext requestContext, final RequestExecutionCallback<RestResponse> callback, final RestLiAttachmentReader attachmentReader, final boolean isDebugMode) {
try {
ensureRequestUsesValidRestliProtocol(request);
} catch (RestLiServiceException e) {
respondWithPreRoutingError(e, request, attachmentReader, callback);
return;
}
final RoutingResult method;
try {
method = _router.process(request, requestContext, attachmentReader);
} catch (Exception e) {
respondWithPreRoutingError(e, request, attachmentReader, callback);
return;
}
final RequestExecutionCallback<RestResponse> wrappedCallback = notifyInvokeAwares(method, callback);
RequestExecutionReportBuilder requestExecutionReportBuilder = null;
if (isDebugMode) {
requestExecutionReportBuilder = new RequestExecutionReportBuilder();
}
final FilterRequestContextInternal filterContext = new FilterRequestContextInternalImpl((ServerResourceContext) method.getContext(), method.getResourceMethod());
RestLiArgumentBuilder adapter;
try {
RestUtils.validateRequestHeadersAndUpdateResourceContext(request.getHeaders(), (ServerResourceContext) method.getContext());
adapter = buildRestLiArgumentBuilder(method, _errorResponseBuilder);
filterContext.setRequestData(adapter.extractRequestData(method, request));
} catch (Exception e) {
// would not trigger response filters because request filters haven't run yet
wrappedCallback.onError(e, requestExecutionReportBuilder == null ? null : requestExecutionReportBuilder.build(), ((ServerResourceContext) method.getContext()).getRequestAttachmentReader(), null);
return;
}
RestLiFilterResponseContextFactory<Object> filterResponseContextFactory = new RestLiFilterResponseContextFactory<Object>(request, method, _responseHandler);
FilterChainCallback filterChainCallback = new FilterChainCallbackImpl(method, _methodInvoker, adapter, requestExecutionReportBuilder, attachmentReader, _responseHandler, wrappedCallback);
RestLiFilterChain filterChain = new RestLiFilterChain(_filters, filterChainCallback);
filterChain.onRequest(filterContext, filterResponseContextFactory);
}
use of com.linkedin.restli.internal.server.ServerResourceContext in project rest.li by linkedin.
the class BatchGetResponseBuilder method buildRestLiResponseData.
@Override
public RestLiResponseData buildRestLiResponseData(RestRequest request, RoutingResult routingResult, Object result, Map<String, String> headers, List<HttpCookie> cookies) {
@SuppressWarnings({ "unchecked" }) final Map<Object, RecordTemplate> /** constrained by signature of {@link com.linkedin.restli.server.resources.CollectionResource#batchGet(java.util.Set)} */
entities = (Map<Object, RecordTemplate>) result;
Map<Object, HttpStatus> statuses = Collections.emptyMap();
Map<Object, RestLiServiceException> serviceErrors = Collections.emptyMap();
if (result instanceof BatchResult) {
@SuppressWarnings({ "unchecked" }) final BatchResult<Object, RecordTemplate> /** constrained by signature of {@link com.linkedin.restli.server.resources.CollectionResource#batchGet(java.util.Set)} */
batchResult = (BatchResult<Object, RecordTemplate>) result;
statuses = batchResult.getStatuses();
serviceErrors = batchResult.getErrors();
}
try {
if (statuses.containsKey(null)) {
throw new RestLiServiceException(HttpStatus.S_500_INTERNAL_SERVER_ERROR, "Unexpected null encountered. Null key inside of a Map returned by the resource method: " + routingResult.getResourceMethod());
}
} catch (NullPointerException e) {
// Some map implementations will throw an NPE if they do not support null keys.
// In this case it is OK to swallow this exception and proceed.
}
Map<Object, BatchResponseEntry> batchResult = new HashMap<Object, BatchResponseEntry>(entities.size() + serviceErrors.size());
for (Map.Entry<Object, RecordTemplate> entity : entities.entrySet()) {
if (entity.getKey() == null) {
throw new RestLiServiceException(HttpStatus.S_500_INTERNAL_SERVER_ERROR, "Unexpected null encountered. Null key inside of a Map returned by the resource method: " + routingResult.getResourceMethod());
}
Object finalKey = ResponseUtils.translateCanonicalKeyToAlternativeKeyIfNeeded(entity.getKey(), routingResult);
final DataMap projectedData = RestUtils.projectFields(entity.getValue().data(), routingResult.getContext().getProjectionMode(), routingResult.getContext().getProjectionMask());
AnyRecord anyRecord = new AnyRecord(projectedData);
batchResult.put(finalKey, new BatchResponseEntry(statuses.get(entity.getKey()), anyRecord));
}
for (Map.Entry<Object, RestLiServiceException> entity : serviceErrors.entrySet()) {
if (entity.getKey() == null || entity.getValue() == null) {
throw new RestLiServiceException(HttpStatus.S_500_INTERNAL_SERVER_ERROR, "Unexpected null encountered. Null key inside of a Map returned by the resource method: " + routingResult.getResourceMethod());
}
Object finalKey = ResponseUtils.translateCanonicalKeyToAlternativeKeyIfNeeded(entity.getKey(), routingResult);
batchResult.put(finalKey, new BatchResponseEntry(statuses.get(entity.getKey()), entity.getValue()));
}
final Map<Object, RestLiServiceException> contextErrors = ((ServerResourceContext) routingResult.getContext()).getBatchKeyErrors();
for (Map.Entry<Object, RestLiServiceException> entry : contextErrors.entrySet()) {
Object finalKey = ResponseUtils.translateCanonicalKeyToAlternativeKeyIfNeeded(entry.getKey(), routingResult);
batchResult.put(finalKey, new BatchResponseEntry(statuses.get(entry.getKey()), entry.getValue()));
}
RestLiResponseDataImpl responseData = new RestLiResponseDataImpl(HttpStatus.S_200_OK, headers, cookies);
responseData.setResponseEnvelope(new BatchGetResponseEnvelope(batchResult, responseData));
return responseData;
}
use of com.linkedin.restli.internal.server.ServerResourceContext in project rest.li by linkedin.
the class ArgumentBuilder method buildArgs.
/**
* Build arguments for resource method invocation. Combines various types of arguments
* into a single array.
*
* @param positionalArguments pass-through arguments coming from
* {@link RestLiArgumentBuilder}
* @param resourceMethod the resource method
* @param context {@link ResourceContext}
* @param template {@link DynamicRecordTemplate}
* @return array of method argument for method invocation.
*/
@SuppressWarnings("deprecation")
public static Object[] buildArgs(final Object[] positionalArguments, final ResourceMethodDescriptor resourceMethod, final ResourceContext context, final DynamicRecordTemplate template) {
List<Parameter<?>> parameters = resourceMethod.getParameters();
Object[] arguments = Arrays.copyOf(positionalArguments, parameters.size());
fixUpComplexKeySingletonArraysInArguments(arguments);
boolean attachmentsDesired = false;
for (int i = positionalArguments.length; i < parameters.size(); ++i) {
Parameter<?> param = parameters.get(i);
try {
if (param.getParamType() == Parameter.ParamType.KEY || param.getParamType() == Parameter.ParamType.ASSOC_KEY_PARAM) {
Object value = context.getPathKeys().get(param.getName());
if (value != null) {
arguments[i] = value;
continue;
}
} else if (param.getParamType() == Parameter.ParamType.CALLBACK) {
continue;
} else if (param.getParamType() == Parameter.ParamType.PARSEQ_CONTEXT_PARAM || param.getParamType() == Parameter.ParamType.PARSEQ_CONTEXT) {
// don't know what to fill in yet
continue;
} else if (param.getParamType() == Parameter.ParamType.HEADER) {
HeaderParam headerParam = param.getAnnotations().get(HeaderParam.class);
String value = context.getRequestHeaders().get(headerParam.value());
arguments[i] = value;
continue;
} else //we must evaluate based on the param type (annotation used)
if (param.getParamType() == Parameter.ParamType.PROJECTION || param.getParamType() == Parameter.ParamType.PROJECTION_PARAM) {
arguments[i] = context.getProjectionMask();
continue;
} else if (param.getParamType() == Parameter.ParamType.METADATA_PROJECTION_PARAM) {
arguments[i] = context.getMetadataProjectionMask();
continue;
} else if (param.getParamType() == Parameter.ParamType.PAGING_PROJECTION_PARAM) {
arguments[i] = context.getPagingProjectionMask();
continue;
} else if (param.getParamType() == Parameter.ParamType.CONTEXT || param.getParamType() == Parameter.ParamType.PAGING_CONTEXT_PARAM) {
PagingContext ctx = RestUtils.getPagingContext(context, (PagingContext) param.getDefaultValue());
arguments[i] = ctx;
continue;
} else if (param.getParamType() == Parameter.ParamType.PATH_KEYS || param.getParamType() == Parameter.ParamType.PATH_KEYS_PARAM) {
arguments[i] = context.getPathKeys();
continue;
} else if (param.getParamType() == Parameter.ParamType.PATH_KEY_PARAM) {
Object value = context.getPathKeys().get(param.getName());
if (value != null) {
arguments[i] = value;
continue;
}
} else if (param.getParamType() == Parameter.ParamType.RESOURCE_CONTEXT || param.getParamType() == Parameter.ParamType.RESOURCE_CONTEXT_PARAM) {
arguments[i] = context;
continue;
} else if (param.getParamType() == Parameter.ParamType.VALIDATOR_PARAM) {
RestLiDataValidator validator = new RestLiDataValidator(resourceMethod.getResourceModel().getResourceClass().getAnnotations(), resourceMethod.getResourceModel().getValueClass(), resourceMethod.getMethodType());
arguments[i] = validator;
continue;
} else if (param.getParamType() == Parameter.ParamType.RESTLI_ATTACHMENTS_PARAM) {
arguments[i] = ((ServerResourceContext) context).getRequestAttachmentReader();
attachmentsDesired = true;
continue;
} else if (param.getParamType() == Parameter.ParamType.POST) {
// handle action parameters
if (template != null) {
DataMap data = template.data();
if (data.containsKey(param.getName())) {
arguments[i] = template.getValue(param);
continue;
}
}
} else if (param.getParamType() == Parameter.ParamType.QUERY) {
Object value;
if (DataTemplate.class.isAssignableFrom(param.getType())) {
value = buildDataTemplateArgument(context, param);
} else {
value = buildRegularArgument(context, param);
}
if (value != null) {
arguments[i] = value;
continue;
}
} else if (param.getParamType() == Parameter.ParamType.BATCH || param.getParamType() == Parameter.ParamType.RESOURCE_KEY) {
// should not come to this routine since it should be handled by passing in positionalArguments
throw new RoutingException("Parameter '" + param.getName() + "' should be passed in as a positional argument", HttpStatus.S_400_BAD_REQUEST.getCode());
} else {
// unknown param type
throw new RoutingException("Parameter '" + param.getName() + "' has an unknown parameter type '" + param.getParamType().name() + "'", HttpStatus.S_400_BAD_REQUEST.getCode());
}
} catch (TemplateRuntimeException e) {
throw new RoutingException("Parameter '" + param.getName() + "' is invalid", HttpStatus.S_400_BAD_REQUEST.getCode());
}
try {
// check if it is optional parameter
if (param.isOptional() && param.hasDefaultValue()) {
arguments[i] = param.getDefaultValue();
} else if (param.isOptional() && !param.getType().isPrimitive()) {
// optional primitive parameter must have default value or provided
arguments[i] = null;
} else {
throw new RoutingException("Parameter '" + param.getName() + "' is required", HttpStatus.S_400_BAD_REQUEST.getCode());
}
} catch (ResourceConfigException e) {
// Parameter default value format exception should result in server error code 500.
throw new RestLiServiceException(HttpStatus.S_500_INTERNAL_SERVER_ERROR, "Parameter '" + param.getName() + "' default value is invalid", e);
}
}
//that were not needed is safe, but not for request attachments.
if (!attachmentsDesired && ((ServerResourceContext) context).getRequestAttachmentReader() != null) {
throw new RestLiServiceException(HttpStatus.S_400_BAD_REQUEST, "Resource method endpoint invoked does not accept any request attachments.");
}
return arguments;
}
Aggregations