Cleaned up scoping of delegated methods

This commit is contained in:
Adrian Cole 2010-07-13 02:39:52 -05:00
parent 436037c7be
commit 891484a2aa
4 changed files with 502 additions and 304 deletions

View File

@ -0,0 +1,38 @@
/**
*
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
package org.jclouds.rest.annotations;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import javax.inject.Qualifier;
/**
* Apply this to implementation classes when you want Access to items from the
* scope of a delegate.
*
* @author Adrian Cole
*/
@Target( { ElementType.TYPE, ElementType.METHOD, ElementType.PARAMETER , ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface Caller {
}

View File

@ -58,8 +58,8 @@ public class RestClientModule<S, A> extends AbstractModule {
}
public RestClientModule(Class<S> syncClientType, Class<A> asyncClientType) {
this(syncClientType, asyncClientType, ImmutableMap.<Class<?>, Class<?>> of(syncClientType,
asyncClientType));
this(syncClientType, asyncClientType, ImmutableMap
.<Class<?>, Class<?>> of(syncClientType, asyncClientType));
}
@SuppressWarnings("unchecked")
@ -68,8 +68,9 @@ public class RestClientModule<S, A> extends AbstractModule {
// Ensures the restcontext can be looked up without generic types.
bind(new TypeLiteral<RestContext>() {
}).to(
(TypeLiteral) TypeLiteral.get(Types.newParameterizedType(RestContextImpl.class,
syncClientType, asyncClientType))).in(Scopes.SINGLETON);
(TypeLiteral) TypeLiteral.get(Types.newParameterizedType(
RestContextImpl.class, syncClientType, asyncClientType))).in(
Scopes.SINGLETON);
bindAsyncClient();
bindClient();
bindErrorHandlers();
@ -82,8 +83,10 @@ public class RestClientModule<S, A> extends AbstractModule {
* ex.
*
* <pre>
* bind(HttpRetryHandler.class).annotatedWith(Redirection.class).to(AWSRedirectionRetryHandler.class);
* bind(HttpRetryHandler.class).annotatedWith(ClientError.class).to(AWSClientErrorRetryHandler.class);
* bind(HttpRetryHandler.class).annotatedWith(Redirection.class).to(
* AWSRedirectionRetryHandler.class);
* bind(HttpRetryHandler.class).annotatedWith(ClientError.class).to(
* AWSClientErrorRetryHandler.class);
* </pre>
*
*/
@ -96,9 +99,12 @@ public class RestClientModule<S, A> extends AbstractModule {
* ex.
*
* <pre>
* bind(HttpErrorHandler.class).annotatedWith(Redirection.class).to(ParseAWSErrorFromXmlContent.class);
* bind(HttpErrorHandler.class).annotatedWith(ClientError.class).to(ParseAWSErrorFromXmlContent.class);
* bind(HttpErrorHandler.class).annotatedWith(ServerError.class).to(ParseAWSErrorFromXmlContent.class);
* bind(HttpErrorHandler.class).annotatedWith(Redirection.class).to(
* ParseAWSErrorFromXmlContent.class);
* bind(HttpErrorHandler.class).annotatedWith(ClientError.class).to(
* ParseAWSErrorFromXmlContent.class);
* bind(HttpErrorHandler.class).annotatedWith(ServerError.class).to(
* ParseAWSErrorFromXmlContent.class);
* </pre>
*
*
@ -111,9 +117,11 @@ public class RestClientModule<S, A> extends AbstractModule {
}
protected void bindClient() {
BinderUtils.bindClient(binder(), syncClientType, asyncClientType, delegates);
BinderUtils.bindClient(binder(), syncClientType, asyncClientType,
delegates);
}
@Provides
@Singleton
@Named("sync")

View File

@ -18,9 +18,9 @@
*/
package org.jclouds.rest.config;
import java.net.URI;
import java.util.concurrent.ConcurrentMap;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import javax.ws.rs.core.UriBuilder;
@ -36,6 +36,7 @@ import org.jclouds.internal.ClassMethodArgs;
import org.jclouds.rest.AsyncClientFactory;
import org.jclouds.rest.HttpAsyncClient;
import org.jclouds.rest.HttpClient;
import org.jclouds.rest.annotations.Caller;
import org.jclouds.rest.internal.AsyncRestClientProxy;
import org.jclouds.rest.internal.RestAnnotationProcessor;
@ -43,8 +44,10 @@ import com.google.common.base.Function;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.MapMaker;
import com.google.inject.AbstractModule;
import com.google.inject.Inject;
import com.google.inject.Injector;
import com.google.inject.Key;
import com.google.inject.Module;
import com.google.inject.Provides;
import com.google.inject.Scopes;
import com.google.inject.TypeLiteral;
@ -61,10 +64,12 @@ public class RestModule extends AbstractModule {
protected void configure() {
install(new ParserModule());
bind(UriBuilder.class).to(UriBuilderImpl.class);
bind(AsyncRestClientProxy.Factory.class).to(Factory.class).in(Scopes.SINGLETON);
bind(AsyncRestClientProxy.Factory.class).to(Factory.class).in(
Scopes.SINGLETON);
BinderUtils.bindAsyncClient(binder(), HttpAsyncClient.class);
BinderUtils.bindClient(binder(), HttpClient.class, HttpAsyncClient.class, ImmutableMap
.<Class<?>, Class<?>> of(HttpClient.class, HttpAsyncClient.class));
BinderUtils.bindClient(binder(), HttpClient.class, HttpAsyncClient.class,
ImmutableMap.<Class<?>, Class<?>> of(HttpClient.class,
HttpAsyncClient.class));
}
@Provides
@ -75,36 +80,74 @@ public class RestModule extends AbstractModule {
return new MapMaker().makeComputingMap(createAsyncClientForCaller);
}
static class CreateAsyncClientForCaller implements Function<ClassMethodArgs, Object> {
static class CreateAsyncClientForCaller implements
Function<ClassMethodArgs, Object> {
private final Injector injector;
private final AsyncRestClientProxy.Factory factory;
@Caller
@Inject(optional = true)
Module callerModule = new CallerScopedBindingModule();
@Inject
CreateAsyncClientForCaller(Injector injector, AsyncRestClientProxy.Factory factory) {
CreateAsyncClientForCaller(Injector injector,
AsyncRestClientProxy.Factory factory) {
this.injector = injector;
this.factory = factory;
}
@SuppressWarnings("unchecked")
@Override
public Object apply(ClassMethodArgs from) {
public Object apply(final ClassMethodArgs from) {
Class clazz = from.getAsyncClass();
TypeLiteral typeLiteral = TypeLiteral.get(clazz);
RestAnnotationProcessor util = (RestAnnotationProcessor) injector.getInstance(Key
.get(TypeLiteral.get(Types.newParameterizedType(RestAnnotationProcessor.class,
clazz))));
util.setCaller(from);
Injector injector = this.injector.createChildInjector(callerModule,
new AbstractModule() {
ConcurrentMap<ClassMethodArgs, Object> delegateMap = injector.getInstance(Key.get(
@Override
protected void configure() {
bind(ClassMethodArgs.class).annotatedWith(Caller.class)
.toInstance(from);
install(callerModule);
}
});
RestAnnotationProcessor util = (RestAnnotationProcessor) injector
.getInstance(Key.get(TypeLiteral.get(Types.newParameterizedType(
RestAnnotationProcessor.class, clazz))));
// not sure why we have to go back and re-inject this...
injector.injectMembers(util);
ConcurrentMap<ClassMethodArgs, Object> delegateMap = injector
.getInstance(Key.get(
new TypeLiteral<ConcurrentMap<ClassMethodArgs, Object>>() {
}, Names.named("async")));
AsyncRestClientProxy proxy = new AsyncRestClientProxy(injector, factory, util,
typeLiteral, delegateMap);
AsyncRestClientProxy proxy = new AsyncRestClientProxy(injector,
factory, util, typeLiteral, delegateMap);
injector.injectMembers(proxy);
return AsyncClientFactory.create(clazz, proxy);
}
}
@Singleton
public static class CallerScopedBindingModule extends AbstractModule {
@Provides
@Caller
URI provideCallerScopedURI(Injector injector, @Caller ClassMethodArgs args) {
try {
return RestAnnotationProcessor.getEndpointFor(args.getMethod(),
args.getArgs(), injector);
} catch (IllegalStateException e) {
return null;
}
}
@Override
protected void configure() {
}
}
private static class Factory implements AsyncRestClientProxy.Factory {
@Inject
private TransformingHttpCommandExecutorService executorService;
@ -112,7 +155,8 @@ public class RestModule extends AbstractModule {
@SuppressWarnings("unchecked")
public TransformingHttpCommand<?> create(HttpRequest request,
Function<HttpResponse, ?> transformer) {
return new TransformingHttpCommandImpl(executorService, request, transformer);
return new TransformingHttpCommandImpl(executorService, request,
transformer);
}
}

View File

@ -20,8 +20,6 @@ package org.jclouds.rest.internal;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.collect.Collections2.filter;
import static com.google.common.collect.Collections2.transform;
import static com.google.common.collect.Iterables.concat;
import static com.google.common.collect.Lists.newArrayList;
import static com.google.common.collect.Lists.newLinkedList;
import static com.google.common.collect.Maps.filterValues;
@ -37,8 +35,6 @@ import static org.jclouds.http.HttpUtils.makeQueryLine;
import static org.jclouds.http.HttpUtils.parseQueryToMap;
import static org.jclouds.http.HttpUtils.urlEncode;
import static org.jclouds.http.Payloads.newPayload;
import static org.jclouds.http.Payloads.newStringPayload;
import static org.jclouds.http.Payloads.newUrlEncodedFormPayload;
import static org.jclouds.util.Utils.replaceTokens;
import java.io.InputStream;
@ -76,6 +72,7 @@ import org.jclouds.http.HttpResponse;
import org.jclouds.http.HttpUtils;
import org.jclouds.http.Payload;
import org.jclouds.http.PayloadEnclosing;
import org.jclouds.http.Payloads;
import org.jclouds.http.functions.ParseSax;
import org.jclouds.http.functions.ParseURIFromListOrLocationHeaderIf20x;
import org.jclouds.http.functions.ReleasePayloadAndReturn;
@ -93,6 +90,7 @@ import org.jclouds.rest.Binder;
import org.jclouds.rest.InputParamValidator;
import org.jclouds.rest.InvocationContext;
import org.jclouds.rest.annotations.BinderParam;
import org.jclouds.rest.annotations.Caller;
import org.jclouds.rest.annotations.Delegate;
import org.jclouds.rest.annotations.Endpoint;
import org.jclouds.rest.annotations.EndpointParam;
@ -116,6 +114,7 @@ import org.jclouds.rest.functions.MapHttp4xxCodesToExceptions;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
import com.google.common.collect.LinkedHashMultimap;
import com.google.common.collect.LinkedListMultimap;
import com.google.common.collect.MapMaker;
@ -136,51 +135,48 @@ public class RestAnnotationProcessor<T> {
@Resource
protected Logger logger = Logger.NULL;
ClassMethodArgs caller;
@Inject(optional = true)
public void setCaller(@Named("caller") ClassMethodArgs caller) {
seedCache(caller.getMethod().getDeclaringClass());
this.caller = caller;
}
private final Class<T> declaring;
private final Map<Method, Map<Integer, Set<Annotation>>> methodToIndexOfParamToDecoratorParamAnnotation = createMethodToIndexOfParamToAnnotation(BinderParam.class);
private final Map<Method, Map<Integer, Set<Annotation>>> methodToIndexOfParamToHeaderParamAnnotations = createMethodToIndexOfParamToAnnotation(HeaderParam.class);
private final Map<Method, Map<Integer, Set<Annotation>>> methodToIndexOfParamToEndpointAnnotations = createMethodToIndexOfParamToAnnotation(Endpoint.class);
private final Map<Method, Map<Integer, Set<Annotation>>> methodToIndexOfParamToEndpointParamAnnotations = createMethodToIndexOfParamToAnnotation(EndpointParam.class);
private final Map<Method, Map<Integer, Set<Annotation>>> methodToIndexOfParamToMatrixParamAnnotations = createMethodToIndexOfParamToAnnotation(MatrixParam.class);
private final Map<Method, Map<Integer, Set<Annotation>>> methodToIndexOfParamToFormParamAnnotations = createMethodToIndexOfParamToAnnotation(FormParam.class);
private final Map<Method, Map<Integer, Set<Annotation>>> methodToIndexOfParamToQueryParamAnnotations = createMethodToIndexOfParamToAnnotation(QueryParam.class);
private final Map<Method, Map<Integer, Set<Annotation>>> methodToIndexOfParamToPathParamAnnotations = createMethodToIndexOfParamToAnnotation(PathParam.class);
private final Map<Method, Map<Integer, Set<Annotation>>> methodToIndexOfParamToPostParamAnnotations = createMethodToIndexOfParamToAnnotation(MapPayloadParam.class);
private final Map<Method, Map<Integer, Set<Annotation>>> methodToIndexOfParamToPartParamAnnotations = createMethodToIndexOfParamToAnnotation(PartParam.class);
private final Map<Method, Map<Integer, Set<Annotation>>> methodToIndexOfParamToParamParserAnnotations = createMethodToIndexOfParamToAnnotation(ParamParser.class);
private final Map<MethodKey, Method> delegationMap = newHashMap();
static final Map<Method, Map<Integer, Set<Annotation>>> methodToIndexOfParamToDecoratorParamAnnotation = createMethodToIndexOfParamToAnnotation(BinderParam.class);
static final Map<Method, Map<Integer, Set<Annotation>>> methodToIndexOfParamToHeaderParamAnnotations = createMethodToIndexOfParamToAnnotation(HeaderParam.class);
static final Map<Method, Map<Integer, Set<Annotation>>> methodToIndexOfParamToEndpointAnnotations = createMethodToIndexOfParamToAnnotation(Endpoint.class);
static final Map<Method, Map<Integer, Set<Annotation>>> methodToIndexOfParamToEndpointParamAnnotations = createMethodToIndexOfParamToAnnotation(EndpointParam.class);
static final Map<Method, Map<Integer, Set<Annotation>>> methodToIndexOfParamToMatrixParamAnnotations = createMethodToIndexOfParamToAnnotation(MatrixParam.class);
static final Map<Method, Map<Integer, Set<Annotation>>> methodToIndexOfParamToFormParamAnnotations = createMethodToIndexOfParamToAnnotation(FormParam.class);
static final Map<Method, Map<Integer, Set<Annotation>>> methodToIndexOfParamToQueryParamAnnotations = createMethodToIndexOfParamToAnnotation(QueryParam.class);
static final Map<Method, Map<Integer, Set<Annotation>>> methodToIndexOfParamToPathParamAnnotations = createMethodToIndexOfParamToAnnotation(PathParam.class);
static final Map<Method, Map<Integer, Set<Annotation>>> methodToIndexOfParamToPostParamAnnotations = createMethodToIndexOfParamToAnnotation(MapPayloadParam.class);
static final Map<Method, Map<Integer, Set<Annotation>>> methodToIndexOfParamToPartParamAnnotations = createMethodToIndexOfParamToAnnotation(PartParam.class);
static final Map<Method, Map<Integer, Set<Annotation>>> methodToIndexOfParamToParamParserAnnotations = createMethodToIndexOfParamToAnnotation(ParamParser.class);
static final Map<MethodKey, Method> delegationMap = newHashMap();
static Map<Method, Map<Integer, Set<Annotation>>> createMethodToIndexOfParamToAnnotation(
final Class<? extends Annotation> annotation) {
return new MapMaker().makeComputingMap(new Function<Method, Map<Integer, Set<Annotation>>>() {
return new MapMaker()
.makeComputingMap(new Function<Method, Map<Integer, Set<Annotation>>>() {
public Map<Integer, Set<Annotation>> apply(final Method method) {
return new MapMaker().makeComputingMap(new GetAnnotationsForMethodParameterIndex(
return new MapMaker()
.makeComputingMap(new GetAnnotationsForMethodParameterIndex(
method, annotation));
}
});
}
static class GetAnnotationsForMethodParameterIndex implements Function<Integer, Set<Annotation>> {
static class GetAnnotationsForMethodParameterIndex implements
Function<Integer, Set<Annotation>> {
private final Method method;
private final Class<?> clazz;
protected GetAnnotationsForMethodParameterIndex(Method method, Class<?> clazz) {
protected GetAnnotationsForMethodParameterIndex(Method method,
Class<?> clazz) {
this.method = method;
this.clazz = clazz;
}
public Set<Annotation> apply(final Integer index) {
Set<Annotation> keys = new HashSet<Annotation>();
List<Annotation> parameterAnnotations = newArrayList(method.getParameterAnnotations()[index]);
List<Annotation> parameterAnnotations = newArrayList(method
.getParameterAnnotations()[index]);
Collection<Annotation> filtered = filter(parameterAnnotations,
new Predicate<Annotation>() {
public boolean apply(Annotation input) {
@ -231,13 +227,15 @@ public class RestAnnotationProcessor<T> {
private InputParamValidator inputParamValidator;
@VisibleForTesting
Function<HttpResponse, ?> createResponseParser(Method method, HttpRequest request) {
Function<HttpResponse, ?> createResponseParser(Method method,
HttpRequest request) {
return createResponseParser(parserFactory, injector, method, request);
}
@VisibleForTesting
public static Function<HttpResponse, ?> createResponseParser(ParseSax.Factory parserFactory,
Injector injector, Method method, HttpRequest request) {
public static Function<HttpResponse, ?> createResponseParser(
ParseSax.Factory parserFactory, Injector injector, Method method,
HttpRequest request) {
Function<HttpResponse, ?> transformer;
Class<? extends HandlerWithResult<?>> handler = getSaxResponseParserClassOrNull(method);
if (handler != null) {
@ -246,7 +244,8 @@ public class RestAnnotationProcessor<T> {
transformer = injector.getInstance(getParserOrThrowException(method));
}
if (transformer instanceof InvocationContext) {
((InvocationContext) transformer).setContext((GeneratedHttpRequest<?>) request);
((InvocationContext) transformer)
.setContext((GeneratedHttpRequest<?>) request);
}
return transformer;
}
@ -254,7 +253,8 @@ public class RestAnnotationProcessor<T> {
@VisibleForTesting
Function<Exception, ?> createExceptionParserOrThrowResourceNotFoundOn404IfNoAnnotation(
Method method) {
return createExceptionParserOrThrowResourceNotFoundOn404IfNoAnnotation(injector, method);
return createExceptionParserOrThrowResourceNotFoundOn404IfNoAnnotation(
injector, method);
}
@VisibleForTesting
@ -269,8 +269,9 @@ public class RestAnnotationProcessor<T> {
@SuppressWarnings("unchecked")
@Inject
public RestAnnotationProcessor(Injector injector, ParseSax.Factory parserFactory,
HttpUtils utils, TypeLiteral<T> typeLiteral) {
public RestAnnotationProcessor(Injector injector,
ParseSax.Factory parserFactory, HttpUtils utils,
TypeLiteral<T> typeLiteral) {
this.declaring = (Class<T>) typeLiteral.getRawType();
this.injector = injector;
this.parserFactory = parserFactory;
@ -294,17 +295,27 @@ public class RestAnnotationProcessor<T> {
for (Method method : methods) {
if (isHttpMethod(method)) {
for (int index = 0; index < method.getParameterTypes().length; index++) {
methodToIndexOfParamToDecoratorParamAnnotation.get(method).get(index);
methodToIndexOfParamToHeaderParamAnnotations.get(method).get(index);
methodToIndexOfParamToMatrixParamAnnotations.get(method).get(index);
methodToIndexOfParamToFormParamAnnotations.get(method).get(index);
methodToIndexOfParamToQueryParamAnnotations.get(method).get(index);
methodToIndexOfParamToDecoratorParamAnnotation.get(method).get(
index);
methodToIndexOfParamToHeaderParamAnnotations.get(method).get(
index);
methodToIndexOfParamToMatrixParamAnnotations.get(method).get(
index);
methodToIndexOfParamToFormParamAnnotations.get(method)
.get(index);
methodToIndexOfParamToQueryParamAnnotations.get(method).get(
index);
methodToIndexOfParamToEndpointAnnotations.get(method).get(index);
methodToIndexOfParamToEndpointParamAnnotations.get(method).get(index);
methodToIndexOfParamToPathParamAnnotations.get(method).get(index);
methodToIndexOfParamToPostParamAnnotations.get(method).get(index);
methodToIndexOfParamToParamParserAnnotations.get(method).get(index);
methodToIndexOfParamToPartParamAnnotations.get(method).get(index);
methodToIndexOfParamToEndpointParamAnnotations.get(method).get(
index);
methodToIndexOfParamToPathParamAnnotations.get(method)
.get(index);
methodToIndexOfParamToPostParamAnnotations.get(method)
.get(index);
methodToIndexOfParamToParamParserAnnotations.get(method).get(
index);
methodToIndexOfParamToPartParamAnnotations.get(method)
.get(index);
methodToIndexesOfOptions.get(method);
}
delegationMap.put(new MethodKey(method), method);
@ -315,7 +326,9 @@ public class RestAnnotationProcessor<T> {
} else if (method.isAnnotationPresent(Delegate.class)) {
logger.debug("skipping delegate method %s", method);
} else if (!method.getName().startsWith("new")) {
logger.trace("Method is not annotated as either http or constant: %s", method);
logger.trace(
"Method is not annotated as either http or constant: %s",
method);
}
}
}
@ -362,19 +375,26 @@ public class RestAnnotationProcessor<T> {
final Injector injector;
ClassMethodArgs caller;
@Inject(optional = true)
public void setCaller(@Caller ClassMethodArgs caller) {
seedCache(caller.getMethod().getDeclaringClass());
this.caller = caller;
}
@Inject(optional = true)
@Caller
@Nullable
URI callerEndpoint;
public GeneratedHttpRequest<T> createRequest(Method method, Object... args) {
inputParamValidator.validateMethodParametersOrThrow(method, args);
URI endpoint;
URI endpoint = callerEndpoint;
try {
if (caller != null) {
try {
endpoint = getEndpointFor(caller.getMethod(), caller.getArgs());
} catch (IllegalStateException e) {
endpoint = getEndpointFor(method, args);
}
} else {
endpoint = getEndpointFor(method, args);
}
if (endpoint == null)
endpoint = getEndpointFor(method, args, injector);
} catch (IllegalStateException e) {
endpoint = injector.getInstance(Key.get(URI.class,
org.jclouds.rest.annotations.Provider.class));
@ -386,34 +406,44 @@ public class RestAnnotationProcessor<T> {
Multimap<String, String> tokenValues = LinkedHashMultimap.create();
if (caller != null) {
builder.path(getPath(caller.getMethod().getDeclaringClass(), caller.getMethod(), caller
.getArgs()));
builder.path(getPath(caller.getMethod().getDeclaringClass(), caller
.getMethod(), caller.getArgs()));
}
tokenValues.putAll(addPathAndGetTokens(declaring, method, args, builder));
Multimap<String, String> formParams = addFormParams(tokenValues.entries(), method, args);
Multimap<String, String> queryParams = addQueryParams(tokenValues.entries(), method, args);
Multimap<String, String> formParams = addFormParams(
tokenValues.entries(), method, args);
Multimap<String, String> queryParams = addQueryParams(tokenValues
.entries(), method, args);
addMatrixParams(builder, tokenValues.entries(), method, args);
Multimap<String, String> headers = buildHeaders(tokenValues.entries(), method, args);
Multimap<String, String> headers = buildHeaders(tokenValues.entries(),
method, args);
Payload payload = null;
HttpRequestOptions options = findOptionsIn(method, args);
if (options != null) {
injector.injectMembers(options);// TODO test case
for (Entry<String, String> header : options.buildRequestHeaders().entries()) {
headers.put(header.getKey(), replaceTokens(header.getValue(), tokenValues.entries()));
for (Entry<String, String> header : options.buildRequestHeaders()
.entries()) {
headers.put(header.getKey(), replaceTokens(header.getValue(),
tokenValues.entries()));
}
for (Entry<String, String> matrix : options.buildMatrixParameters().entries()) {
builder.matrixParam(matrix.getKey(), replaceTokens(matrix.getValue(), tokenValues
.entries()));
for (Entry<String, String> matrix : options.buildMatrixParameters()
.entries()) {
builder.matrixParam(matrix.getKey(), replaceTokens(matrix
.getValue(), tokenValues.entries()));
}
for (Entry<String, String> query : options.buildQueryParameters().entries()) {
queryParams.put(query.getKey(), replaceTokens(query.getValue(), tokenValues.entries()));
for (Entry<String, String> query : options.buildQueryParameters()
.entries()) {
queryParams.put(query.getKey(), replaceTokens(query.getValue(),
tokenValues.entries()));
}
for (Entry<String, String> form : options.buildFormParameters().entries()) {
formParams.put(form.getKey(), replaceTokens(form.getValue(), tokenValues.entries()));
for (Entry<String, String> form : options.buildFormParameters()
.entries()) {
formParams.put(form.getKey(), replaceTokens(form.getValue(),
tokenValues.entries()));
}
String pathSuffix = options.buildPathSuffix();
@ -422,7 +452,7 @@ public class RestAnnotationProcessor<T> {
}
String stringPayload = options.buildStringPayload();
if (stringPayload != null)
payload = newStringPayload(stringPayload);
payload = Payloads.newStringPayload(stringPayload);
}
if (queryParams.size() > 0) {
@ -437,22 +467,24 @@ public class RestAnnotationProcessor<T> {
throw new IllegalStateException(e);
}
GeneratedHttpRequest<T> request = new GeneratedHttpRequest<T>(httpMethod, endpoint, skips,
declaring, method, args);
addHostHeaderIfAnnotatedWithVirtualHost(headers, request.getEndpoint().getHost(), method);
GeneratedHttpRequest<T> request = new GeneratedHttpRequest<T>(httpMethod,
endpoint, skips, declaring, method, args);
addHostHeaderIfAnnotatedWithVirtualHost(headers, request.getEndpoint()
.getHost(), method);
addFiltersIfAnnotated(method, request);
if (payload == null)
payload = findPayloadInArgs(args);
List<? extends Part> parts = getParts(method, args, concat(tokenValues.entries(), formParams
.entries()));
List<? extends Part> parts = getParts(method, args, Iterables.concat(
tokenValues.entries(), formParams.entries()));
if (parts.size() > 0) {
if (formParams.size() > 0) {
parts = newLinkedList(concat(transform(formParams.entries(), ENTRY_TO_PART), parts));
parts = newLinkedList(Iterables.concat(Iterables.transform(
formParams.entries(), ENTRY_TO_PART), parts));
}
payload = new MultipartForm(BOUNDARY, parts);
} else if (formParams.size() > 0) {
payload = newUrlEncodedFormPayload(formParams, skips);
payload = Payloads.newUrlEncodedFormPayload(formParams, skips);
}
if (payload != null) {
request.setPayload(payload);
@ -469,11 +501,12 @@ public class RestAnnotationProcessor<T> {
builder.path(clazz);
builder.path(method);
return builder.buildFromEncodedMap(
convertUnsafe(encodeValues(getPathParamKeyValues(method, args), skips))).getPath();
convertUnsafe(encodeValues(getPathParamKeyValues(method, args),
skips))).getPath();
}
private Multimap<String, String> addPathAndGetTokens(Class<?> clazz, Method method,
Object[] args, UriBuilder builder) {
private Multimap<String, String> addPathAndGetTokens(Class<?> clazz,
Method method, Object[] args, UriBuilder builder) {
if (clazz.isAnnotationPresent(Path.class))
builder.path(clazz);
builder.path(method);
@ -485,15 +518,18 @@ public class RestAnnotationProcessor<T> {
return replaceQuery(uriBuilderProvider, in, newQuery, sorter, skips);
}
public static URI replaceQuery(Provider<UriBuilder> uriBuilderProvider, URI in, String newQuery,
public static URI replaceQuery(Provider<UriBuilder> uriBuilderProvider,
URI in, String newQuery,
@Nullable Comparator<Entry<String, String>> sorter, char... skips) {
UriBuilder builder = uriBuilderProvider.get().uri(in);
builder.replaceQuery(makeQueryLine(parseQueryToMap(newQuery), sorter, skips));
builder.replaceQuery(makeQueryLine(parseQueryToMap(newQuery), sorter,
skips));
return builder.build();
}
private void addMatrixParams(UriBuilder builder, Collection<Entry<String, String>> tokenValues,
Method method, Object... args) {
private void addMatrixParams(UriBuilder builder,
Collection<Entry<String, String>> tokenValues, Method method,
Object... args) {
if (declaring.isAnnotationPresent(MatrixParams.class)) {
MatrixParams matrix = declaring.getAnnotation(MatrixParams.class);
addMatrix(builder, matrix, tokenValues);
@ -504,13 +540,16 @@ public class RestAnnotationProcessor<T> {
addMatrix(builder, matrix, tokenValues);
}
for (Entry<String, String> matrix : getMatrixParamKeyValues(method, args).entries()) {
builder.matrixParam(matrix.getKey(), replaceTokens(matrix.getValue(), tokenValues));
for (Entry<String, String> matrix : getMatrixParamKeyValues(method, args)
.entries()) {
builder.matrixParam(matrix.getKey(), replaceTokens(matrix.getValue(),
tokenValues));
}
}
private Multimap<String, String> addFormParams(Collection<Entry<String, String>> tokenValues,
Method method, Object... args) {
private Multimap<String, String> addFormParams(
Collection<Entry<String, String>> tokenValues, Method method,
Object... args) {
Multimap<String, String> formMap = LinkedListMultimap.create();
if (declaring.isAnnotationPresent(FormParams.class)) {
FormParams form = declaring.getAnnotation(FormParams.class);
@ -522,14 +561,17 @@ public class RestAnnotationProcessor<T> {
addForm(formMap, form, tokenValues);
}
for (Entry<String, String> form : getFormParamKeyValues(method, args).entries()) {
formMap.put(form.getKey(), replaceTokens(form.getValue(), tokenValues));
for (Entry<String, String> form : getFormParamKeyValues(method, args)
.entries()) {
formMap
.put(form.getKey(), replaceTokens(form.getValue(), tokenValues));
}
return formMap;
}
private Multimap<String, String> addQueryParams(Collection<Entry<String, String>> tokenValues,
Method method, Object... args) {
private Multimap<String, String> addQueryParams(
Collection<Entry<String, String>> tokenValues, Method method,
Object... args) {
Multimap<String, String> queryMap = LinkedListMultimap.create();
if (declaring.isAnnotationPresent(QueryParams.class)) {
QueryParams query = declaring.getAnnotation(QueryParams.class);
@ -541,8 +583,10 @@ public class RestAnnotationProcessor<T> {
addQuery(queryMap, query, tokenValues);
}
for (Entry<String, String> query : getQueryParamKeyValues(method, args).entries()) {
queryMap.put(query.getKey(), replaceTokens(query.getValue(), tokenValues));
for (Entry<String, String> query : getQueryParamKeyValues(method, args)
.entries()) {
queryMap.put(query.getKey(), replaceTokens(query.getValue(),
tokenValues));
}
return queryMap;
}
@ -554,19 +598,21 @@ public class RestAnnotationProcessor<T> {
formParams.removeAll(form.keys()[i]);
formParams.put(form.keys()[i], null);
} else {
formParams.put(form.keys()[i], replaceTokens(form.values()[i], tokenValues));
formParams.put(form.keys()[i], replaceTokens(form.values()[i],
tokenValues));
}
}
}
private void addQuery(Multimap<String, String> queryParams, QueryParams query,
Collection<Entry<String, String>> tokenValues) {
private void addQuery(Multimap<String, String> queryParams,
QueryParams query, Collection<Entry<String, String>> tokenValues) {
for (int i = 0; i < query.keys().length; i++) {
if (query.values()[i].equals(QueryParams.NULL)) {
queryParams.removeAll(query.keys()[i]);
queryParams.put(query.keys()[i], null);
} else {
queryParams.put(query.keys()[i], replaceTokens(query.values()[i], tokenValues));
queryParams.put(query.keys()[i], replaceTokens(query.values()[i],
tokenValues));
}
}
}
@ -577,56 +623,82 @@ public class RestAnnotationProcessor<T> {
if (matrix.values()[i].equals(MatrixParams.NULL)) {
builder.replaceMatrix(matrix.keys()[i]);
} else {
builder.matrixParam(matrix.keys()[i], replaceTokens(matrix.values()[i], tokenValues));
builder.matrixParam(matrix.keys()[i], replaceTokens(
matrix.values()[i], tokenValues));
}
}
}
private void addFiltersIfAnnotated(Method method, HttpRequest request) {
if (declaring.isAnnotationPresent(RequestFilters.class)) {
for (Class<? extends HttpRequestFilter> clazz : declaring.getAnnotation(
RequestFilters.class).value()) {
for (Class<? extends HttpRequestFilter> clazz : declaring
.getAnnotation(RequestFilters.class).value()) {
HttpRequestFilter instance = injector.getInstance(clazz);
request.getFilters().add(instance);
logger.trace("%s - adding filter %s from annotation on %s", request, instance,
declaring.getName());
logger.trace("%s - adding filter %s from annotation on %s",
request, instance, declaring.getName());
}
}
if (method.isAnnotationPresent(RequestFilters.class)) {
if (method.isAnnotationPresent(OverrideRequestFilters.class))
request.getFilters().clear();
for (Class<? extends HttpRequestFilter> clazz : method.getAnnotation(RequestFilters.class)
.value()) {
for (Class<? extends HttpRequestFilter> clazz : method.getAnnotation(
RequestFilters.class).value()) {
HttpRequestFilter instance = injector.getInstance(clazz);
request.getFilters().add(instance);
logger.trace("%s - adding filter %s from annotation on %s", request, instance, method
.getName());
logger.trace("%s - adding filter %s from annotation on %s",
request, instance, method.getName());
}
}
}
@VisibleForTesting
URI getEndpointInParametersOrNull(Method method, Object... args) {
Map<Integer, Set<Annotation>> map = indexWithOnlyOneAnnotation(method, "@EndpointParam",
methodToIndexOfParamToEndpointParamAnnotations);
public static URI getEndpointInParametersOrNull(Method method,
Object[] args, Injector injector) {
Map<Integer, Set<Annotation>> map = RestAnnotationProcessor
.indexWithOnlyOneAnnotation(
method,
"@EndpointParam",
RestAnnotationProcessor.methodToIndexOfParamToEndpointParamAnnotations);
if (map.size() == 1 && args.length > 0) {
EndpointParam annotation = (EndpointParam) map.values().iterator().next().iterator()
.next();
EndpointParam annotation = (EndpointParam) map.values().iterator()
.next().iterator().next();
int index = map.keySet().iterator().next();
Function<Object, URI> parser = injector.getInstance(annotation.parser());
Function<Object, URI> parser = injector.getInstance(annotation
.parser());
try {
URI returnVal = parser.apply(args[index]);
checkArgument(returnVal != null, String.format(
"endpoint for [%s] not configured for %s", args[index], method));
"endpoint for [%s] not configured for %s", args[index],
method));
return returnVal;
} catch (NullPointerException e) {
logger.error("argument at index %d on method %s", index, method);
throw e;
throw new IllegalArgumentException(String.format(
"argument at index %d on method %s", index, method), e);
}
}
return null;
}
public static URI getEndpointFor(Method method, Object[] args, Injector injector) {
URI endpoint = getEndpointInParametersOrNull(method, args, injector);
if (endpoint == null) {
Endpoint annotation;
if (method.isAnnotationPresent(Endpoint.class)) {
annotation = method.getAnnotation(Endpoint.class);
} else if (method.getDeclaringClass().isAnnotationPresent(
Endpoint.class)) {
annotation = method.getDeclaringClass().getAnnotation(
Endpoint.class);
} else {
throw new IllegalStateException(
"no annotations on class or method: " + method);
}
return injector.getInstance(Key.get(URI.class, annotation.value()));
}
return endpoint;
}
public static final TypeLiteral<ListenableFuture<Boolean>> futureBooleanLiteral = new TypeLiteral<ListenableFuture<Boolean>>() {
};
@ -640,43 +712,52 @@ public class RestAnnotationProcessor<T> {
public static final TypeLiteral<ListenableFuture<InputStream>> futureInputStreamLiteral = new TypeLiteral<ListenableFuture<InputStream>>() {
};
public static Class<? extends Function<HttpResponse, ?>> getParserOrThrowException(Method method) {
public static Class<? extends Function<HttpResponse, ?>> getParserOrThrowException(
Method method) {
ResponseParser annotation = method.getAnnotation(ResponseParser.class);
if (annotation == null) {
if (method.getReturnType().equals(boolean.class)
|| method.getReturnType().equals(Boolean.class)
|| TypeLiteral.get(method.getGenericReturnType()).equals(futureBooleanLiteral)) {
|| TypeLiteral.get(method.getGenericReturnType()).equals(
futureBooleanLiteral)) {
return ReturnTrueIf2xx.class;
} else if (method.getReturnType().equals(String.class)
|| TypeLiteral.get(method.getGenericReturnType()).equals(futureStringLiteral)) {
|| TypeLiteral.get(method.getGenericReturnType()).equals(
futureStringLiteral)) {
return ReturnStringIf2xx.class;
} else if (method.getReturnType().equals(void.class)
|| TypeLiteral.get(method.getGenericReturnType()).equals(futureVoidLiteral)) {
|| TypeLiteral.get(method.getGenericReturnType()).equals(
futureVoidLiteral)) {
return ReleasePayloadAndReturn.class;
} else if (method.getReturnType().equals(URI.class)
|| TypeLiteral.get(method.getGenericReturnType()).equals(futureURILiteral)) {
|| TypeLiteral.get(method.getGenericReturnType()).equals(
futureURILiteral)) {
return ParseURIFromListOrLocationHeaderIf20x.class;
} else if (method.getReturnType().equals(InputStream.class)
|| TypeLiteral.get(method.getGenericReturnType())
.equals(futureInputStreamLiteral)) {
|| TypeLiteral.get(method.getGenericReturnType()).equals(
futureInputStreamLiteral)) {
return ReturnInputStream.class;
} else {
throw new IllegalStateException(
"You must specify a ResponseTransformer annotation on: " + method.toString());
"You must specify a ResponseTransformer annotation on: "
+ method.toString());
}
}
return annotation.value();
}
public static Class<? extends HandlerWithResult<?>> getSaxResponseParserClassOrNull(Method method) {
XMLResponseParser annotation = method.getAnnotation(XMLResponseParser.class);
public static Class<? extends HandlerWithResult<?>> getSaxResponseParserClassOrNull(
Method method) {
XMLResponseParser annotation = method
.getAnnotation(XMLResponseParser.class);
if (annotation != null) {
return annotation.value();
}
return null;
}
public org.jclouds.rest.MapBinder getMapPayloadBinderOrNull(Method method, Object... args) {
public org.jclouds.rest.MapBinder getMapPayloadBinderOrNull(Method method,
Object... args) {
if (args != null) {
for (Object arg : args) {
if (arg instanceof Object[]) {
@ -712,16 +793,19 @@ public class RestAnnotationProcessor<T> {
private Multimap<String, String> constants = LinkedHashMultimap.create();
public boolean isHttpMethod(Method method) {
return method.isAnnotationPresent(Path.class) || IsHttpMethod.getHttpMethods(method) != null;
return method.isAnnotationPresent(Path.class)
|| IsHttpMethod.getHttpMethods(method) != null;
}
public boolean isConstantDeclaration(Method method) {
return method.isAnnotationPresent(PathParam.class) && method.isAnnotationPresent(Named.class);
return method.isAnnotationPresent(PathParam.class)
&& method.isAnnotationPresent(Named.class);
}
public void bindConstant(Method method) {
String key = method.getAnnotation(PathParam.class).value();
String value = injector.getInstance(Key.get(String.class, method.getAnnotation(Named.class)));
String value = injector.getInstance(Key.get(String.class, method
.getAnnotation(Named.class)));
constants.put(key, value);
}
@ -735,18 +819,20 @@ public class RestAnnotationProcessor<T> {
return requests.iterator().next();
}
public void addHostHeaderIfAnnotatedWithVirtualHost(Multimap<String, String> headers,
String host, Method method) {
public void addHostHeaderIfAnnotatedWithVirtualHost(
Multimap<String, String> headers, String host, Method method) {
if (declaring.isAnnotationPresent(VirtualHost.class)
|| method.isAnnotationPresent(VirtualHost.class)) {
headers.put(HOST, host);
}
}
public void decorateRequest(GeneratedHttpRequest<T> request, Multimap<String, String> headers) {
org.jclouds.rest.MapBinder mapBinder = getMapPayloadBinderOrNull(request.getJavaMethod(),
public void decorateRequest(GeneratedHttpRequest<T> request,
Multimap<String, String> headers) {
org.jclouds.rest.MapBinder mapBinder = getMapPayloadBinderOrNull(request
.getJavaMethod(), request.getArgs());
Map<String, String> mapParams = buildPostParams(request.getJavaMethod(),
request.getArgs());
Map<String, String> mapParams = buildPostParams(request.getJavaMethod(), request.getArgs());
// MapPayloadBinder is only useful if there are parameters. We guard here
// in case the
// MapPayloadBinder is also an PayloadBinder. If so, it can be used with
@ -756,31 +842,37 @@ public class RestAnnotationProcessor<T> {
mapBinder.bindToRequest(request, mapParams);
} else {
OUTER: for (Entry<Integer, Set<Annotation>> entry : filterValues(
methodToIndexOfParamToDecoratorParamAnnotation.get(request.getJavaMethod()),
new Predicate<Set<Annotation>>() {
methodToIndexOfParamToDecoratorParamAnnotation.get(request
.getJavaMethod()), new Predicate<Set<Annotation>>() {
public boolean apply(Set<Annotation> input) {
return input.size() >= 1;
}
}).entrySet()) {
boolean shouldBreak = false;
BinderParam payloadAnnotation = (BinderParam) entry.getValue().iterator().next();
BinderParam payloadAnnotation = (BinderParam) entry.getValue()
.iterator().next();
Binder binder = injector.getInstance(payloadAnnotation.value());
if (request.getArgs().length >= entry.getKey() + 1
&& request.getArgs()[entry.getKey()] != null) {
Object input;
Class<?> parameterType = request.getJavaMethod().getParameterTypes()[entry.getKey()];
Class<? extends Object> argType = request.getArgs()[entry.getKey()].getClass();
Class<?> parameterType = request.getJavaMethod()
.getParameterTypes()[entry.getKey()];
Class<? extends Object> argType = request.getArgs()[entry
.getKey()].getClass();
if (!argType.isArray() && request.getJavaMethod().isVarArgs()
&& parameterType.isArray()) {
int arrayLength = request.getArgs().length
- request.getJavaMethod().getParameterTypes().length + 1;
- request.getJavaMethod().getParameterTypes().length
+ 1;
if (arrayLength == 0)
break OUTER;
input = (Object[]) Array.newInstance(
request.getArgs()[entry.getKey()].getClass(), arrayLength);
System.arraycopy(request.getArgs(), entry.getKey(), input, 0, arrayLength);
input = (Object[]) Array.newInstance(request.getArgs()[entry
.getKey()].getClass(), arrayLength);
System.arraycopy(request.getArgs(), entry.getKey(), input, 0,
arrayLength);
shouldBreak = true;
} else if (argType.isArray() && request.getJavaMethod().isVarArgs()
} else if (argType.isArray()
&& request.getJavaMethod().isVarArgs()
&& parameterType.isArray()) {
input = request.getArgs()[entry.getKey()];
} else {
@ -801,19 +893,23 @@ public class RestAnnotationProcessor<T> {
utils.setPayloadPropertiesFromHeaders(headers, request);
}
protected Map<Integer, Set<Annotation>> indexWithOnlyOneAnnotation(Method method,
String description, Map<Method, Map<Integer, Set<Annotation>>> toRefine) {
Map<Integer, Set<Annotation>> indexToPayloadAnnotation = filterValues(toRefine.get(method),
new Predicate<Set<Annotation>>() {
public static Map<Integer, Set<Annotation>> indexWithOnlyOneAnnotation(
Method method, String description,
Map<Method, Map<Integer, Set<Annotation>>> toRefine) {
Map<Integer, Set<Annotation>> indexToPayloadAnnotation = filterValues(
toRefine.get(method), new Predicate<Set<Annotation>>() {
public boolean apply(Set<Annotation> input) {
return input.size() == 1;
}
});
if (indexToPayloadAnnotation.size() > 1) {
throw new IllegalStateException(String.format(
"You must not specify more than one %s annotation on: %s; found %s", description,
method.toString(), indexToPayloadAnnotation));
throw new IllegalStateException(
String
.format(
"You must not specify more than one %s annotation on: %s; found %s",
description, method.toString(),
indexToPayloadAnnotation));
}
return indexToPayloadAnnotation;
}
@ -845,13 +941,15 @@ public class RestAnnotationProcessor<T> {
return null;
}
public Multimap<String, String> buildHeaders(Collection<Entry<String, String>> tokenValues,
Method method, final Object... args) {
public Multimap<String, String> buildHeaders(
Collection<Entry<String, String>> tokenValues, Method method,
final Object... args) {
Multimap<String, String> headers = LinkedHashMultimap.create();
addHeaderIfAnnotationPresentOnMethod(headers, method, tokenValues);
Map<Integer, Set<Annotation>> indexToHeaderParam = methodToIndexOfParamToHeaderParamAnnotations
.get(method);
for (Entry<Integer, Set<Annotation>> entry : indexToHeaderParam.entrySet()) {
for (Entry<Integer, Set<Annotation>> entry : indexToHeaderParam
.entrySet()) {
for (Annotation key : entry.getValue()) {
String value = args[entry.getKey()].toString();
value = replaceTokens(value, tokenValues);
@ -863,7 +961,8 @@ public class RestAnnotationProcessor<T> {
return headers;
}
void addConsumesIfPresentOnTypeOrMethod(Multimap<String, String> headers, Method method) {
void addConsumesIfPresentOnTypeOrMethod(Multimap<String, String> headers,
Method method) {
if (declaring.isAnnotationPresent(Consumes.class)) {
Consumes header = declaring.getAnnotation(Consumes.class);
headers.replaceValues(ACCEPT, asList(header.value()));
@ -874,7 +973,8 @@ public class RestAnnotationProcessor<T> {
}
}
void addProducesIfPresentOnTypeOrMethod(Multimap<String, String> headers, Method method) {
void addProducesIfPresentOnTypeOrMethod(Multimap<String, String> headers,
Method method) {
if (declaring.isAnnotationPresent(Produces.class)) {
Produces header = declaring.getAnnotation(Produces.class);
headers.replaceValues(CONTENT_TYPE, asList(header.value()));
@ -885,8 +985,9 @@ public class RestAnnotationProcessor<T> {
}
}
public void addHeaderIfAnnotationPresentOnMethod(Multimap<String, String> headers,
Method method, Collection<Entry<String, String>> tokenValues) {
public void addHeaderIfAnnotationPresentOnMethod(
Multimap<String, String> headers, Method method,
Collection<Entry<String, String>> tokenValues) {
if (declaring.isAnnotationPresent(Headers.class)) {
Headers header = declaring.getAnnotation(Headers.class);
addHeader(headers, header, tokenValues);
@ -928,7 +1029,8 @@ public class RestAnnotationProcessor<T> {
options.contentType(param.contentType());
if (!PartParam.NO_FILENAME.equals(param.filename()))
options.filename(replaceTokens(param.filename(), iterable));
Part part = Part.create(param.name(), newPayload(args[entry.getKey()]), options);
Part part = Part.create(param.name(), newPayload(args[entry
.getKey()]), options);
parts.add(part);
}
}
@ -946,7 +1048,8 @@ public class RestAnnotationProcessor<T> {
return null;
}
private Multimap<String, String> getPathParamKeyValues(Method method, Object... args) {
private Multimap<String, String> getPathParamKeyValues(Method method,
Object... args) {
Multimap<String, String> pathParamValues = LinkedHashMultimap.create();
pathParamValues.putAll(constants);
Map<Integer, Set<Annotation>> indexToPathParam = methodToIndexOfParamToPathParamAnnotations
@ -956,12 +1059,15 @@ public class RestAnnotationProcessor<T> {
.get(method);
for (Entry<Integer, Set<Annotation>> entry : indexToPathParam.entrySet()) {
for (Annotation key : entry.getValue()) {
Set<Annotation> extractors = indexToParamExtractor.get(entry.getKey());
Set<Annotation> extractors = indexToParamExtractor.get(entry
.getKey());
String paramKey = ((PathParam) key).value();
String paramValue;
if (extractors != null && extractors.size() > 0) {
ParamParser extractor = (ParamParser) extractors.iterator().next();
paramValue = injector.getInstance(extractor.value()).apply(args[entry.getKey()]);
ParamParser extractor = (ParamParser) extractors.iterator()
.next();
paramValue = injector.getInstance(extractor.value()).apply(
args[entry.getKey()]);
} else {
paramValue = args[entry.getKey()].toString();
}
@ -972,15 +1078,16 @@ public class RestAnnotationProcessor<T> {
if (method.isAnnotationPresent(PathParam.class)
&& method.isAnnotationPresent(ParamParser.class)) {
String paramKey = method.getAnnotation(PathParam.class).value();
String paramValue = injector.getInstance(method.getAnnotation(ParamParser.class).value())
.apply(args);
String paramValue = injector.getInstance(
method.getAnnotation(ParamParser.class).value()).apply(args);
pathParamValues.put(paramKey, paramValue);
}
return pathParamValues;
}
private Multimap<String, String> encodeValues(Multimap<String, String> unencoded, char... skips) {
private Multimap<String, String> encodeValues(
Multimap<String, String> unencoded, char... skips) {
Multimap<String, String> encoded = LinkedHashMultimap.create();
for (Entry<String, String> entry : unencoded.entries()) {
encoded.put(entry.getKey(), urlEncode(entry.getValue(), skips));
@ -988,7 +1095,8 @@ public class RestAnnotationProcessor<T> {
return encoded;
}
private Multimap<String, String> getMatrixParamKeyValues(Method method, Object... args) {
private Multimap<String, String> getMatrixParamKeyValues(Method method,
Object... args) {
Multimap<String, String> matrixParamValues = LinkedHashMultimap.create();
matrixParamValues.putAll(constants);
Map<Integer, Set<Annotation>> indexToMatrixParam = methodToIndexOfParamToMatrixParamAnnotations
@ -996,14 +1104,18 @@ public class RestAnnotationProcessor<T> {
Map<Integer, Set<Annotation>> indexToParamExtractor = methodToIndexOfParamToParamParserAnnotations
.get(method);
for (Entry<Integer, Set<Annotation>> entry : indexToMatrixParam.entrySet()) {
for (Entry<Integer, Set<Annotation>> entry : indexToMatrixParam
.entrySet()) {
for (Annotation key : entry.getValue()) {
Set<Annotation> extractors = indexToParamExtractor.get(entry.getKey());
Set<Annotation> extractors = indexToParamExtractor.get(entry
.getKey());
String paramKey = ((MatrixParam) key).value();
String paramValue;
if (extractors != null && extractors.size() > 0) {
ParamParser extractor = (ParamParser) extractors.iterator().next();
paramValue = injector.getInstance(extractor.value()).apply(args[entry.getKey()]);
ParamParser extractor = (ParamParser) extractors.iterator()
.next();
paramValue = injector.getInstance(extractor.value()).apply(
args[entry.getKey()]);
} else {
paramValue = args[entry.getKey()].toString();
}
@ -1014,15 +1126,16 @@ public class RestAnnotationProcessor<T> {
if (method.isAnnotationPresent(MatrixParam.class)
&& method.isAnnotationPresent(ParamParser.class)) {
String paramKey = method.getAnnotation(MatrixParam.class).value();
String paramValue = injector.getInstance(method.getAnnotation(ParamParser.class).value())
.apply(args);
String paramValue = injector.getInstance(
method.getAnnotation(ParamParser.class).value()).apply(args);
matrixParamValues.put(paramKey, paramValue);
}
return matrixParamValues;
}
private Multimap<String, String> getFormParamKeyValues(Method method, Object... args) {
private Multimap<String, String> getFormParamKeyValues(Method method,
Object... args) {
Multimap<String, String> formParamValues = LinkedHashMultimap.create();
formParamValues.putAll(constants);
Map<Integer, Set<Annotation>> indexToFormParam = methodToIndexOfParamToFormParamAnnotations
@ -1032,12 +1145,15 @@ public class RestAnnotationProcessor<T> {
.get(method);
for (Entry<Integer, Set<Annotation>> entry : indexToFormParam.entrySet()) {
for (Annotation key : entry.getValue()) {
Set<Annotation> extractors = indexToParamExtractor.get(entry.getKey());
Set<Annotation> extractors = indexToParamExtractor.get(entry
.getKey());
String paramKey = ((FormParam) key).value();
String paramValue;
if (extractors != null && extractors.size() > 0) {
ParamParser extractor = (ParamParser) extractors.iterator().next();
paramValue = injector.getInstance(extractor.value()).apply(args[entry.getKey()]);
ParamParser extractor = (ParamParser) extractors.iterator()
.next();
paramValue = injector.getInstance(extractor.value()).apply(
args[entry.getKey()]);
} else {
paramValue = args[entry.getKey()].toString();
}
@ -1048,15 +1164,16 @@ public class RestAnnotationProcessor<T> {
if (method.isAnnotationPresent(FormParam.class)
&& method.isAnnotationPresent(ParamParser.class)) {
String paramKey = method.getAnnotation(FormParam.class).value();
String paramValue = injector.getInstance(method.getAnnotation(ParamParser.class).value())
.apply(args);
String paramValue = injector.getInstance(
method.getAnnotation(ParamParser.class).value()).apply(args);
formParamValues.put(paramKey, paramValue);
}
return formParamValues;
}
private Multimap<String, String> getQueryParamKeyValues(Method method, Object... args) {
private Multimap<String, String> getQueryParamKeyValues(Method method,
Object... args) {
Multimap<String, String> queryParamValues = LinkedHashMultimap.create();
queryParamValues.putAll(constants);
Map<Integer, Set<Annotation>> indexToQueryParam = methodToIndexOfParamToQueryParamAnnotations
@ -1066,12 +1183,15 @@ public class RestAnnotationProcessor<T> {
.get(method);
for (Entry<Integer, Set<Annotation>> entry : indexToQueryParam.entrySet()) {
for (Annotation key : entry.getValue()) {
Set<Annotation> extractors = indexToParamExtractor.get(entry.getKey());
Set<Annotation> extractors = indexToParamExtractor.get(entry
.getKey());
String paramKey = ((QueryParam) key).value();
String paramValue;
if (extractors != null && extractors.size() > 0) {
ParamParser extractor = (ParamParser) extractors.iterator().next();
paramValue = injector.getInstance(extractor.value()).apply(args[entry.getKey()]);
ParamParser extractor = (ParamParser) extractors.iterator()
.next();
paramValue = injector.getInstance(extractor.value()).apply(
args[entry.getKey()]);
} else {
paramValue = args[entry.getKey()].toString();
}
@ -1082,8 +1202,8 @@ public class RestAnnotationProcessor<T> {
if (method.isAnnotationPresent(QueryParam.class)
&& method.isAnnotationPresent(ParamParser.class)) {
String paramKey = method.getAnnotation(QueryParam.class).value();
String paramValue = injector.getInstance(method.getAnnotation(ParamParser.class).value())
.apply(args);
String paramValue = injector.getInstance(
method.getAnnotation(ParamParser.class).value()).apply(args);
queryParamValues.put(paramKey, paramValue);
}
@ -1098,12 +1218,15 @@ public class RestAnnotationProcessor<T> {
.get(method);
for (Entry<Integer, Set<Annotation>> entry : indexToPathParam.entrySet()) {
for (Annotation key : entry.getValue()) {
Set<Annotation> extractors = indexToParamExtractor.get(entry.getKey());
Set<Annotation> extractors = indexToParamExtractor.get(entry
.getKey());
String paramKey = ((MapPayloadParam) key).value();
String paramValue;
if (extractors != null && extractors.size() > 0) {
ParamParser extractor = (ParamParser) extractors.iterator().next();
paramValue = injector.getInstance(extractor.value()).apply(args[entry.getKey()]);
ParamParser extractor = (ParamParser) extractors.iterator()
.next();
paramValue = injector.getInstance(extractor.value()).apply(
args[entry.getKey()]);
} else {
paramValue = args[entry.getKey()].toString();
@ -1115,19 +1238,4 @@ public class RestAnnotationProcessor<T> {
return postParams;
}
public URI getEndpointFor(Method method, Object... args) {
URI endpoint = getEndpointInParametersOrNull(method, args);
if (endpoint == null) {
Endpoint annotation;
if (method.isAnnotationPresent(Endpoint.class)) {
annotation = method.getAnnotation(Endpoint.class);
} else if (method.getDeclaringClass().isAnnotationPresent(Endpoint.class)) {
annotation = method.getDeclaringClass().getAnnotation(Endpoint.class);
} else {
throw new IllegalStateException("no annotations on class or method: " + method);
}
return injector.getInstance(Key.get(URI.class, annotation.value()));
}
return endpoint;
}
}