RestAnnotationProcessor implements Function<Invocation, HttpRequest> { @Override public GeneratedHttpRequest apply(Invocation invocation) { checkNotNull(invocation, "invocation"); inputParamValidator.validateMethodParametersOrThrow(invocation); Optional<URI> endpoint = Optional.absent(); HttpRequest r = findOrNull(invocation.getArgs(), HttpRequest.class); if (r != null) { endpoint = Optional.fromNullable(r.getEndpoint()); if (endpoint.isPresent()) logger.trace("using endpoint %s from invocation.getArgs() for %s", endpoint, invocation); } else if (caller != null) { endpoint = getEndpointFor(caller); if (endpoint.isPresent()) logger.trace("using endpoint %s from caller %s for %s", endpoint, caller, invocation); else endpoint = findEndpoint(invocation); } else { endpoint = findEndpoint(invocation); } if (!endpoint.isPresent()) throw new NoSuchElementException(format("no endpoint found for %s", invocation)); GeneratedHttpRequest.Builder requestBuilder = GeneratedHttpRequest.builder().invocation(invocation) .caller(caller); String requestMethod = null; if (r != null) { requestMethod = r.getMethod(); requestBuilder.fromHttpRequest(r); } else { requestMethod = tryFindHttpMethod(invocation.getInvokable()).get(); requestBuilder.method(requestMethod); } requestBuilder.filters(getFiltersIfAnnotated(invocation)); Multimap<String, Object> tokenValues = LinkedHashMultimap.create(); tokenValues.put(Constants.PROPERTY_API_VERSION, apiVersion); tokenValues.put(Constants.PROPERTY_BUILD_VERSION, buildVersion); UriBuilder uriBuilder = uriBuilder(endpoint.get().toString()); overridePathEncoding(uriBuilder, invocation); if (caller != null) tokenValues.putAll(addPathAndGetTokens(caller, uriBuilder)); tokenValues.putAll(addPathAndGetTokens(invocation, uriBuilder)); Multimap<String, Object> formParams; if (caller != null) { formParams = addFormParams(tokenValues, caller); formParams.putAll(addFormParams(tokenValues, invocation)); } else { formParams = addFormParams(tokenValues, invocation); } Multimap<String, Object> queryParams = addQueryParams(tokenValues, invocation); Multimap<String, String> headers = buildHeaders(tokenValues, invocation); if (r != null) headers.putAll(r.getHeaders()); if (shouldAddHostHeader(invocation)) { StringBuilder hostHeader = new StringBuilder(endpoint.get().getHost()); if (endpoint.get().getPort() != -1) hostHeader.append(":").append(endpoint.get().getPort()); headers.put(HOST, hostHeader.toString()); } Payload payload = null; for (HttpRequestOptions options : findOptionsIn(invocation)) { injector.injectMembers(options); for (Entry<String, String> header : options.buildRequestHeaders().entries()) { headers.put(header.getKey(), replaceTokens(header.getValue(), tokenValues)); } for (Entry<String, String> query : options.buildQueryParameters().entries()) { queryParams.put(query.getKey(), replaceTokens(query.getValue(), tokenValues)); } for (Entry<String, String> form : options.buildFormParameters().entries()) { formParams.put(form.getKey(), replaceTokens(form.getValue(), tokenValues)); } String pathSuffix = options.buildPathSuffix(); if (pathSuffix != null) { uriBuilder.appendPath(pathSuffix); } String stringPayload = options.buildStringPayload(); if (stringPayload != null) payload = Payloads.newStringPayload(stringPayload); } if (queryParams.size() > 0) { uriBuilder.query(queryParams); } requestBuilder.headers(filterOutContentHeaders(headers)); requestBuilder.endpoint(uriBuilder.build(convertUnsafe(tokenValues))); if (payload == null) { PayloadEnclosing payloadEnclosing = findOrNull(invocation.getArgs(), PayloadEnclosing.class); payload = (payloadEnclosing != null) ? payloadEnclosing.getPayload() : findOrNull(invocation.getArgs(), Payload.class); } List<? extends Part> parts = getParts(invocation, ImmutableMultimap.<String, Object> builder() .putAll(tokenValues).putAll(formParams).build()); if (parts.size() > 0) { if (formParams.size() > 0) { parts = newLinkedList(concat(transform(formParams.entries(), ENTRY_TO_PART), parts)); } payload = new MultipartForm(MultipartForm.BOUNDARY, parts); } else if (formParams.size() > 0) { payload = Payloads.newUrlEncodedFormPayload(transformValues(formParams, NullableToStringFunction.INSTANCE)); } else if (headers.containsKey(CONTENT_TYPE) && !HttpRequest.NON_PAYLOAD_METHODS.contains(requestMethod)) { if (payload == null) payload = Payloads.newByteArrayPayload(new byte[] {}); payload.getContentMetadata().setContentType(get(headers.get(CONTENT_TYPE), 0)); } if (payload != null) { requestBuilder.payload(payload); } GeneratedHttpRequest request = requestBuilder.build(); org.jclouds.rest.MapBinder mapBinder = getMapPayloadBinderOrNull(invocation); if (mapBinder != null) { Map<String, Object> mapParams; if (caller != null) { mapParams = buildPayloadParams(caller); mapParams.putAll(buildPayloadParams(invocation)); } else { mapParams = buildPayloadParams(invocation); } if (invocation.getInvokable().isAnnotationPresent(PayloadParams.class)) { PayloadParams params = invocation.getInvokable().getAnnotation(PayloadParams.class); addMapPayload(mapParams, params, headers); } request = mapBinder.bindToRequest(request, mapParams); } else { request = decorateRequest(request); } if (request.getPayload() != null) { contentMetadataCodec.fromHeaders(request.getPayload().getContentMetadata(), headers); } utils.checkRequestHasRequiredProperties(request); return request; } @Inject private  RestAnnotationProcessor(Injector injector, @ApiVersion String apiVersion, @BuildVersion String buildVersion,
         HttpUtils utils, ContentMetadataCodec contentMetadataCodec, InputParamValidator inputParamValidator,
         GetAcceptHeaders getAcceptHeaders, @Nullable @Named("caller") Invocation caller); @Deprecated GeneratedHttpRequest createRequest(Invokable<?, ?> invokable, List<Object> args); @Override GeneratedHttpRequest apply(Invocation invocation); @Override String toString();  }
