use of com.linkedin.restli.server.annotations.HeaderParam in project rest.li by linkedin.
the class TestArgumentBuilder method testHeaderParamType.
@Test
public void testHeaderParamType() {
String testParamKey = "testParam";
String expectedTestParamValue = "testParamValue";
ServerResourceContext mockResourceContext = EasyMock.createMock(ServerResourceContext.class);
HeaderParam annotation = EasyMock.createMock(HeaderParam.class);
EasyMock.expect(annotation.value()).andReturn(testParamKey);
AnnotationSet annotationSet = EasyMock.createMock(AnnotationSet.class);
EasyMock.expect(annotationSet.getAll()).andReturn(new Annotation[] {});
EasyMock.expect(annotationSet.get(HeaderParam.class)).andReturn(annotation);
Map<String, String> headers = new HashMap<>();
headers.put(testParamKey, expectedTestParamValue);
EasyMock.expect(mockResourceContext.getRequestHeaders()).andReturn(headers);
EasyMock.expect(mockResourceContext.getRequestAttachmentReader()).andReturn(null);
EasyMock.replay(mockResourceContext, annotation, annotationSet);
Parameter<String> param = new Parameter<>(testParamKey, String.class, DataSchemaConstants.STRING_DATA_SCHEMA, false, null, Parameter.ParamType.HEADER, false, annotationSet);
List<Parameter<?>> parameters = Collections.singletonList(param);
Object[] results = ArgumentBuilder.buildArgs(new Object[0], getMockResourceMethod(parameters), mockResourceContext, null, getMockResourceMethodConfig(false));
Assert.assertEquals(results[0], expectedTestParamValue);
}
use of com.linkedin.restli.server.annotations.HeaderParam 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;
}
use of com.linkedin.restli.server.annotations.HeaderParam in project rest.li by linkedin.
the class TestGetArgumentBuilder method testHeaderArgument.
@Test
public void testHeaderArgument() throws IOException {
String keyName = "myComplexKeyCollectionId";
Object keyValue = Integer.valueOf(123);
DataSchema keySchema = new IntegerDataSchema();
Key key = new Key(keyName, keyValue.getClass(), keySchema);
Map<String, String> headers = new HashMap<>();
String headerString = "An extra string.";
headers.put("extra", headerString);
List<Parameter<?>> headerParams = new ArrayList<>();
headerParams.add(getIntegerParam());
HeaderParam annotation = createMock(HeaderParam.class);
expect(annotation.value()).andReturn("extra");
AnnotationSet annotationSet = createMock(AnnotationSet.class);
expect(annotationSet.getAll()).andReturn(new Annotation[] {});
expect(annotationSet.get(HeaderParam.class)).andReturn(annotation);
replay(annotation, annotationSet);
Parameter<String> headerParam = new Parameter<>("", String.class, null, false, null, Parameter.ParamType.HEADER, false, annotationSet);
headerParams.add(headerParam);
ResourceModel model = RestLiArgumentBuilderTestHelper.getMockResourceModel(null, key, false);
ResourceMethodDescriptor descriptor = RestLiArgumentBuilderTestHelper.getMockResourceMethodDescriptor(model, 2, headerParams);
ServerResourceContext context = RestLiArgumentBuilderTestHelper.getMockResourceContext(keyName, keyValue, null, headers, true);
RoutingResult routingResult = RestLiArgumentBuilderTestHelper.getMockRoutingResult(descriptor, 3, context, 2);
RestRequest request = RestLiArgumentBuilderTestHelper.getMockRequest(false, null);
RestLiArgumentBuilder argumentBuilder = new GetArgumentBuilder();
RestLiRequestData requestData = argumentBuilder.extractRequestData(routingResult, null);
Object[] args = argumentBuilder.buildArguments(requestData, routingResult);
Object[] expectedArgs = new Object[] { keyValue, headerString };
assertEquals(args, expectedArgs);
verify(model, descriptor, context, routingResult, request, annotation, annotationSet);
}
use of com.linkedin.restli.server.annotations.HeaderParam 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")
static Object[] buildArgs(final Object[] positionalArguments, final ResourceMethodDescriptor resourceMethod, final ServerResourceContext context, final DynamicRecordTemplate template, final ResourceMethodConfig resourceMethodConfig) {
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] = context.getRequestAttachmentReader();
attachmentsDesired = true;
continue;
} else if (param.getParamType() == Parameter.ParamType.UNSTRUCTURED_DATA_WRITER_PARAM) {
// The OutputStream is passed to the resource implementation in a synchronous call. Upon return of the
// resource method, all the bytes would haven't written to the OutputStream. The EntityStream would have
// contained all the bytes by the time data is requested. The ownership of the OutputStream is passed to
// the ByteArrayOutputStreamWriter, which is responsible of closing the OutputStream if necessary.
ByteArrayOutputStream out = new ByteArrayOutputStream();
context.setResponseEntityStream(EntityStreams.newEntityStream(new ByteArrayOutputStreamWriter(out)));
arguments[i] = new UnstructuredDataWriter(out, context);
continue;
} else if (param.getParamType() == Parameter.ParamType.UNSTRUCTURED_DATA_REACTIVE_READER_PARAM) {
arguments[i] = new UnstructuredDataReactiveReader(context.getRequestEntityStream(), context.getRawRequest().getHeader(RestConstants.HEADER_CONTENT_TYPE));
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.getStructuredParameter(param.getName()), param, resourceMethodConfig.shouldValidateQueryParams());
} else {
value = buildRegularArgument(context, param, resourceMethodConfig.shouldValidateQueryParams());
}
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 && context.getRequestAttachmentReader() != null) {
throw new RestLiServiceException(HttpStatus.S_400_BAD_REQUEST, "Resource method endpoint invoked does not accept any request attachments.");
}
return arguments;
}
Aggregations