@Test(expectedExceptions = NullPointerException.class, expectedExceptionsMessageRegExp = "param\\{robbie\\} for invocation TestQuery.foo3") public void testNiceNPEQueryParam() throws SecurityException, NoSuchMethodException, IOException { processor.apply(Invocation.create(method(TestQuery.class, "foo3", String.class), Lists.<Object> newArrayList((String) null))); }
@Test(expectedExceptions = NullPointerException.class, expectedExceptionsMessageRegExp = "postNonnull parameter 1") public void testCreatePostRequestNullNotOk2() throws SecurityException, NoSuchMethodException, IOException { Invokable<?, ?> method = method(TestPost.class, "postNonnull", String.class); processor.apply(Invocation.create(method, Lists.<Object> newArrayList((String) null))); }
@Test(expectedExceptions = NullPointerException.class, expectedExceptionsMessageRegExp = "fooble") public void testMultipartWithStringPartNullNotOkay() throws SecurityException, NoSuchMethodException, IOException { Invokable<?, ?> method = method(TestMultipartForm.class, "withStringPart", String.class); processor.apply(Invocation.create(method, Lists.<Object> newArrayList((String) null))); }
@Test(expectedExceptions = NullPointerException.class, expectedExceptionsMessageRegExp = "param\\{name\\} for invocation TestMultipartForm.withParamStringPart") public void testMultipartWithParamStringPartNullNotOk() throws SecurityException, NoSuchMethodException, IOException { Invokable<?, ?> method = method(TestMultipartForm.class, "withParamStringPart", String.class, String.class); processor.apply(Invocation.create(method, Lists.<Object> newArrayList(null, "foobledata"))); }
@Test public void testRequestFilter() throws SecurityException, NoSuchMethodException { Invokable<?, ?> method = method(TestRequestFilter.class, "get"); GeneratedHttpRequest request = processor.apply(Invocation.create(method)); assertEquals(request.getFilters().size(), 2); assertEquals(request.getFilters().get(0).getClass(), TestRequestFilter1.class); assertEquals(request.getFilters().get(1).getClass(), TestRequestFilter2.class); }
@Test public void testSkipEncoding() throws SecurityException, NoSuchMethodException { Invokable<?, ?> method = method(TestEncoding.class, "twoPaths", String.class, String.class); GeneratedHttpRequest request = processor.apply(Invocation.create(method, ImmutableList.<Object> of("1", "localhost"))); assertEquals(request.getEndpoint().getPath(), "/1/localhost"); assertEquals(request.getMethod(), HttpMethod.GET); assertEquals(request.getHeaders().size(), 0); }
@Test public void testEncodingPath() throws SecurityException, NoSuchMethodException { Invokable<?, ?> method = method(TestEncoding.class, "twoPaths", String.class, String.class); GeneratedHttpRequest request = processor.apply(Invocation.create(method, ImmutableList.<Object> of("/", "localhost"))); assertEquals(request.getEndpoint().getPath(), " assertEquals(request.getMethod(), HttpMethod.GET); assertEquals(request.getHeaders().size(), 0); }
@Test(enabled = false) public void testConstantPathParam() throws SecurityException, NoSuchMethodException, IOException { Invokable<?, ?> method = method(TestConstantPathParam.class, "twoPaths", String.class, String.class); GeneratedHttpRequest request = processor.apply(Invocation.create(method, ImmutableList.<Object> of("1", "localhost"))); assertRequestLineEquals(request, "GET http: assertNonPayloadHeadersEqual(request, ""); assertPayloadEquals(request, null, null, false); }
@Test(expectedExceptions = NullPointerException.class, expectedExceptionsMessageRegExp = "param\\{path\\} for invocation TestPath.onePath") public void testNiceNPEPathParam() throws SecurityException, NoSuchMethodException, IOException { Invokable<?, ?> method = method(TestPath.class, "onePath", String.class); processor.apply(Invocation.create(method, Lists.<Object> newArrayList((String) null))); }
@Test public void testPathParamExtractor() throws SecurityException, NoSuchMethodException, IOException { Invokable<?, ?> method = method(TestPath.class, "onePathParamExtractor", String.class); GeneratedHttpRequest request = processor.apply(Invocation.create(method, ImmutableList.<Object> of("localhost"))); assertRequestLineEquals(request, "GET http: assertNonPayloadHeadersEqual(request, ""); assertPayloadEquals(request, null, null, false); }
@Test public void testQueryParamExtractor() throws SecurityException, NoSuchMethodException, IOException { Invokable<?, ?> method = method(TestPath.class, "oneQueryParamExtractor", String.class); GeneratedHttpRequest request = processor.apply(Invocation.create(method, ImmutableList.<Object> of("localhost"))); assertRequestLineEquals(request, "GET http: assertNonPayloadHeadersEqual(request, ""); assertPayloadEquals(request, null, null, false); }
@Test public void testFormParamExtractor() throws SecurityException, NoSuchMethodException, IOException { Invokable<?, ?> method = method(TestPath.class, "oneFormParamExtractor", String.class); GeneratedHttpRequest request = processor.apply(Invocation.create(method, ImmutableList.<Object> of("localhost"))); assertRequestLineEquals(request, "POST http: assertNonPayloadHeadersEqual(request, ""); assertPayloadEquals(request, "one=l", "application/x-www-form-urlencoded", false); }
@Test(expectedExceptions = NullPointerException.class, expectedExceptionsMessageRegExp = "param\\{one\\} for invocation TestPath.oneFormParamExtractor") public void testNiceNPEFormParam() throws SecurityException, NoSuchMethodException, IOException { Invokable<?, ?> method = method(TestPath.class, "oneFormParamExtractor", String.class); processor.apply(Invocation.create(method, Lists.<Object> newArrayList((String) null))); }
@Test public void testBuildTwoHeader() throws SecurityException, NoSuchMethodException { Invokable<?, ?> method = method(TestHeader.class, "twoHeader", String.class); Multimap<String, String> headers = processor.apply(Invocation.create(method, ImmutableList.<Object> of("robot"))).getHeaders(); assertEquals(headers.size(), 2); assertEquals(headers.get("slash"), ImmutableList.of("/robot")); assertEquals(headers.get("hyphen"), ImmutableList.of("-robot")); }
@Test public void testBuildOneClassHeader() throws SecurityException, NoSuchMethodException { Invokable<?, ?> method = method(TestClassHeader.class, "oneHeader", String.class); Multimap<String, String> headers = processor.apply(Invocation.create(method, ImmutableList.<Object> of("robot"))).getHeaders(); assertEquals(headers.size(), 1); assertEquals(headers.get("x-amz-copy-source"), ImmutableList.of("/robot")); }
@Test public void testBuildOneHeader() throws SecurityException, NoSuchMethodException { Invokable<?, ?> method = method(TestHeader.class, "oneHeader", String.class); Multimap<String, String> headers = processor.apply(Invocation.create(method, ImmutableList.<Object> of("robot"))).getHeaders(); assertEquals(headers.size(), 1); assertEquals(headers.get("x-amz-copy-source"), ImmutableList.of("/robot")); }
@Test public void testBuildTwoHeaders() throws SecurityException, NoSuchMethodException { Invokable<?, ?> method = method(TestHeader.class, "twoHeaders", String.class, String.class); Multimap<String, String> headers = processor.apply(Invocation.create(method, ImmutableList.<Object> of("robot", "eggs"))).getHeaders(); assertEquals(headers.size(), 1); assertEquals(headers.get("x-amz-copy-source"), ImmutableList.of("/robot/eggs")); }
@Test public void testBuildTwoHeadersOutOfOrder() throws SecurityException, NoSuchMethodException { Invokable<?, ?> method = method(TestHeader.class, "twoHeadersOutOfOrder", String.class, String.class); Multimap<String, String> headers = processor.apply(Invocation.create(method, ImmutableList.<Object> of("robot", "eggs"))).getHeaders(); assertEquals(headers.size(), 1); assertEquals(headers.get("x-amz-copy-source"), ImmutableList.of("/eggs/robot")); }
@Test public void testQueryInOptions() throws SecurityException, NoSuchMethodException { Invokable<?, ?> method = method(TestQueryReplace.class, "queryInOptions", String.class, TestReplaceQueryOptions.class); String query = processor .apply(Invocation.create(method, ImmutableList.<Object> of("robot", new TestReplaceQueryOptions()))).getEndpoint() .getQuery(); assertEquals(query, "x-amz-copy-source=/robot"); }
@Test public void testBuildTwoQuery() throws SecurityException, NoSuchMethodException { Invokable<?, ?> method = method(TestQueryReplace.class, "twoQuery", String.class); String query = processor.apply(Invocation.create(method, ImmutableList.<Object> of("robot"))) .getEndpoint().getQuery(); assertEquals(query, "slash=/robot&hyphen=-robot"); }
@Test public void testBuildOneClassQuery() throws SecurityException, NoSuchMethodException { Invokable<?, ?> method = method(TestClassQuery.class, "oneQuery", String.class); String query = processor.apply(Invocation.create(method, ImmutableList.<Object> of("robot"))) .getEndpoint().getQuery(); assertEquals(query, "x-amz-copy-source=/robot"); }
@Test public void testBuildOneQuery() throws SecurityException, NoSuchMethodException { Invokable<?, ?> method = method(TestQueryReplace.class, "oneQuery", String.class); String query = processor.apply(Invocation.create(method, ImmutableList.<Object> of("robot"))) .getEndpoint().getQuery(); assertEquals(query, "x-amz-copy-source=/robot"); }
@Test public void testBuildTwoQuerys() throws SecurityException, NoSuchMethodException { Invokable<?, ?> method = method(TestQueryReplace.class, "twoQuerys", String.class, String.class); String query = processor .apply(Invocation.create(method, ImmutableList.<Object> of("robot", "eggs"))).getEndpoint().getQuery(); assertEquals(query, "x-amz-copy-source=/robot/eggs"); }
@Test public void testBuildTwoQuerysOutOfOrder() throws SecurityException, NoSuchMethodException { Invokable<?, ?> method = method(TestQueryReplace.class, "twoQuerysOutOfOrder", String.class, String.class); String query = processor .apply(Invocation.create(method, ImmutableList.<Object> of("robot", "eggs"))).getEndpoint().getQuery(); assertEquals(query, "x-amz-copy-source=/eggs/robot"); }
@Test(dataProvider = "strings") public void testCreateGetRequest(String key) throws SecurityException, NoSuchMethodException, UnsupportedEncodingException { Invokable<?, ?> method = method(TestRequest.class, "get", String.class, String.class); GeneratedHttpRequest request = processor.apply(Invocation.create(method, ImmutableList.<Object> of(key, "localhost"))); assertEquals(request.getEndpoint().getHost(), "localhost"); String expectedPath = "/" + URLEncoder.encode(key, "UTF-8").replaceAll("\\+", "%20"); assertEquals(request.getEndpoint().getRawPath(), expectedPath); assertEquals(request.getEndpoint().getPath(), "/" + key); assertEquals(request.getMethod(), HttpMethod.GET); assertEquals(request.getHeaders().size(), 1); assertEquals(request.getHeaders().get(HttpHeaders.HOST), ImmutableList.of("localhost")); }
@Test public void testVirtualHostMethod() throws SecurityException, NoSuchMethodException { Invokable<?, ?> method = method(TestVirtualHostMethod.class, "get", String.class, String.class); GeneratedHttpRequest request = processor.apply(Invocation.create(method, ImmutableList.<Object> of("1", "localhost"))); assertEquals(request.getEndpoint().getHost(), "localhost"); assertEquals(request.getEndpoint().getPath(), "/1"); assertEquals(request.getMethod(), HttpMethod.GET); assertEquals(request.getHeaders().size(), 1); assertEquals(request.getHeaders().get(HttpHeaders.HOST), ImmutableList.of("localhost:9999")); }
@Test public void testVirtualHost() throws SecurityException, NoSuchMethodException { Invokable<?, ?> method = method(TestVirtualHost.class, "get", String.class, String.class); GeneratedHttpRequest request = processor.apply(Invocation.create(method, ImmutableList.<Object> of("1", "localhost"))); assertEquals(request.getEndpoint().getHost(), "localhost"); assertEquals(request.getEndpoint().getPath(), "/1"); assertEquals(request.getMethod(), HttpMethod.GET); assertEquals(request.getHeaders().size(), 1); assertEquals(request.getHeaders().get(HttpHeaders.HOST), ImmutableList.of("localhost:9999")); }
@Test public void testHostPrefix() throws SecurityException, NoSuchMethodException { Invokable<?, ?> method = method(TestVirtualHost.class, "getPrefix", String.class, String.class); GeneratedHttpRequest request = processor.apply(Invocation.create(method, ImmutableList.<Object> of("1", "holy"))); assertEquals(request.getEndpoint().getHost(), "holy.localhost"); assertEquals(request.getEndpoint().getPath(), "/1"); assertEquals(request.getMethod(), HttpMethod.GET); assertEquals(request.getHeaders().size(), 0); }
@Test(expectedExceptions = IllegalArgumentException.class) public void testHostPrefixEmpty() throws SecurityException, NoSuchMethodException { Invokable<?, ?> method = method(TestVirtualHost.class, "getPrefix", String.class, String.class); processor.apply(Invocation.create(method, ImmutableList.<Object> of("1", ""))); }
@Test public void testOneHeader() throws SecurityException, NoSuchMethodException, ExecutionException { Invokable<?, ?> method = method(TestHeaders.class, "oneHeader", String.class); Multimap<String, String> headers = processor.apply(Invocation.create(method, ImmutableList.<Object> of("robot"))).getHeaders(); assertEquals(headers.size(), 1); assertEquals(headers.get("header"), ImmutableList.of("robot")); }
@Test public void testOneIntHeader() throws SecurityException, NoSuchMethodException, ExecutionException { Invokable<?, ?> method = method(TestHeaders.class, "oneIntHeader", int.class); Multimap<String, String> headers = processor.apply(Invocation.create(method, ImmutableList.<Object> of(1))).getHeaders(); assertEquals(headers.size(), 1); assertEquals(headers.get("header"), ImmutableList.of("1")); }
@Test public void testTwoDifferentHeaders() throws SecurityException, NoSuchMethodException, ExecutionException { Invokable<?, ?> method = method(TestHeaders.class, "twoDifferentHeaders", String.class, String.class); Multimap<String, String> headers = processor.apply(Invocation.create(method, ImmutableList.<Object> of("robot", "egg"))).getHeaders(); assertEquals(headers.size(), 2); assertEquals(headers.get("header1"), ImmutableList.of("robot")); assertEquals(headers.get("header2"), ImmutableList.of("egg")); }
@Test public void testTwoSameHeaders() throws SecurityException, NoSuchMethodException, ExecutionException { Invokable<?, ?> method = method(TestHeaders.class, "twoSameHeaders", String.class, String.class); Multimap<String, String> headers = processor.apply(Invocation.create(method, ImmutableList.<Object> of("robot", "egg"))).getHeaders(); assertEquals(headers.size(), 2); Collection<String> values = headers.get("header"); assert values.contains("robot"); assert values.contains("egg"); }
@Test public void testPut() throws SecurityException, NoSuchMethodException, IOException { Invokable<?, ?> method = method(TestPayload.class, "put", String.class); GeneratedHttpRequest request = processor.apply(Invocation.create(method, ImmutableList.<Object> of("test"))); assertRequestLineEquals(request, "PUT http: assertNonPayloadHeadersEqual(request, ""); assertPayloadEquals(request, "test", "application/unknown", false); }
@Test public void putWithPath() throws SecurityException, NoSuchMethodException, IOException { Invokable<?, ?> method = method(TestPayload.class, "putWithPath", String.class, String.class); GeneratedHttpRequest request = processor.apply(Invocation.create(method, ImmutableList.<Object> of("rabble", "test"))); assertRequestLineEquals(request, "PUT http: assertNonPayloadHeadersEqual(request, ""); assertPayloadEquals(request, "test", "application/unknown", false); }
@Test public void testBuildTwoForm() throws SecurityException, NoSuchMethodException { Invokable<?, ?> method = method(TestFormReplace.class, "twoForm", String.class); Object form = processor.apply(Invocation.create(method, ImmutableList.<Object> of("robot"))) .getPayload().getRawContent(); assertEquals(form, "slash=/robot&hyphen=-robot"); }
@Test public void testBuildOneClassForm() throws SecurityException, NoSuchMethodException { Invokable<?, ?> method = method(TestClassForm.class, "oneForm", String.class); Object form = processor.apply(Invocation.create(method, ImmutableList.<Object> of("robot"))) .getPayload().getRawContent(); assertEquals(form, "x-amz-copy-source=/robot"); }
@Test public void testBuildOneForm() throws SecurityException, NoSuchMethodException { Invokable<?, ?> method = method(TestFormReplace.class, "oneForm", String.class); Object form = processor.apply(Invocation.create(method, ImmutableList.<Object> of("robot"))) .getPayload().getRawContent(); assertEquals(form, "x-amz-copy-source=/robot"); }
@Test public void testBuildTwoForms() throws SecurityException, NoSuchMethodException { Invokable<?, ?> method = method(TestFormReplace.class, "twoForms", String.class, String.class); Object form = processor.apply(Invocation.create(method, ImmutableList.<Object> of("robot", "eggs"))) .getPayload().getRawContent(); assertEquals(form, "x-amz-copy-source=/robot/eggs"); }
@Test public void testBuildTwoFormsOutOfOrder() throws SecurityException, NoSuchMethodException { Invokable<?, ?> method = method(TestFormReplace.class, "twoFormsOutOfOrder", String.class, String.class); Object form = processor.apply(Invocation.create(method, ImmutableList.<Object> of("robot", "eggs"))) .getPayload().getRawContent(); assertEquals(form, "x-amz-copy-source=/eggs/robot"); }