mirror of https://github.com/apache/jclouds.git
JCLOUDS-152 remove RestContext and its dependencies.
This commit is contained in:
parent
67c49efeb3
commit
65d40b4435
|
@ -18,12 +18,10 @@ package org.jclouds;
|
||||||
|
|
||||||
import static com.google.common.base.Objects.toStringHelper;
|
import static com.google.common.base.Objects.toStringHelper;
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
import static com.google.common.base.Predicates.and;
|
|
||||||
import static com.google.common.base.Predicates.containsPattern;
|
import static com.google.common.base.Predicates.containsPattern;
|
||||||
import static com.google.common.base.Predicates.instanceOf;
|
import static com.google.common.base.Predicates.instanceOf;
|
||||||
import static com.google.common.base.Predicates.not;
|
import static com.google.common.base.Predicates.not;
|
||||||
import static com.google.common.base.Predicates.notNull;
|
import static com.google.common.base.Predicates.notNull;
|
||||||
import static com.google.common.base.Predicates.or;
|
|
||||||
import static com.google.common.base.Throwables.propagate;
|
import static com.google.common.base.Throwables.propagate;
|
||||||
import static com.google.common.collect.Iterables.addAll;
|
import static com.google.common.collect.Iterables.addAll;
|
||||||
import static com.google.common.collect.Iterables.any;
|
import static com.google.common.collect.Iterables.any;
|
||||||
|
@ -43,6 +41,7 @@ import static org.jclouds.Constants.PROPERTY_IDENTITY;
|
||||||
import static org.jclouds.Constants.PROPERTY_ISO3166_CODES;
|
import static org.jclouds.Constants.PROPERTY_ISO3166_CODES;
|
||||||
import static org.jclouds.Constants.PROPERTY_PROVIDER;
|
import static org.jclouds.Constants.PROPERTY_PROVIDER;
|
||||||
import static org.jclouds.reflect.Reflection2.typeToken;
|
import static org.jclouds.reflect.Reflection2.typeToken;
|
||||||
|
import static org.jclouds.rest.config.BinderUtils.bindHttpApi;
|
||||||
import static org.jclouds.util.Throwables2.propagateAuthorizationOrOriginalException;
|
import static org.jclouds.util.Throwables2.propagateAuthorizationOrOriginalException;
|
||||||
|
|
||||||
import java.io.Closeable;
|
import java.io.Closeable;
|
||||||
|
@ -60,7 +59,6 @@ import org.jclouds.concurrent.config.ExecutorServiceModule;
|
||||||
import org.jclouds.config.BindApiContextWithWildcardExtendsExplicitAndRawType;
|
import org.jclouds.config.BindApiContextWithWildcardExtendsExplicitAndRawType;
|
||||||
import org.jclouds.config.BindNameToContext;
|
import org.jclouds.config.BindNameToContext;
|
||||||
import org.jclouds.config.BindPropertiesToExpandedValues;
|
import org.jclouds.config.BindPropertiesToExpandedValues;
|
||||||
import org.jclouds.config.BindRestContextWithWildcardExtendsExplicitAndRawType;
|
|
||||||
import org.jclouds.domain.Credentials;
|
import org.jclouds.domain.Credentials;
|
||||||
import org.jclouds.events.config.ConfiguresEventBus;
|
import org.jclouds.events.config.ConfiguresEventBus;
|
||||||
import org.jclouds.events.config.EventBusModule;
|
import org.jclouds.events.config.EventBusModule;
|
||||||
|
@ -74,16 +72,15 @@ import org.jclouds.providers.ProviderMetadata;
|
||||||
import org.jclouds.providers.Providers;
|
import org.jclouds.providers.Providers;
|
||||||
import org.jclouds.providers.config.BindProviderMetadataContextAndCredentials;
|
import org.jclouds.providers.config.BindProviderMetadataContextAndCredentials;
|
||||||
import org.jclouds.providers.internal.UpdateProviderMetadataFromProperties;
|
import org.jclouds.providers.internal.UpdateProviderMetadataFromProperties;
|
||||||
|
import org.jclouds.reflect.Invocation;
|
||||||
import org.jclouds.rest.ConfiguresCredentialStore;
|
import org.jclouds.rest.ConfiguresCredentialStore;
|
||||||
import org.jclouds.rest.ConfiguresHttpApi;
|
import org.jclouds.rest.ConfiguresHttpApi;
|
||||||
import org.jclouds.rest.ConfiguresRestClient;
|
|
||||||
import org.jclouds.rest.HttpApiMetadata;
|
import org.jclouds.rest.HttpApiMetadata;
|
||||||
import org.jclouds.rest.RestApiMetadata;
|
import org.jclouds.rest.HttpClient;
|
||||||
import org.jclouds.rest.config.CredentialStoreModule;
|
import org.jclouds.rest.config.CredentialStoreModule;
|
||||||
import org.jclouds.rest.config.HttpApiModule;
|
import org.jclouds.rest.config.HttpApiModule;
|
||||||
import org.jclouds.rest.config.SyncToAsyncHttpInvocationModule;
|
|
||||||
import org.jclouds.rest.config.RestClientModule;
|
|
||||||
import org.jclouds.rest.config.RestModule;
|
import org.jclouds.rest.config.RestModule;
|
||||||
|
import org.jclouds.rest.internal.InvokeHttpMethod;
|
||||||
|
|
||||||
import com.google.common.annotations.VisibleForTesting;
|
import com.google.common.annotations.VisibleForTesting;
|
||||||
import com.google.common.base.Function;
|
import com.google.common.base.Function;
|
||||||
|
@ -100,6 +97,7 @@ import com.google.common.collect.ImmutableSet;
|
||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
import com.google.common.reflect.TypeToken;
|
import com.google.common.reflect.TypeToken;
|
||||||
import com.google.common.util.concurrent.ExecutionList;
|
import com.google.common.util.concurrent.ExecutionList;
|
||||||
|
import com.google.inject.AbstractModule;
|
||||||
import com.google.inject.Guice;
|
import com.google.inject.Guice;
|
||||||
import com.google.inject.Injector;
|
import com.google.inject.Injector;
|
||||||
import com.google.inject.Key;
|
import com.google.inject.Key;
|
||||||
|
@ -426,13 +424,6 @@ public class ContextBuilder {
|
||||||
.add(new BindApiContextWithWildcardExtendsExplicitAndRawType(HttpApiMetadata.class.cast(apiMetadata)));
|
.add(new BindApiContextWithWildcardExtendsExplicitAndRawType(HttpApiMetadata.class.cast(apiMetadata)));
|
||||||
} catch (IllegalArgumentException ignored) {
|
} catch (IllegalArgumentException ignored) {
|
||||||
|
|
||||||
}
|
|
||||||
} else if (apiMetadata instanceof RestApiMetadata) {
|
|
||||||
try {
|
|
||||||
modules.add(new BindRestContextWithWildcardExtendsExplicitAndRawType(RestApiMetadata.class
|
|
||||||
.cast(apiMetadata)));
|
|
||||||
} catch (IllegalArgumentException ignored) {
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -455,7 +446,7 @@ public class ContextBuilder {
|
||||||
|
|
||||||
});
|
});
|
||||||
if (restModuleSpecifiedByUser)
|
if (restModuleSpecifiedByUser)
|
||||||
defaultModules = filter(defaultModules, and(not(configuresApi), not(configuresRest)));
|
defaultModules = filter(defaultModules, not(configuresApi));
|
||||||
return defaultModules;
|
return defaultModules;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -493,7 +484,7 @@ public class ContextBuilder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private static boolean apiModulePresent(List<Module> modules) {
|
private static boolean apiModulePresent(List<Module> modules) {
|
||||||
return any(modules, or(configuresApi, configuresRest));
|
return any(modules, configuresApi);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Predicate<Module> configuresApi = new Predicate<Module>() {
|
private static Predicate<Module> configuresApi = new Predicate<Module>() {
|
||||||
|
@ -503,25 +494,22 @@ public class ContextBuilder {
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
private static Predicate<Module> configuresRest = new Predicate<Module>() {
|
|
||||||
public boolean apply(Module input) {
|
|
||||||
return input.getClass().isAnnotationPresent(ConfiguresRestClient.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||||
static void addClientModule(ApiMetadata apiMetadata, List<Module> modules) {
|
static void addClientModule(ApiMetadata apiMetadata, List<Module> modules) {
|
||||||
// TODO: move this up
|
// TODO: move this up
|
||||||
if (apiMetadata instanceof HttpApiMetadata) {
|
if (apiMetadata instanceof HttpApiMetadata) {
|
||||||
HttpApiMetadata api = HttpApiMetadata.class.cast(apiMetadata);
|
HttpApiMetadata api = HttpApiMetadata.class.cast(apiMetadata);
|
||||||
modules.add(new HttpApiModule(api.getApi()));
|
modules.add(new HttpApiModule(api.getApi()));
|
||||||
} else if (apiMetadata instanceof RestApiMetadata) {
|
|
||||||
RestApiMetadata rest = RestApiMetadata.class.cast(apiMetadata);
|
|
||||||
modules.add(new RestClientModule(typeToken(rest.getApi()), typeToken(rest.getAsyncApi())));
|
|
||||||
} else {
|
} else {
|
||||||
modules.add(new RestModule());
|
modules.add(new RestModule());
|
||||||
modules.add(new SyncToAsyncHttpInvocationModule());
|
// Minimally bind HttpClient so that Utils works.
|
||||||
|
modules.add(new AbstractModule() {
|
||||||
|
@Override public void configure() {
|
||||||
|
bind(new TypeLiteral<Function<Invocation, Object>>() {
|
||||||
|
}).to(InvokeHttpMethod.class);
|
||||||
|
bindHttpApi(binder(), HttpClient.class);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -570,12 +558,13 @@ public class ContextBuilder {
|
||||||
)) {
|
)) {
|
||||||
modules.add(new CredentialStoreModule());
|
modules.add(new CredentialStoreModule());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Builds the base context for this api. Note that this may be of type {@link Closer}, if nothing
|
* Builds the base context for this api. Note that this may be of type {@link Closer}, if nothing
|
||||||
* else was configured via {@link ApiMetadata#getContext()}. Typically, the type returned is
|
* else was configured via {@link ApiMetadata#getContext()}. Typically, the type returned is
|
||||||
* {@link RestContext}
|
* {@link ApiContext}
|
||||||
*
|
*
|
||||||
* @see ApiMetadata#getContext()
|
* @see ApiMetadata#getContext()
|
||||||
* @see #build(TypeToken)
|
* @see #build(TypeToken)
|
||||||
|
|
|
@ -20,7 +20,6 @@ import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
import static com.google.common.base.Strings.emptyToNull;
|
import static com.google.common.base.Strings.emptyToNull;
|
||||||
|
|
||||||
import org.jclouds.View;
|
import org.jclouds.View;
|
||||||
import org.jclouds.rest.RestApiMetadata;
|
|
||||||
|
|
||||||
import com.google.common.base.Predicate;
|
import com.google.common.base.Predicate;
|
||||||
import com.google.common.base.Predicates;
|
import com.google.common.base.Predicates;
|
||||||
|
@ -69,35 +68,6 @@ public class ApiPredicates {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns all apis with the given type.
|
|
||||||
*
|
|
||||||
* @param type
|
|
||||||
* the type of the api to return
|
|
||||||
*
|
|
||||||
* @return the apis with the given type
|
|
||||||
*/
|
|
||||||
public static Predicate<RestApiMetadata> apiAssignableFrom(final TypeToken<?> type) {
|
|
||||||
checkNotNull(type, "type must be defined");
|
|
||||||
return new Predicate<RestApiMetadata>() {
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public boolean apply(RestApiMetadata apiMetadata) {
|
|
||||||
return type.isAssignableFrom(apiMetadata.getApi());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "contextAssignableFrom(" + type + ")";
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns all apis who's contexts are assignable from the parameter
|
* Returns all apis who's contexts are assignable from the parameter
|
||||||
*
|
*
|
||||||
|
|
|
@ -1,69 +0,0 @@
|
||||||
/*
|
|
||||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
||||||
* contributor license agreements. See the NOTICE file distributed with
|
|
||||||
* this work for additional information regarding copyright ownership.
|
|
||||||
* The ASF licenses this file to You 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.config;
|
|
||||||
import static com.google.common.base.Preconditions.checkArgument;
|
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
|
||||||
import static org.jclouds.reflect.Reflection2.typeToken;
|
|
||||||
|
|
||||||
import org.jclouds.rest.RestApiMetadata;
|
|
||||||
import org.jclouds.rest.RestContext;
|
|
||||||
import org.jclouds.rest.internal.BaseRestApiMetadata;
|
|
||||||
import org.jclouds.rest.internal.RestContextImpl;
|
|
||||||
|
|
||||||
import com.google.common.reflect.TypeToken;
|
|
||||||
import com.google.inject.AbstractModule;
|
|
||||||
import com.google.inject.TypeLiteral;
|
|
||||||
import com.google.inject.util.Types;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Allows you to lookup the {@link RestApiMetadata#getContext()} as {@link RestContext}, {@code RestContext<Client, AsyncClient>}, and {@code
|
|
||||||
*
|
|
||||||
* @deprecated please use {@link BindApiContextWithWildcardExtendsExplicitAndRawType} as
|
|
||||||
* async interface will be removed in jclouds 1.7.
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
public class BindRestContextWithWildcardExtendsExplicitAndRawType extends AbstractModule {
|
|
||||||
private final RestApiMetadata restApiMetadata;
|
|
||||||
|
|
||||||
public BindRestContextWithWildcardExtendsExplicitAndRawType(RestApiMetadata restApiMetadata)
|
|
||||||
throws IllegalArgumentException {
|
|
||||||
this.restApiMetadata = checkNotNull(restApiMetadata, "restApiMetadata");
|
|
||||||
checkArgument(restApiMetadata.getContext().getRawType().equals(RestContext.class),
|
|
||||||
"this does not work as %s raw type is not RestContext", restApiMetadata.getContext());
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
@Override
|
|
||||||
protected void configure() {
|
|
||||||
TypeToken<?> concreteType = BaseRestApiMetadata.contextToken(typeToken(restApiMetadata.getApi()),
|
|
||||||
typeToken(restApiMetadata.getAsyncApi()));
|
|
||||||
// bind explicit type
|
|
||||||
bind(TypeLiteral.get(concreteType.getType())).to(
|
|
||||||
TypeLiteral.class.cast(TypeLiteral.get(Types.newParameterizedType(RestContextImpl.class,
|
|
||||||
restApiMetadata.getApi(), restApiMetadata.getAsyncApi()))));
|
|
||||||
// bind potentially wildcard type
|
|
||||||
if (!concreteType.equals(restApiMetadata.getContext())) {
|
|
||||||
bind(TypeLiteral.get(restApiMetadata.getContext().getType())).to(
|
|
||||||
TypeLiteral.class.cast(TypeLiteral.get(Types.newParameterizedType(RestContextImpl.class,
|
|
||||||
restApiMetadata.getApi(), restApiMetadata.getAsyncApi()))));
|
|
||||||
}
|
|
||||||
// bind w/o types
|
|
||||||
bind(TypeLiteral.get(RestContext.class)).to(
|
|
||||||
TypeLiteral.class.cast(TypeLiteral.get(Types.newParameterizedType(RestContextImpl.class,
|
|
||||||
restApiMetadata.getApi(), restApiMetadata.getAsyncApi()))));
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -21,7 +21,6 @@ import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
import org.jclouds.apis.ApiMetadata;
|
import org.jclouds.apis.ApiMetadata;
|
||||||
import org.jclouds.providers.internal.BaseProviderMetadata;
|
import org.jclouds.providers.internal.BaseProviderMetadata;
|
||||||
import org.jclouds.rest.AnonymousHttpApiMetadata;
|
import org.jclouds.rest.AnonymousHttpApiMetadata;
|
||||||
import org.jclouds.rest.AnonymousRestApiMetadata;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Useful in creating arbitrary clients.
|
* Useful in creating arbitrary clients.
|
||||||
|
@ -32,10 +31,6 @@ public class AnonymousProviderMetadata extends BaseProviderMetadata {
|
||||||
return forApiWithEndpoint(AnonymousHttpApiMetadata.forApi(api), endpoint);
|
return forApiWithEndpoint(AnonymousHttpApiMetadata.forApi(api), endpoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ProviderMetadata forClientMappedToAsyncClientOnEndpoint(Class<?> client, Class<?> asyncClient,
|
|
||||||
String endpoint) {
|
|
||||||
return forApiWithEndpoint(AnonymousRestApiMetadata.forClientMappedToAsyncClient(client, asyncClient), endpoint);
|
|
||||||
}
|
|
||||||
public static ProviderMetadata forApiWithEndpoint(ApiMetadata md, String endpoint) {
|
public static ProviderMetadata forApiWithEndpoint(ApiMetadata md, String endpoint) {
|
||||||
checkNotNull(md, "api");
|
checkNotNull(md, "api");
|
||||||
checkNotNull(endpoint, "endpoint (%s)", md.getEndpointName());
|
checkNotNull(endpoint, "endpoint (%s)", md.getEndpointName());
|
||||||
|
|
|
@ -1,73 +0,0 @@
|
||||||
/*
|
|
||||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
||||||
* contributor license agreements. See the NOTICE file distributed with
|
|
||||||
* this work for additional information regarding copyright ownership.
|
|
||||||
* The ASF licenses this file to You 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;
|
|
||||||
|
|
||||||
import java.net.URI;
|
|
||||||
|
|
||||||
import org.jclouds.rest.internal.BaseRestApiMetadata;
|
|
||||||
|
|
||||||
import com.google.common.annotations.Beta;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Useful in creating arbitrary clients.
|
|
||||||
*
|
|
||||||
* @deprecated please use {@link AnonymousHttpApiMetadata} as
|
|
||||||
* async interface will be removed in jclouds 1.7.
|
|
||||||
*/
|
|
||||||
@Beta
|
|
||||||
@Deprecated
|
|
||||||
public class AnonymousRestApiMetadata extends BaseRestApiMetadata {
|
|
||||||
|
|
||||||
public static AnonymousRestApiMetadata forClientMappedToAsyncClient(Class<?> client, Class<?> asyncClient) {
|
|
||||||
return new AnonymousRestApiMetadata(client, asyncClient);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Builder toBuilder() {
|
|
||||||
return new Builder(getApi(), getAsyncApi()).fromApiMetadata(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
public AnonymousRestApiMetadata(Class<?> client, Class<?> asyncClient) {
|
|
||||||
super(new Builder(client, asyncClient));
|
|
||||||
}
|
|
||||||
|
|
||||||
protected AnonymousRestApiMetadata(Builder builder) {
|
|
||||||
super(builder);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static final class Builder extends BaseRestApiMetadata.Builder<Builder> {
|
|
||||||
|
|
||||||
public Builder(Class<?> client, Class<?> asyncClient) {
|
|
||||||
super(client, asyncClient);
|
|
||||||
id(client.getSimpleName())
|
|
||||||
.identityName("unused")
|
|
||||||
.defaultIdentity("foo")
|
|
||||||
.version("1")
|
|
||||||
.documentation(URI.create("http://jclouds.org/documentation"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public AnonymousRestApiMetadata build() {
|
|
||||||
return new AnonymousRestApiMetadata(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Builder self() {
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,32 +0,0 @@
|
||||||
/*
|
|
||||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
||||||
* contributor license agreements. See the NOTICE file distributed with
|
|
||||||
* this work for additional information regarding copyright ownership.
|
|
||||||
* The ASF licenses this file to You 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;
|
|
||||||
|
|
||||||
import static java.lang.annotation.ElementType.TYPE;
|
|
||||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
|
||||||
|
|
||||||
import java.lang.annotation.Retention;
|
|
||||||
import java.lang.annotation.Target;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* designates the module configures a Client to a cloud.
|
|
||||||
*/
|
|
||||||
@Retention(RUNTIME)
|
|
||||||
@Target(TYPE)
|
|
||||||
public @interface ConfiguresRestClient {
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,88 +0,0 @@
|
||||||
/*
|
|
||||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
||||||
* contributor license agreements. See the NOTICE file distributed with
|
|
||||||
* this work for additional information regarding copyright ownership.
|
|
||||||
* The ASF licenses this file to You 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;
|
|
||||||
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.net.URI;
|
|
||||||
|
|
||||||
import javax.ws.rs.DELETE;
|
|
||||||
import javax.ws.rs.GET;
|
|
||||||
import javax.ws.rs.HEAD;
|
|
||||||
import javax.ws.rs.POST;
|
|
||||||
import javax.ws.rs.PUT;
|
|
||||||
|
|
||||||
import org.jclouds.Fallbacks.FalseOnNotFoundOr404;
|
|
||||||
import org.jclouds.Fallbacks.NullOnNotFoundOr404;
|
|
||||||
import org.jclouds.http.HttpRequest;
|
|
||||||
import org.jclouds.http.HttpResponse;
|
|
||||||
import org.jclouds.http.functions.ParseETagHeader;
|
|
||||||
import org.jclouds.io.Payload;
|
|
||||||
import org.jclouds.rest.annotations.EndpointParam;
|
|
||||||
import org.jclouds.rest.annotations.Fallback;
|
|
||||||
import org.jclouds.rest.annotations.ResponseParser;
|
|
||||||
|
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Simple rest client
|
|
||||||
*
|
|
||||||
* @deprecated will be removed in jclouds 1.7, as async interfaces are no longer
|
|
||||||
* supported.
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
public interface HttpAsyncClient {
|
|
||||||
/**
|
|
||||||
* @see HttpClient#put
|
|
||||||
*/
|
|
||||||
@PUT
|
|
||||||
@ResponseParser(ParseETagHeader.class)
|
|
||||||
ListenableFuture<String> put(@EndpointParam URI location, Payload payload);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see HttpClient#post
|
|
||||||
*/
|
|
||||||
@POST
|
|
||||||
@ResponseParser(ParseETagHeader.class)
|
|
||||||
ListenableFuture<String> post(@EndpointParam URI location, Payload payload);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see HttpClient#exists
|
|
||||||
*/
|
|
||||||
@HEAD
|
|
||||||
@Fallback(FalseOnNotFoundOr404.class)
|
|
||||||
ListenableFuture<Boolean> exists(@EndpointParam URI location);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see HttpClient#get
|
|
||||||
*/
|
|
||||||
@GET
|
|
||||||
@Fallback(NullOnNotFoundOr404.class)
|
|
||||||
ListenableFuture<InputStream> get(@EndpointParam URI location);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see HttpClient#invoke
|
|
||||||
*/
|
|
||||||
ListenableFuture<HttpResponse> invoke(HttpRequest request);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see HttpClient#delete
|
|
||||||
*/
|
|
||||||
@DELETE
|
|
||||||
@Fallback(FalseOnNotFoundOr404.class)
|
|
||||||
ListenableFuture<Boolean> delete(@EndpointParam URI location);
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,55 +0,0 @@
|
||||||
/*
|
|
||||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
||||||
* contributor license agreements. See the NOTICE file distributed with
|
|
||||||
* this work for additional information regarding copyright ownership.
|
|
||||||
* The ASF licenses this file to You 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;
|
|
||||||
|
|
||||||
import org.jclouds.apis.ApiMetadata;
|
|
||||||
|
|
||||||
import com.google.common.annotations.Beta;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @since 1.5
|
|
||||||
*
|
|
||||||
* @deprecated please use {@link HttpApiMetadata} as
|
|
||||||
* async interface will be removed in jclouds 1.7.
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
@Beta
|
|
||||||
public interface RestApiMetadata extends ApiMetadata {
|
|
||||||
|
|
||||||
public interface Builder<T extends Builder<T>> extends ApiMetadata.Builder<T> {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see ApiMetadata#getApi()
|
|
||||||
* @see ApiMetadata#getAsyncApi()
|
|
||||||
*/
|
|
||||||
T javaApi(Class<?> api, Class<?> asyncApi);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @return the type of the api which blocks on all requests
|
|
||||||
*/
|
|
||||||
Class<?> getApi();
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @return the type of the api, which is the same as {@link #getApi}, except
|
|
||||||
* all methods return {@link ListenableFuture}
|
|
||||||
*/
|
|
||||||
Class<?> getAsyncApi();
|
|
||||||
}
|
|
|
@ -1,56 +0,0 @@
|
||||||
/*
|
|
||||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
||||||
* contributor license agreements. See the NOTICE file distributed with
|
|
||||||
* this work for additional information regarding copyright ownership.
|
|
||||||
* The ASF licenses this file to You 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.config;
|
|
||||||
|
|
||||||
import java.lang.reflect.Proxy;
|
|
||||||
|
|
||||||
import javax.inject.Inject;
|
|
||||||
import javax.inject.Singleton;
|
|
||||||
|
|
||||||
import org.jclouds.reflect.Invocation;
|
|
||||||
import org.jclouds.rest.internal.DelegatesToPotentiallySyncToAsyncInvocationFunction;
|
|
||||||
|
|
||||||
import com.google.common.base.Function;
|
|
||||||
import com.google.inject.Provider;
|
|
||||||
import com.google.inject.TypeLiteral;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @deprecated please use {@link DelegatesToInvocationFunction} as async
|
|
||||||
* interface will be removed in jclouds 1.7.
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
@Singleton
|
|
||||||
public class AnnotatedSyncToAsyncHttpApiProvider<A> implements Provider<A> {
|
|
||||||
private final Class<? super A> annotatedApiType;
|
|
||||||
private final DelegatesToPotentiallySyncToAsyncInvocationFunction<A, Function<Invocation, Object>> httpInvoker;
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
private AnnotatedSyncToAsyncHttpApiProvider(
|
|
||||||
DelegatesToPotentiallySyncToAsyncInvocationFunction<A, Function<Invocation, Object>> httpInvoker,
|
|
||||||
TypeLiteral<A> annotatedApiType) {
|
|
||||||
this.httpInvoker = httpInvoker;
|
|
||||||
this.annotatedApiType = annotatedApiType.getRawType();
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
@Override
|
|
||||||
public A get() {
|
|
||||||
return (A) Proxy.newProxyInstance(annotatedApiType.getClassLoader(), new Class<?>[] { annotatedApiType },
|
|
||||||
httpInvoker);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -48,100 +48,6 @@ public class BinderUtils {
|
||||||
binder.bind(annotated).toProvider(TypeLiteral.class.cast(TypeLiteral.get(token.getType())));
|
binder.bind(annotated).toProvider(TypeLiteral.class.cast(TypeLiteral.get(token.getType())));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* adds an explicit binding for {@code async} by parsing its annotations. Then, adds an explicit binding for an
|
|
||||||
* interface which synchronously blocks on similar calls to an {@code async} type.
|
|
||||||
*
|
|
||||||
* @param <S>
|
|
||||||
* sync interface that blocks
|
|
||||||
* @param <A>
|
|
||||||
* async type where all methods have same args as {@code sync}, but returns {@link ListenableFuture}
|
|
||||||
* @param binder
|
|
||||||
* guice binder
|
|
||||||
* @param sync
|
|
||||||
* type interface that blocks
|
|
||||||
* @param async
|
|
||||||
* type type that returns {@link ListenableFuture}
|
|
||||||
*
|
|
||||||
* @deprecated will be removed in jclouds 1.7, as async interfaces are no
|
|
||||||
* longer supported.
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
public static <S, A> void bindSyncToAsyncHttpApi(Binder binder, Class<S> sync, Class<A> async) {
|
|
||||||
bindClass(binder, sync);
|
|
||||||
bindClass(binder, async);
|
|
||||||
bindAnnotatedSyncToAsyncHttpApiProvider(binder, async);
|
|
||||||
bindHttpApiProvider(binder, sync, async);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated will be removed in jclouds 1.7, as async interfaces are no
|
|
||||||
* longer supported.
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
@SuppressWarnings({ "unchecked", "serial" })
|
|
||||||
private static <T> void bindAnnotatedSyncToAsyncHttpApiProvider(Binder binder, Class<T> annotated) {
|
|
||||||
TypeToken<AnnotatedSyncToAsyncHttpApiProvider<T>> token = new TypeToken<AnnotatedSyncToAsyncHttpApiProvider<T>>() {
|
|
||||||
}.where(new TypeParameter<T>() {
|
|
||||||
}, annotated);
|
|
||||||
binder.bind(annotated).toProvider(TypeLiteral.class.cast(TypeLiteral.get(token.getType())));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @deprecated will be removed in jclouds 1.7, as async interfaces are no
|
|
||||||
* longer supported.
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
@SuppressWarnings({ "unchecked", "serial" })
|
|
||||||
private static <S, A> void bindHttpApiProvider(Binder binder, Class<S> sync, Class<A> async) {
|
|
||||||
TypeToken<SyncToAsyncHttpApiProvider<S, A>> token = new TypeToken<SyncToAsyncHttpApiProvider<S, A>>() {
|
|
||||||
}.where(new TypeParameter<S>() {
|
|
||||||
}, sync).where(new TypeParameter<A>() {
|
|
||||||
}, async);
|
|
||||||
binder.bind(sync).toProvider(TypeLiteral.class.cast(TypeLiteral.get(token.getType())));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* adds an explicit binding for an interface which synchronously blocks on
|
|
||||||
* similar calls to an {@code async} type.
|
|
||||||
*
|
|
||||||
* @param <S>
|
|
||||||
* sync interface that blocks
|
|
||||||
* @param <A>
|
|
||||||
* async type where all methods have same args as {@code sync}, but
|
|
||||||
* returns {@link ListenableFuture}
|
|
||||||
* @param binder
|
|
||||||
* guice binder
|
|
||||||
* @param sync
|
|
||||||
* type interface that blocks
|
|
||||||
* @param async
|
|
||||||
* type type that returns {@link ListenableFuture}
|
|
||||||
*
|
|
||||||
* @deprecated will be removed in jclouds 1.7, as async interfaces are no
|
|
||||||
* longer supported.
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
public static <S, A> void bindSyncToAsyncApi(Binder binder, Class<S> sync, Class<A> async) {
|
|
||||||
bindClass(binder, sync);
|
|
||||||
bindClass(binder, async);
|
|
||||||
bindCallGetOnFutures(binder, sync, async);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated will be removed in jclouds 1.7, as async interfaces are no
|
|
||||||
* longer supported.
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
@SuppressWarnings({ "unchecked", "serial" })
|
|
||||||
private static <S, A> void bindCallGetOnFutures(Binder binder, Class<S> sync, Class<A> async) {
|
|
||||||
TypeToken<CallGetOnFuturesProvider<S, A>> token = new TypeToken<CallGetOnFuturesProvider<S, A>>() {
|
|
||||||
}.where(new TypeParameter<S>() {
|
|
||||||
}, sync).where(new TypeParameter<A>() {
|
|
||||||
}, async);
|
|
||||||
binder.bind(sync).toProvider(TypeLiteral.class.cast(TypeLiteral.get(token.getType())));
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings({ "unchecked", "serial" })
|
@SuppressWarnings({ "unchecked", "serial" })
|
||||||
private static <K> void bindClass(Binder binder, Class<K> sync) {
|
private static <K> void bindClass(Binder binder, Class<K> sync) {
|
||||||
binder.bind(TypeLiteral.class.cast(TypeLiteral.get(new TypeToken<Class<K>>() {
|
binder.bind(TypeLiteral.class.cast(TypeLiteral.get(new TypeToken<Class<K>>() {
|
||||||
|
|
|
@ -1,57 +0,0 @@
|
||||||
/*
|
|
||||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
||||||
* contributor license agreements. See the NOTICE file distributed with
|
|
||||||
* this work for additional information regarding copyright ownership.
|
|
||||||
* The ASF licenses this file to You 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.config;
|
|
||||||
|
|
||||||
|
|
||||||
import java.lang.reflect.Proxy;
|
|
||||||
|
|
||||||
import javax.inject.Inject;
|
|
||||||
import javax.inject.Singleton;
|
|
||||||
|
|
||||||
import org.jclouds.rest.internal.DelegatesToPotentiallySyncToAsyncInvocationFunction;
|
|
||||||
import org.jclouds.rest.internal.InvokeAndCallGetOnFutures;
|
|
||||||
|
|
||||||
import com.google.common.cache.Cache;
|
|
||||||
import com.google.common.reflect.Invokable;
|
|
||||||
import com.google.inject.Provider;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated will be removed in jclouds 1.7, as async interfaces are no longer supported.
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
@Singleton
|
|
||||||
public class CallGetOnFuturesProvider<S, A> implements Provider<S> {
|
|
||||||
|
|
||||||
private final Class<? super S> apiType;
|
|
||||||
private final DelegatesToPotentiallySyncToAsyncInvocationFunction<S, InvokeAndCallGetOnFutures<A>> syncInvoker;
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
private CallGetOnFuturesProvider(Cache<Invokable<?, ?>, Invokable<?, ?>> invokables,
|
|
||||||
DelegatesToPotentiallySyncToAsyncInvocationFunction<S, InvokeAndCallGetOnFutures<A>> syncInvoker, Class<S> apiType,
|
|
||||||
Class<A> asyncApiType) {
|
|
||||||
this.syncInvoker = syncInvoker;
|
|
||||||
this.apiType = apiType;
|
|
||||||
SyncToAsyncHttpInvocationModule.putInvokables(apiType, asyncApiType, invokables);
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
@Override
|
|
||||||
@Singleton
|
|
||||||
public S get() {
|
|
||||||
return (S) Proxy.newProxyInstance(apiType.getClassLoader(), new Class<?>[] { apiType }, syncInvoker);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,119 +0,0 @@
|
||||||
/*
|
|
||||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
||||||
* contributor license agreements. See the NOTICE file distributed with
|
|
||||||
* this work for additional information regarding copyright ownership.
|
|
||||||
* The ASF licenses this file to You 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.config;
|
|
||||||
|
|
||||||
import static org.jclouds.reflect.Types2.checkBound;
|
|
||||||
import static org.jclouds.rest.config.BinderUtils.bindSyncToAsyncHttpApi;
|
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import org.jclouds.rest.ConfiguresRestClient;
|
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableMap;
|
|
||||||
import com.google.common.reflect.TypeToken;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @deprecated will be removed in jclouds 1.7; use {@link HttpApiModule}
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
@ConfiguresRestClient
|
|
||||||
public class RestClientModule<S, A> extends RestModule {
|
|
||||||
protected final TypeToken<S> syncClientType;
|
|
||||||
protected final TypeToken<A> asyncClientType;
|
|
||||||
|
|
||||||
private final SyncToAsyncHttpInvocationModule invocationModule;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Note that this ctor requires that you instantiate w/resolved generic params. For example, via
|
|
||||||
* a subclass of a bound type, or natural instantiation w/resolved type params.
|
|
||||||
*/
|
|
||||||
protected RestClientModule(Map<Class<?>, Class<?>> sync2Async) {
|
|
||||||
this.invocationModule = new SyncToAsyncHttpInvocationModule(sync2Async);
|
|
||||||
this.syncClientType = checkBound(new TypeToken<S>(getClass()) {
|
|
||||||
private static final long serialVersionUID = 1L;
|
|
||||||
});
|
|
||||||
this.asyncClientType = checkBound(new TypeToken<A>(getClass()) {
|
|
||||||
private static final long serialVersionUID = 1L;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see #RestClientModule(Map)
|
|
||||||
*/
|
|
||||||
protected RestClientModule() {
|
|
||||||
this(ImmutableMap.<Class<?>, Class<?>> of());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see #RestClientModule(TypeToken, TypeToken, Map)
|
|
||||||
*/
|
|
||||||
public RestClientModule(TypeToken<S> syncClientType, TypeToken<A> asyncClientType) {
|
|
||||||
this(syncClientType, asyncClientType, ImmutableMap.<Class<?>, Class<?>> of());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* only necessary when type params are not resolvable at runtime.
|
|
||||||
*/
|
|
||||||
public RestClientModule(TypeToken<S> syncClientType, TypeToken<A> asyncClientType, Map<Class<?>, Class<?>> sync2Async) {
|
|
||||||
this.invocationModule = new SyncToAsyncHttpInvocationModule(sync2Async);
|
|
||||||
this.syncClientType = checkBound(syncClientType);
|
|
||||||
this.asyncClientType = checkBound(asyncClientType);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void configure() {
|
|
||||||
super.configure();
|
|
||||||
install(invocationModule);
|
|
||||||
bindSyncToAsyncHttpApi(binder(), syncClientType.getRawType(), asyncClientType.getRawType());
|
|
||||||
bindErrorHandlers();
|
|
||||||
bindRetryHandlers();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* overrides this to change the default retry handlers for the http engine
|
|
||||||
*
|
|
||||||
* ex.
|
|
||||||
*
|
|
||||||
* <pre>
|
|
||||||
* bind(HttpRetryHandler.class).annotatedWith(Redirection.class).to(AWSRedirectionRetryHandler.class);
|
|
||||||
* bind(HttpRetryHandler.class).annotatedWith(ClientError.class).to(AWSClientErrorRetryHandler.class);
|
|
||||||
* </pre>
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
protected void bindRetryHandlers() {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* overrides this to change the default error handlers for the http engine
|
|
||||||
*
|
|
||||||
* 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);
|
|
||||||
* </pre>
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
protected void bindErrorHandlers() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,57 +0,0 @@
|
||||||
/*
|
|
||||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
||||||
* contributor license agreements. See the NOTICE file distributed with
|
|
||||||
* this work for additional information regarding copyright ownership.
|
|
||||||
* The ASF licenses this file to You 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.config;
|
|
||||||
|
|
||||||
|
|
||||||
import java.lang.reflect.Proxy;
|
|
||||||
|
|
||||||
import javax.inject.Inject;
|
|
||||||
import javax.inject.Singleton;
|
|
||||||
|
|
||||||
import org.jclouds.reflect.Invocation;
|
|
||||||
import org.jclouds.rest.internal.DelegatesToPotentiallySyncToAsyncInvocationFunction;
|
|
||||||
|
|
||||||
import com.google.common.base.Function;
|
|
||||||
import com.google.common.cache.Cache;
|
|
||||||
import com.google.common.reflect.Invokable;
|
|
||||||
import com.google.inject.Provider;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @deprecated will be removed in jclouds 1.7; use {@link AnnotatedHttpApiProvider}
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
@Singleton
|
|
||||||
public class SyncToAsyncHttpApiProvider<S, A> implements Provider<S> {
|
|
||||||
private final Class<? super S> apiType;
|
|
||||||
private final DelegatesToPotentiallySyncToAsyncInvocationFunction<S, Function<Invocation, Object>> httpInvoker;
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
private SyncToAsyncHttpApiProvider(Cache<Invokable<?, ?>, Invokable<?, ?>> invokables,
|
|
||||||
DelegatesToPotentiallySyncToAsyncInvocationFunction<S, Function<Invocation, Object>> httpInvoker, Class<S> apiType, Class<A> asyncApiType) {
|
|
||||||
this.httpInvoker = httpInvoker;
|
|
||||||
this.apiType = apiType;
|
|
||||||
SyncToAsyncHttpInvocationModule.putInvokables(apiType, asyncApiType, invokables);
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
@Override
|
|
||||||
@Singleton
|
|
||||||
public S get() {
|
|
||||||
return (S) Proxy.newProxyInstance(apiType.getClassLoader(), new Class<?>[] { apiType }, httpInvoker);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,145 +0,0 @@
|
||||||
/*
|
|
||||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
||||||
* contributor license agreements. See the NOTICE file distributed with
|
|
||||||
* this work for additional information regarding copyright ownership.
|
|
||||||
* The ASF licenses this file to You 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.config;
|
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkArgument;
|
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
|
||||||
import static com.google.common.collect.Iterables.toArray;
|
|
||||||
import static com.google.common.collect.Iterables.transform;
|
|
||||||
import static org.jclouds.reflect.Reflection2.method;
|
|
||||||
import static org.jclouds.reflect.Reflection2.methods;
|
|
||||||
|
|
||||||
import java.io.Closeable;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import javax.inject.Singleton;
|
|
||||||
|
|
||||||
import org.jclouds.reflect.Invocation;
|
|
||||||
import org.jclouds.rest.HttpAsyncClient;
|
|
||||||
import org.jclouds.rest.HttpClient;
|
|
||||||
import org.jclouds.rest.internal.InvokeSyncToAsyncHttpMethod;
|
|
||||||
|
|
||||||
import com.google.common.annotations.VisibleForTesting;
|
|
||||||
import com.google.common.base.Function;
|
|
||||||
import com.google.common.cache.Cache;
|
|
||||||
import com.google.common.cache.CacheBuilder;
|
|
||||||
import com.google.common.collect.ImmutableMap;
|
|
||||||
import com.google.common.reflect.Invokable;
|
|
||||||
import com.google.common.reflect.Parameter;
|
|
||||||
import com.google.inject.AbstractModule;
|
|
||||||
import com.google.inject.Provides;
|
|
||||||
import com.google.inject.TypeLiteral;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* supports sync-async mapping
|
|
||||||
*
|
|
||||||
* @deprecated will be removed in jclouds 1.7; use {@link HttpApiModule}
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
public class SyncToAsyncHttpInvocationModule extends AbstractModule {
|
|
||||||
protected final Map<Class<?>, Class<?>> sync2Async;
|
|
||||||
|
|
||||||
public SyncToAsyncHttpInvocationModule() {
|
|
||||||
this(ImmutableMap.<Class<?>, Class<?>> of());
|
|
||||||
}
|
|
||||||
|
|
||||||
public SyncToAsyncHttpInvocationModule(Map<Class<?>, Class<?>> sync2Async) {
|
|
||||||
this.sync2Async = sync2Async;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void configure() {
|
|
||||||
bind(new TypeLiteral<Map<Class<?>, Class<?>>>() {
|
|
||||||
}).toInstance(sync2Async);
|
|
||||||
bind(new TypeLiteral<Function<Invocation, Object>>() {
|
|
||||||
}).to(InvokeSyncToAsyncHttpMethod.class);
|
|
||||||
BinderUtils.bindSyncToAsyncHttpApi(binder(), HttpClient.class, HttpAsyncClient.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* seeds well-known invokables.
|
|
||||||
*/
|
|
||||||
@Provides
|
|
||||||
@Singleton
|
|
||||||
protected Cache<Invokable<?, ?>, Invokable<?, ?>> seedKnownSync2AsyncInvokables() {
|
|
||||||
return seedKnownSync2AsyncInvokables(sync2Async);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* function view of above
|
|
||||||
*
|
|
||||||
* @see InvokeAndCallGetOnFutures
|
|
||||||
* @see InvokeSyncToAsyncHttpMethod
|
|
||||||
*/
|
|
||||||
@Provides
|
|
||||||
@Singleton
|
|
||||||
protected Function<Invocation, Invocation> sync2async(final Cache<Invokable<?, ?>, Invokable<?, ?>> cache) {
|
|
||||||
return new Function<Invocation, Invocation>() {
|
|
||||||
public Invocation apply(Invocation in) {
|
|
||||||
return Invocation.create(
|
|
||||||
checkNotNull(cache.getIfPresent(in.getInvokable()), "invokable %s not in %s", in.getInvokable(),
|
|
||||||
cache), in.getArgs());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
@VisibleForTesting
|
|
||||||
static Cache<Invokable<?, ?>, Invokable<?, ?>> seedKnownSync2AsyncInvokables(Map<Class<?>, Class<?>> sync2Async) {
|
|
||||||
Cache<Invokable<?, ?>, Invokable<?, ?>> sync2AsyncBuilder = CacheBuilder.newBuilder().build();
|
|
||||||
putInvokables(HttpClient.class, HttpAsyncClient.class, sync2AsyncBuilder);
|
|
||||||
for (Map.Entry<Class<?>, Class<?>> entry : sync2Async.entrySet()) {
|
|
||||||
putInvokables(entry.getKey(), entry.getValue(), sync2AsyncBuilder);
|
|
||||||
}
|
|
||||||
return sync2AsyncBuilder;
|
|
||||||
}
|
|
||||||
|
|
||||||
// accessible for ClientProvider
|
|
||||||
public static void putInvokables(Class<?> sync, Class<?> async, Cache<Invokable<?, ?>, Invokable<?, ?>> cache) {
|
|
||||||
for (Invokable<?, ?> invoked : methods(sync)) {
|
|
||||||
Invokable<?, ?> delegatedMethod = method(async, invoked.getName(), getParameterTypes(invoked));
|
|
||||||
checkArgument(delegatedMethod.getExceptionTypes().equals(invoked.getExceptionTypes())
|
|
||||||
|| isCloseable(delegatedMethod), "invoked %s has different typed exceptions than target %s", invoked,
|
|
||||||
delegatedMethod);
|
|
||||||
cache.put(invoked, delegatedMethod);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* In JDK7 Closeable.close is declared in AutoCloseable, which throws
|
|
||||||
* Exception vs IOException, so we have to be more lenient about exception
|
|
||||||
* type declarations.
|
|
||||||
*
|
|
||||||
* <h4>note</h4>
|
|
||||||
*
|
|
||||||
* This will be refactored out when we delete Async code in jclouds 1.7.
|
|
||||||
*/
|
|
||||||
private static boolean isCloseable(Invokable<?, ?> delegatedMethod) {
|
|
||||||
return "close".equals(delegatedMethod.getName())
|
|
||||||
&& Closeable.class.isAssignableFrom(delegatedMethod.getDeclaringClass());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* for portability with {@link Class#getMethod(String, Class...)}
|
|
||||||
*/
|
|
||||||
private static Class<?>[] getParameterTypes(Invokable<?, ?> in) {
|
|
||||||
return toArray(transform(checkNotNull(in, "invokable").getParameters(), new Function<Parameter, Class<?>>() {
|
|
||||||
public Class<?> apply(Parameter input) {
|
|
||||||
return input.getType().getRawType();
|
|
||||||
}
|
|
||||||
}), Class.class);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,120 +0,0 @@
|
||||||
/*
|
|
||||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
||||||
* contributor license agreements. See the NOTICE file distributed with
|
|
||||||
* this work for additional information regarding copyright ownership.
|
|
||||||
* The ASF licenses this file to You 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.internal;
|
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
|
||||||
import static org.jclouds.reflect.Reflection2.typeToken;
|
|
||||||
|
|
||||||
import java.util.Properties;
|
|
||||||
|
|
||||||
import org.jclouds.apis.ApiMetadata;
|
|
||||||
import org.jclouds.apis.internal.BaseApiMetadata;
|
|
||||||
import org.jclouds.rest.RestApiMetadata;
|
|
||||||
|
|
||||||
import com.google.common.annotations.Beta;
|
|
||||||
import com.google.common.base.Objects.ToStringHelper;
|
|
||||||
import com.google.common.reflect.TypeParameter;
|
|
||||||
import com.google.common.reflect.TypeToken;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Useful in creating rest apis.
|
|
||||||
*
|
|
||||||
* @deprecated please use {@link BaseHttpApiMetadata} as
|
|
||||||
* async interface will be removed in jclouds 1.7.
|
|
||||||
*/
|
|
||||||
@Beta
|
|
||||||
@Deprecated
|
|
||||||
public abstract class BaseRestApiMetadata extends BaseApiMetadata implements RestApiMetadata {
|
|
||||||
|
|
||||||
protected final Class<?> api;
|
|
||||||
protected final Class<?> asyncApi;
|
|
||||||
|
|
||||||
protected BaseRestApiMetadata(Builder<?> builder) {
|
|
||||||
super(builder);
|
|
||||||
this.api = checkNotNull(builder.api, "api");
|
|
||||||
this.asyncApi = checkNotNull(builder.asyncApi, "asyncApi");
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Properties defaultProperties() {
|
|
||||||
Properties props = BaseApiMetadata.defaultProperties();
|
|
||||||
return props;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <S, A> TypeToken<org.jclouds.rest.RestContext<S, A>> contextToken(TypeToken<S> apiToken, TypeToken<A> asyncApiToken) {
|
|
||||||
return new TypeToken<org.jclouds.rest.RestContext<S, A>>() {
|
|
||||||
private static final long serialVersionUID = 1L;
|
|
||||||
}.where(new TypeParameter<S>() {
|
|
||||||
}, apiToken).where(new TypeParameter<A>() {
|
|
||||||
}, asyncApiToken);
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract static class Builder<T extends Builder<T>> extends BaseApiMetadata.Builder<T> implements RestApiMetadata.Builder<T> {
|
|
||||||
protected Class<?> api;
|
|
||||||
protected Class<?> asyncApi;
|
|
||||||
|
|
||||||
protected Builder(Class<?> api, Class<?> asyncApi) {
|
|
||||||
checkNotNull(api, "api");
|
|
||||||
checkNotNull(asyncApi, "asyncApi");
|
|
||||||
javaApi(api, asyncApi)
|
|
||||||
.name(String.format("%s->%s", api.getSimpleName(), asyncApi.getSimpleName()))
|
|
||||||
.context(contextToken(typeToken(api), typeToken(asyncApi)))
|
|
||||||
.defaultProperties(BaseRestApiMetadata.defaultProperties());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public T javaApi(Class<?> api, Class<?> asyncApi) {
|
|
||||||
this.api = checkNotNull(api, "api");
|
|
||||||
this.asyncApi = checkNotNull(asyncApi, "asyncApi");
|
|
||||||
return self();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public T fromApiMetadata(ApiMetadata in) {
|
|
||||||
if (in instanceof RestApiMetadata) {
|
|
||||||
RestApiMetadata rest = RestApiMetadata.class.cast(in);
|
|
||||||
javaApi(rest.getApi(), rest.getAsyncApi());
|
|
||||||
}
|
|
||||||
super.fromApiMetadata(in);
|
|
||||||
return self();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public Class<?> getApi() {
|
|
||||||
return api;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public Class<?> getAsyncApi() {
|
|
||||||
return asyncApi;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected ToStringHelper string() {
|
|
||||||
return super.string().add("api", getApi()).add("asyncApi", getAsyncApi());
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,72 +0,0 @@
|
||||||
/*
|
|
||||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
||||||
* contributor license agreements. See the NOTICE file distributed with
|
|
||||||
* this work for additional information regarding copyright ownership.
|
|
||||||
* The ASF licenses this file to You 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.internal;
|
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import javax.inject.Inject;
|
|
||||||
|
|
||||||
import org.jclouds.reflect.Invocation;
|
|
||||||
import org.jclouds.reflect.InvocationSuccess;
|
|
||||||
import org.jclouds.rest.config.SetCaller;
|
|
||||||
|
|
||||||
import com.google.common.annotations.Beta;
|
|
||||||
import com.google.common.base.Function;
|
|
||||||
import com.google.common.base.Optional;
|
|
||||||
import com.google.inject.Injector;
|
|
||||||
import com.google.inject.Key;
|
|
||||||
import com.google.inject.util.Types;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param <S>
|
|
||||||
* The enclosing type of the interface that a dynamic proxy like this
|
|
||||||
* implements
|
|
||||||
* @param <F>
|
|
||||||
* The function that implements this dynamic proxy
|
|
||||||
*
|
|
||||||
* @deprecated please use {@link DelegatesToInvocationFunction} as
|
|
||||||
* async interface will be removed in jclouds 1.7.
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
@Beta
|
|
||||||
public final class DelegatesToPotentiallySyncToAsyncInvocationFunction<S, F extends Function<Invocation, Object>> extends
|
|
||||||
DelegatesToInvocationFunction<S, F> {
|
|
||||||
private final Map<Class<?>, Class<?>> syncToAsync;
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
DelegatesToPotentiallySyncToAsyncInvocationFunction(Injector injector, SetCaller setCaller, Class<S> ownerType,
|
|
||||||
Function<InvocationSuccess, Optional<Object>> optionalConverter, F methodInvoker,
|
|
||||||
Map<Class<?>, Class<?>> syncToAsync) {
|
|
||||||
super(injector, setCaller, ownerType, optionalConverter, methodInvoker);
|
|
||||||
this.syncToAsync = checkNotNull(syncToAsync, "syncToAsync");
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Key<?> methodInvokerFor(Class<?> returnType) {
|
|
||||||
if (methodInvoker.getClass().getTypeParameters().length == 2) {
|
|
||||||
if (syncToAsync.containsValue(returnType))
|
|
||||||
return Key.get(Types.newParameterizedType(methodInvoker.getClass(), returnType, returnType));
|
|
||||||
return Key.get(Types.newParameterizedType(
|
|
||||||
methodInvoker.getClass(),
|
|
||||||
returnType,
|
|
||||||
checkNotNull(syncToAsync.get(returnType), "need async type of %s for %s", returnType,
|
|
||||||
methodInvoker.getClass())));
|
|
||||||
}
|
|
||||||
return super.methodInvokerFor(returnType);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,272 +0,0 @@
|
||||||
/*
|
|
||||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
||||||
* contributor license agreements. See the NOTICE file distributed with
|
|
||||||
* this work for additional information regarding copyright ownership.
|
|
||||||
* The ASF licenses this file to You 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.internal;
|
|
||||||
|
|
||||||
import static com.google.common.base.Objects.equal;
|
|
||||||
import static com.google.common.base.Objects.toStringHelper;
|
|
||||||
import static com.google.common.base.Preconditions.checkState;
|
|
||||||
import static com.google.common.base.Throwables.propagate;
|
|
||||||
import static com.google.common.util.concurrent.Futures.transform;
|
|
||||||
import static com.google.common.util.concurrent.Futures.withFallback;
|
|
||||||
import static java.util.concurrent.TimeUnit.NANOSECONDS;
|
|
||||||
import static org.jclouds.Constants.PROPERTY_USER_THREADS;
|
|
||||||
|
|
||||||
import java.util.concurrent.Callable;
|
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
|
||||||
import javax.inject.Inject;
|
|
||||||
import javax.inject.Named;
|
|
||||||
|
|
||||||
import org.jclouds.http.HttpCommand;
|
|
||||||
import org.jclouds.http.HttpCommandExecutorService;
|
|
||||||
import org.jclouds.http.HttpRequest;
|
|
||||||
import org.jclouds.http.HttpResponse;
|
|
||||||
import org.jclouds.logging.Logger;
|
|
||||||
import org.jclouds.reflect.Invocation;
|
|
||||||
import org.jclouds.rest.InvocationContext;
|
|
||||||
import org.jclouds.rest.config.InvocationConfig;
|
|
||||||
|
|
||||||
import com.google.common.annotations.VisibleForTesting;
|
|
||||||
import com.google.common.base.Function;
|
|
||||||
import com.google.common.base.Objects;
|
|
||||||
import com.google.common.base.Optional;
|
|
||||||
import com.google.common.reflect.Invokable;
|
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
|
||||||
import com.google.common.util.concurrent.ListeningExecutorService;
|
|
||||||
import com.google.common.util.concurrent.TimeLimiter;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated will be replaced in jclouds 1.7 with {@link InvokeHttpMethod}, as async interfaces are no longer supported.
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
public class InvokeSyncToAsyncHttpMethod implements Function<Invocation, Object> {
|
|
||||||
|
|
||||||
@Resource
|
|
||||||
private Logger logger = Logger.NULL;
|
|
||||||
|
|
||||||
private final Function<Invocation, Invocation> sync2async;
|
|
||||||
private final Function<Invocation, HttpRequest> annotationProcessor;
|
|
||||||
private final HttpCommandExecutorService http;
|
|
||||||
private final ListeningExecutorService userExecutor;
|
|
||||||
private final TimeLimiter timeLimiter;
|
|
||||||
private final Function<HttpRequest, Function<HttpResponse, ?>> transformerForRequest;
|
|
||||||
private final InvocationConfig config;
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
@VisibleForTesting
|
|
||||||
InvokeSyncToAsyncHttpMethod(Function<Invocation, Invocation> sync2async, Function<Invocation, HttpRequest> annotationProcessor,
|
|
||||||
HttpCommandExecutorService http, Function<HttpRequest, Function<HttpResponse, ?>> transformerForRequest,
|
|
||||||
TimeLimiter timeLimiter, InvocationConfig config,
|
|
||||||
@Named(PROPERTY_USER_THREADS) ListeningExecutorService userExecutor) {
|
|
||||||
this.sync2async = sync2async;
|
|
||||||
this.annotationProcessor = annotationProcessor;
|
|
||||||
this.http = http;
|
|
||||||
this.userExecutor = userExecutor;
|
|
||||||
this.timeLimiter = timeLimiter;
|
|
||||||
this.transformerForRequest = transformerForRequest;
|
|
||||||
this.config = config;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object apply(Invocation in) {
|
|
||||||
if (isFuture(in.getInvokable())) {
|
|
||||||
return submit(in);
|
|
||||||
}
|
|
||||||
Invocation async = toAsync(in);
|
|
||||||
Optional<Long> timeoutNanos = config.getTimeoutNanos(async);
|
|
||||||
if (timeoutNanos.isPresent()) {
|
|
||||||
return invokeWithTimeout(async, timeoutNanos.get());
|
|
||||||
}
|
|
||||||
return invoke(async);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* submits the {@linkplain HttpCommand} associated with {@code invocation},
|
|
||||||
* {@link #getTransformer(String, HttpCommand) parses its response}, and
|
|
||||||
* applies a {@link #getFallback(String, Invocation, HttpCommand) fallback}
|
|
||||||
* if a {@code Throwable} is encountered. Parsing and Fallback occur on the
|
|
||||||
* {@code userExecutor} thread.
|
|
||||||
*/
|
|
||||||
public ListenableFuture<?> submit(Invocation invocation) {
|
|
||||||
String commandName = config.getCommandName(invocation);
|
|
||||||
HttpCommand command = toCommand(commandName, invocation);
|
|
||||||
Function<HttpResponse, ?> transformer = getTransformer(commandName, command);
|
|
||||||
org.jclouds.Fallback<?> fallback = getFallback(commandName, invocation, command);
|
|
||||||
|
|
||||||
logger.debug(">> submitting %s", commandName);
|
|
||||||
return withFallback(transform(http.submit(command), transformer, userExecutor), fallback);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* invokes the {@linkplain HttpCommand} associated with {@code invocation},
|
|
||||||
* {@link #getTransformer(String, HttpCommand) parses its response}, and
|
|
||||||
* applies a {@link #getFallback(String, Invocation, HttpCommand) fallback}
|
|
||||||
* if a {@code Throwable} is encountered.
|
|
||||||
*/
|
|
||||||
public Object invoke(Invocation invocation) {
|
|
||||||
String commandName = config.getCommandName(invocation);
|
|
||||||
HttpCommand command = toCommand(commandName, invocation);
|
|
||||||
Function<HttpResponse, ?> transformer = getTransformer(commandName, command);
|
|
||||||
org.jclouds.Fallback<?> fallback = getFallback(commandName, invocation, command);
|
|
||||||
|
|
||||||
logger.debug(">> invoking %s", commandName);
|
|
||||||
try {
|
|
||||||
return transformer.apply(http.invoke(command));
|
|
||||||
} catch (Throwable t) {
|
|
||||||
try {
|
|
||||||
return fallback.createOrPropagate(t);
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw propagate(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* calls {@link #invoke(Invocation)}, timing out after the specified time
|
|
||||||
* limit. If the target method call finished before the limit is reached, the
|
|
||||||
* return value or exception is propagated to the caller exactly as-is. If,
|
|
||||||
* on the other hand, the time limit is reached, we attempt to abort the call
|
|
||||||
* to the target, and throw an {@link UncheckedTimeoutException} to the
|
|
||||||
* caller.
|
|
||||||
*
|
|
||||||
* @param invocation
|
|
||||||
* the Invocation to invoke via {@link #invoke(Invocation)}
|
|
||||||
* @param limitNanos
|
|
||||||
* with timeoutUnit, the maximum length of time to wait in
|
|
||||||
* nanoseconds
|
|
||||||
* @throws InterruptedException
|
|
||||||
* if our thread is interrupted during execution
|
|
||||||
* @throws UncheckedTimeoutException
|
|
||||||
* if the time limit is reached
|
|
||||||
* @see TimeLimiter#callWithTimeout(Callable, long, TimeUnit, boolean)
|
|
||||||
*/
|
|
||||||
public Object invokeWithTimeout(final Invocation invocation, final long limitNanos) {
|
|
||||||
String commandName = config.getCommandName(invocation);
|
|
||||||
HttpCommand command = toCommand(commandName, invocation);
|
|
||||||
org.jclouds.Fallback<?> fallback = getFallback(commandName, invocation, command);
|
|
||||||
|
|
||||||
logger.debug(">> blocking on %s for %s", invocation, limitNanos);
|
|
||||||
try {
|
|
||||||
return timeLimiter
|
|
||||||
.callWithTimeout(new InvokeAndTransform(commandName, command), limitNanos, NANOSECONDS, true);
|
|
||||||
} catch (Throwable t) {
|
|
||||||
try {
|
|
||||||
return fallback.createOrPropagate(t);
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw propagate(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private org.jclouds.Fallback<?> getFallback(String commandName, Invocation invocation, HttpCommand command) {
|
|
||||||
HttpRequest request = command.getCurrentRequest();
|
|
||||||
org.jclouds.Fallback<?> fallback = config.getFallback(invocation);
|
|
||||||
if (fallback instanceof InvocationContext)
|
|
||||||
InvocationContext.class.cast(fallback).setContext(request);
|
|
||||||
logger.trace("<< exceptions from %s are parsed by %s", commandName, fallback.getClass().getSimpleName());
|
|
||||||
return fallback;
|
|
||||||
}
|
|
||||||
|
|
||||||
@VisibleForTesting
|
|
||||||
final class InvokeAndTransform implements Callable<Object> {
|
|
||||||
private final String commandName;
|
|
||||||
private final HttpCommand command;
|
|
||||||
private final Function<HttpResponse, ?> transformer;
|
|
||||||
|
|
||||||
InvokeAndTransform(String commandName, HttpCommand command) {
|
|
||||||
this.commandName = commandName;
|
|
||||||
this.command = command;
|
|
||||||
this.transformer = getTransformer(commandName, command);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object call() throws Exception {
|
|
||||||
return transformer.apply(http.invoke(command));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return Objects.hashCode(commandName, command, transformer);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object obj) {
|
|
||||||
if (this == obj)
|
|
||||||
return true;
|
|
||||||
if (obj == null || getClass() != obj.getClass())
|
|
||||||
return false;
|
|
||||||
InvokeAndTransform that = InvokeAndTransform.class.cast(obj);
|
|
||||||
return equal(this.commandName, that.commandName) && equal(this.command, that.command)
|
|
||||||
&& equal(this.transformer, that.transformer);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return toStringHelper(this).add("commandName", commandName).add("command", command)
|
|
||||||
.add("transformer", transformer).toString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* looks up the corresponding {@code Invocation} that returns a
|
|
||||||
* {@code Future}. Only Invokables that return {@code Futures} are annotated
|
|
||||||
* in a way that can be parsed into an {@linkplain HttpRequest}.
|
|
||||||
*/
|
|
||||||
private Invocation toAsync(Invocation in) {
|
|
||||||
Invocation async = sync2async.apply(in);
|
|
||||||
checkState(isFuture(async.getInvokable()), "not a future: %s", async);
|
|
||||||
return async;
|
|
||||||
}
|
|
||||||
|
|
||||||
private HttpCommand toCommand(String commandName, Invocation invocation) {
|
|
||||||
logger.trace(">> converting %s", commandName);
|
|
||||||
HttpRequest request = annotationProcessor.apply(invocation);
|
|
||||||
logger.trace("<< converted %s to %s", commandName, request.getRequestLine());
|
|
||||||
return new HttpCommand(request);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Function<HttpResponse, ?> getTransformer(String commandName, HttpCommand command) {
|
|
||||||
HttpRequest request = command.getCurrentRequest();
|
|
||||||
Function<HttpResponse, ?> transformer = transformerForRequest.apply(request);
|
|
||||||
logger.trace("<< response from %s is parsed by %s", commandName, transformer.getClass().getSimpleName());
|
|
||||||
return transformer;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isFuture(Invokable<?, ?> in) {
|
|
||||||
return in.getReturnType().getRawType().equals(ListenableFuture.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object o) {
|
|
||||||
if (this == o)
|
|
||||||
return true;
|
|
||||||
if (o == null || getClass() != o.getClass())
|
|
||||||
return false;
|
|
||||||
InvokeSyncToAsyncHttpMethod that = InvokeSyncToAsyncHttpMethod.class.cast(o);
|
|
||||||
return equal(this.annotationProcessor, that.annotationProcessor);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return Objects.hashCode(annotationProcessor);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return Objects.toStringHelper("").omitNullValues().add("annotationParser", annotationProcessor).toString();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -17,6 +17,7 @@
|
||||||
package org.jclouds;
|
package org.jclouds;
|
||||||
|
|
||||||
import static com.google.common.base.Suppliers.ofInstance;
|
import static com.google.common.base.Suppliers.ofInstance;
|
||||||
|
import static org.jclouds.providers.AnonymousProviderMetadata.forApiOnEndpoint;
|
||||||
import static org.testng.Assert.assertEquals;
|
import static org.testng.Assert.assertEquals;
|
||||||
|
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
|
@ -28,7 +29,6 @@ import java.util.Set;
|
||||||
import org.jclouds.concurrent.config.ExecutorServiceModule;
|
import org.jclouds.concurrent.config.ExecutorServiceModule;
|
||||||
import org.jclouds.domain.Credentials;
|
import org.jclouds.domain.Credentials;
|
||||||
import org.jclouds.events.config.EventBusModule;
|
import org.jclouds.events.config.EventBusModule;
|
||||||
import org.jclouds.http.IntegrationTestAsyncClient;
|
|
||||||
import org.jclouds.http.IntegrationTestClient;
|
import org.jclouds.http.IntegrationTestClient;
|
||||||
import org.jclouds.http.config.ConfiguresHttpCommandExecutorService;
|
import org.jclouds.http.config.ConfiguresHttpCommandExecutorService;
|
||||||
import org.jclouds.http.config.JavaUrlHttpCommandExecutorServiceModule;
|
import org.jclouds.http.config.JavaUrlHttpCommandExecutorServiceModule;
|
||||||
|
@ -36,9 +36,7 @@ import org.jclouds.location.Provider;
|
||||||
import org.jclouds.logging.config.LoggingModule;
|
import org.jclouds.logging.config.LoggingModule;
|
||||||
import org.jclouds.logging.config.NullLoggingModule;
|
import org.jclouds.logging.config.NullLoggingModule;
|
||||||
import org.jclouds.logging.jdk.config.JDKLoggingModule;
|
import org.jclouds.logging.jdk.config.JDKLoggingModule;
|
||||||
import org.jclouds.providers.AnonymousProviderMetadata;
|
|
||||||
import org.jclouds.providers.ProviderMetadata;
|
import org.jclouds.providers.ProviderMetadata;
|
||||||
import org.jclouds.rest.ConfiguresRestClient;
|
|
||||||
import org.jclouds.rest.annotations.ApiVersion;
|
import org.jclouds.rest.annotations.ApiVersion;
|
||||||
import org.jclouds.rest.config.CredentialStoreModule;
|
import org.jclouds.rest.config.CredentialStoreModule;
|
||||||
import org.testng.annotations.Test;
|
import org.testng.annotations.Test;
|
||||||
|
@ -47,7 +45,6 @@ import com.google.common.base.Supplier;
|
||||||
import com.google.common.collect.ImmutableSet;
|
import com.google.common.collect.ImmutableSet;
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
import com.google.inject.AbstractModule;
|
import com.google.inject.AbstractModule;
|
||||||
import com.google.inject.Binder;
|
|
||||||
import com.google.inject.Key;
|
import com.google.inject.Key;
|
||||||
import com.google.inject.Module;
|
import com.google.inject.Module;
|
||||||
import com.google.inject.TypeLiteral;
|
import com.google.inject.TypeLiteral;
|
||||||
|
@ -65,8 +62,7 @@ public class ContextBuilderTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
private ContextBuilder testContextBuilder() {
|
private ContextBuilder testContextBuilder() {
|
||||||
return ContextBuilder.newBuilder(AnonymousProviderMetadata.forClientMappedToAsyncClientOnEndpoint(
|
return ContextBuilder.newBuilder(forApiOnEndpoint(IntegrationTestClient.class, "http://localhost"));
|
||||||
IntegrationTestClient.class, IntegrationTestAsyncClient.class, "http://localhost"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -198,14 +194,6 @@ public class ContextBuilderTest {
|
||||||
assertEquals(modules.remove(0), httpModule);
|
assertEquals(modules.remove(0), httpModule);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ConfiguresRestClient
|
|
||||||
static class ConfiguresClientModule implements Module {
|
|
||||||
|
|
||||||
public void configure(Binder arg0) {
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testAddBothWhenDefault() {
|
public void testAddBothWhenDefault() {
|
||||||
List<Module> modules = Lists.newArrayList();
|
List<Module> modules = Lists.newArrayList();
|
||||||
|
|
|
@ -18,14 +18,13 @@ package org.jclouds.apis;
|
||||||
|
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
|
|
||||||
import org.jclouds.http.IntegrationTestAsyncClient;
|
|
||||||
import org.jclouds.http.IntegrationTestClient;
|
import org.jclouds.http.IntegrationTestClient;
|
||||||
import org.jclouds.rest.internal.BaseRestApiMetadata;
|
import org.jclouds.rest.internal.BaseHttpApiMetadata;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implementation of @ link org.jclouds.types.ApiMetadata} for testing.
|
* Implementation of @ link org.jclouds.types.ApiMetadata} for testing.
|
||||||
*/
|
*/
|
||||||
public class JcloudsTestBlobStoreApiMetadata extends BaseRestApiMetadata {
|
public class JcloudsTestBlobStoreApiMetadata extends BaseHttpApiMetadata {
|
||||||
|
|
||||||
public static Builder builder() {
|
public static Builder builder() {
|
||||||
return new Builder();
|
return new Builder();
|
||||||
|
@ -44,10 +43,10 @@ public class JcloudsTestBlobStoreApiMetadata extends BaseRestApiMetadata {
|
||||||
super(builder);
|
super(builder);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Builder extends BaseRestApiMetadata.Builder<Builder> {
|
public static class Builder extends BaseHttpApiMetadata.Builder<IntegrationTestClient, Builder> {
|
||||||
|
|
||||||
protected Builder() {
|
protected Builder() {
|
||||||
super(IntegrationTestClient.class, IntegrationTestAsyncClient.class);
|
super(IntegrationTestClient.class);
|
||||||
id("test-blobstore-api")
|
id("test-blobstore-api")
|
||||||
.view(Storage.class)
|
.view(Storage.class)
|
||||||
.name("Test Blobstore Api")
|
.name("Test Blobstore Api")
|
||||||
|
|
|
@ -18,14 +18,13 @@ package org.jclouds.apis;
|
||||||
|
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
|
|
||||||
import org.jclouds.http.IntegrationTestAsyncClient;
|
|
||||||
import org.jclouds.http.IntegrationTestClient;
|
import org.jclouds.http.IntegrationTestClient;
|
||||||
import org.jclouds.rest.internal.BaseRestApiMetadata;
|
import org.jclouds.rest.internal.BaseHttpApiMetadata;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implementation of @ link org.jclouds.types.ApiMetadata} for testing.
|
* Implementation of @ link org.jclouds.types.ApiMetadata} for testing.
|
||||||
*/
|
*/
|
||||||
public class JcloudsTestComputeApiMetadata extends BaseRestApiMetadata {
|
public class JcloudsTestComputeApiMetadata extends BaseHttpApiMetadata {
|
||||||
|
|
||||||
public static Builder builder() {
|
public static Builder builder() {
|
||||||
return new Builder();
|
return new Builder();
|
||||||
|
@ -44,10 +43,10 @@ public class JcloudsTestComputeApiMetadata extends BaseRestApiMetadata {
|
||||||
super(builder);
|
super(builder);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Builder extends BaseRestApiMetadata.Builder<Builder> {
|
public static class Builder extends BaseHttpApiMetadata.Builder<IntegrationTestClient, Builder> {
|
||||||
|
|
||||||
protected Builder() {
|
protected Builder() {
|
||||||
super(IntegrationTestClient.class, IntegrationTestAsyncClient.class);
|
super(IntegrationTestClient.class);
|
||||||
id("test-compute-api")
|
id("test-compute-api")
|
||||||
.view(Compute.class)
|
.view(Compute.class)
|
||||||
.name("Test Compute Api")
|
.name("Test Compute Api")
|
||||||
|
|
|
@ -18,14 +18,13 @@ package org.jclouds.apis;
|
||||||
|
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
|
|
||||||
import org.jclouds.http.IntegrationTestAsyncClient;
|
|
||||||
import org.jclouds.http.IntegrationTestClient;
|
import org.jclouds.http.IntegrationTestClient;
|
||||||
import org.jclouds.rest.internal.BaseRestApiMetadata;
|
import org.jclouds.rest.internal.BaseHttpApiMetadata;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implementation of @ link org.jclouds.types.ApiMetadata} for testing.
|
* Implementation of @ link org.jclouds.types.ApiMetadata} for testing.
|
||||||
*/
|
*/
|
||||||
public class JcloudsTestYetAnotherComputeApiMetadata extends BaseRestApiMetadata {
|
public class JcloudsTestYetAnotherComputeApiMetadata extends BaseHttpApiMetadata {
|
||||||
|
|
||||||
public static Builder builder() {
|
public static Builder builder() {
|
||||||
return new Builder();
|
return new Builder();
|
||||||
|
@ -44,10 +43,10 @@ public class JcloudsTestYetAnotherComputeApiMetadata extends BaseRestApiMetadata
|
||||||
super(builder);
|
super(builder);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Builder extends BaseRestApiMetadata.Builder<Builder> {
|
public static class Builder extends BaseHttpApiMetadata.Builder<IntegrationTestClient, Builder> {
|
||||||
|
|
||||||
protected Builder() {
|
protected Builder() {
|
||||||
super(IntegrationTestClient.class, IntegrationTestAsyncClient.class);
|
super(IntegrationTestClient.class);
|
||||||
id("test-yet-another-compute-api")
|
id("test-yet-another-compute-api")
|
||||||
.view(Compute.class)
|
.view(Compute.class)
|
||||||
.name("Test Yet Another Compute Api")
|
.name("Test Yet Another Compute Api")
|
||||||
|
|
|
@ -1,117 +0,0 @@
|
||||||
/*
|
|
||||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
||||||
* contributor license agreements. See the NOTICE file distributed with
|
|
||||||
* this work for additional information regarding copyright ownership.
|
|
||||||
* The ASF licenses this file to You 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.config;
|
|
||||||
|
|
||||||
import static com.google.common.base.Suppliers.ofInstance;
|
|
||||||
import static org.easymock.EasyMock.createMock;
|
|
||||||
import static org.testng.Assert.assertEquals;
|
|
||||||
|
|
||||||
import javax.inject.Inject;
|
|
||||||
|
|
||||||
import org.jclouds.Context;
|
|
||||||
import org.jclouds.domain.Credentials;
|
|
||||||
import org.jclouds.http.IntegrationTestAsyncClient;
|
|
||||||
import org.jclouds.http.IntegrationTestClient;
|
|
||||||
import org.jclouds.providers.AnonymousProviderMetadata;
|
|
||||||
import org.jclouds.providers.ProviderMetadata;
|
|
||||||
import org.jclouds.providers.config.BindProviderMetadataContextAndCredentials;
|
|
||||||
import org.jclouds.rest.ApiContext;
|
|
||||||
import org.jclouds.rest.HttpApiMetadata;
|
|
||||||
import org.jclouds.rest.Utils;
|
|
||||||
import org.jclouds.rest.internal.BaseRestApiTest.MockModule;
|
|
||||||
import org.testng.annotations.Test;
|
|
||||||
|
|
||||||
import com.google.common.reflect.TypeToken;
|
|
||||||
import com.google.inject.AbstractModule;
|
|
||||||
import com.google.inject.Guice;
|
|
||||||
import com.google.inject.Injector;
|
|
||||||
|
|
||||||
@Test(groups = "unit", testName = "BindApiContextWithWildcardExtendsExplicitAndRawTypeTest")
|
|
||||||
public class BindApiContextWithWildcardExtendsExplicitAndRawTypeTest {
|
|
||||||
|
|
||||||
@SuppressWarnings("rawtypes")
|
|
||||||
private static class ExpectedBindings {
|
|
||||||
|
|
||||||
private final ApiContext raw;
|
|
||||||
private final ApiContext<IntegrationTestClient> explicit;
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
public ExpectedBindings(ApiContext raw, ApiContext<IntegrationTestClient> explicit) {
|
|
||||||
this.raw = raw;
|
|
||||||
this.explicit = explicit;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testRawAndExplicit() {
|
|
||||||
ProviderMetadata md = AnonymousProviderMetadata.forApiOnEndpoint(IntegrationTestClient.class, "http://localhost");
|
|
||||||
|
|
||||||
ExpectedBindings bindings = injectorFor(md).getInstance(ExpectedBindings.class);
|
|
||||||
assertEquals(bindings.raw, bindings.explicit);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Injector injectorFor(ProviderMetadata md) {
|
|
||||||
return Guice.createInjector(new BindNameToContext("test"), new BindProviderMetadataContextAndCredentials(md,
|
|
||||||
ofInstance(new Credentials("user", "pass"))), new BindApiContextWithWildcardExtendsExplicitAndRawType(
|
|
||||||
HttpApiMetadata.class.cast(md.getApiMetadata())),
|
|
||||||
|
|
||||||
// stuff needed for ApiContextImpl
|
|
||||||
new MockModule(), new AbstractModule() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void configure() {
|
|
||||||
bind(Utils.class).toInstance(createMock(Utils.class));
|
|
||||||
bind(IntegrationTestClient.class).toInstance(createMock(IntegrationTestClient.class));
|
|
||||||
bind(IntegrationTestAsyncClient.class).toInstance(createMock(IntegrationTestAsyncClient.class));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("rawtypes")
|
|
||||||
private static class ExpectedBindingsWithWildCardExtends {
|
|
||||||
|
|
||||||
private final ApiContext raw;
|
|
||||||
private final ApiContext<IntegrationTestClient> explicit;
|
|
||||||
private final ApiContext<? extends IntegrationTestClient> wildcardExtends;
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
public ExpectedBindingsWithWildCardExtends(ApiContext raw, ApiContext<IntegrationTestClient> explicit,
|
|
||||||
ApiContext<? extends IntegrationTestClient> wildcardExtends) {
|
|
||||||
this.raw = raw;
|
|
||||||
this.explicit = explicit;
|
|
||||||
this.wildcardExtends = wildcardExtends;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testRawExplicitAndWildCardExtends() {
|
|
||||||
ProviderMetadata md = AnonymousProviderMetadata.forApiOnEndpoint(IntegrationTestClient.class, "http://localhost");
|
|
||||||
|
|
||||||
TypeToken<? extends Context> wildCardExtendsType = new TypeToken<ApiContext<? extends IntegrationTestClient>>() {
|
|
||||||
private static final long serialVersionUID = 1L;
|
|
||||||
};
|
|
||||||
|
|
||||||
md = md.toBuilder().apiMetadata(md.getApiMetadata().toBuilder().context(wildCardExtendsType).build()).build();
|
|
||||||
|
|
||||||
ExpectedBindingsWithWildCardExtends bindings = injectorFor(md).getInstance(
|
|
||||||
ExpectedBindingsWithWildCardExtends.class);
|
|
||||||
assertEquals(bindings.raw, bindings.explicit);
|
|
||||||
assertEquals(bindings.explicit, bindings.wildcardExtends);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,123 +0,0 @@
|
||||||
/*
|
|
||||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
||||||
* contributor license agreements. See the NOTICE file distributed with
|
|
||||||
* this work for additional information regarding copyright ownership.
|
|
||||||
* The ASF licenses this file to You 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.config;
|
|
||||||
|
|
||||||
import static com.google.common.base.Suppliers.ofInstance;
|
|
||||||
import static org.easymock.EasyMock.createMock;
|
|
||||||
import static org.testng.Assert.assertEquals;
|
|
||||||
|
|
||||||
import javax.inject.Inject;
|
|
||||||
|
|
||||||
import org.jclouds.Context;
|
|
||||||
import org.jclouds.domain.Credentials;
|
|
||||||
import org.jclouds.http.IntegrationTestAsyncClient;
|
|
||||||
import org.jclouds.http.IntegrationTestClient;
|
|
||||||
import org.jclouds.providers.AnonymousProviderMetadata;
|
|
||||||
import org.jclouds.providers.ProviderMetadata;
|
|
||||||
import org.jclouds.providers.config.BindProviderMetadataContextAndCredentials;
|
|
||||||
import org.jclouds.rest.RestApiMetadata;
|
|
||||||
import org.jclouds.rest.RestContext;
|
|
||||||
import org.jclouds.rest.Utils;
|
|
||||||
import org.jclouds.rest.internal.BaseRestApiTest.MockModule;
|
|
||||||
import org.testng.annotations.Test;
|
|
||||||
|
|
||||||
import com.google.common.reflect.TypeToken;
|
|
||||||
import com.google.inject.AbstractModule;
|
|
||||||
import com.google.inject.Guice;
|
|
||||||
import com.google.inject.Injector;
|
|
||||||
|
|
||||||
@Test(groups = "unit", testName = "BindRestContextWithWildcardExtendsExplicitAndRawTypeTest")
|
|
||||||
public class BindRestContextWithWildcardExtendsExplicitAndRawTypeTest {
|
|
||||||
|
|
||||||
@SuppressWarnings("rawtypes")
|
|
||||||
private static class ExpectedBindings {
|
|
||||||
|
|
||||||
private final RestContext raw;
|
|
||||||
private final RestContext<IntegrationTestClient, IntegrationTestAsyncClient> explicit;
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
public ExpectedBindings(RestContext raw,
|
|
||||||
RestContext<IntegrationTestClient, IntegrationTestAsyncClient> explicit) {
|
|
||||||
this.raw = raw;
|
|
||||||
this.explicit = explicit;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testRawAndExplicit() {
|
|
||||||
ProviderMetadata md = AnonymousProviderMetadata.forClientMappedToAsyncClientOnEndpoint(
|
|
||||||
IntegrationTestClient.class, IntegrationTestAsyncClient.class, "http://localhost");
|
|
||||||
|
|
||||||
ExpectedBindings bindings = injectorFor(md).getInstance(ExpectedBindings.class);
|
|
||||||
assertEquals(bindings.raw, bindings.explicit);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Injector injectorFor(ProviderMetadata md) {
|
|
||||||
return Guice.createInjector(
|
|
||||||
new BindNameToContext("test"),
|
|
||||||
new BindProviderMetadataContextAndCredentials(md, ofInstance(new Credentials("user", "pass"))),
|
|
||||||
new BindRestContextWithWildcardExtendsExplicitAndRawType(RestApiMetadata.class.cast(md
|
|
||||||
.getApiMetadata())),
|
|
||||||
|
|
||||||
// stuff needed for RestContextImpl
|
|
||||||
new MockModule(),
|
|
||||||
new AbstractModule() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void configure() {
|
|
||||||
bind(Utils.class).toInstance(createMock(Utils.class));
|
|
||||||
bind(IntegrationTestClient.class).toInstance(createMock(IntegrationTestClient.class));
|
|
||||||
bind(IntegrationTestAsyncClient.class).toInstance(createMock(IntegrationTestAsyncClient.class));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("rawtypes")
|
|
||||||
private static class ExpectedBindingsWithWildCardExtends {
|
|
||||||
|
|
||||||
private final RestContext raw;
|
|
||||||
private final RestContext<IntegrationTestClient, IntegrationTestAsyncClient> explicit;
|
|
||||||
private final RestContext<? extends IntegrationTestClient, ? extends IntegrationTestAsyncClient> wildcardExtends;
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
public ExpectedBindingsWithWildCardExtends(RestContext raw,
|
|
||||||
RestContext<IntegrationTestClient, IntegrationTestAsyncClient> explicit,
|
|
||||||
RestContext<? extends IntegrationTestClient, ? extends IntegrationTestAsyncClient> wildcardExtends) {
|
|
||||||
this.raw = raw;
|
|
||||||
this.explicit = explicit;
|
|
||||||
this.wildcardExtends = wildcardExtends;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testRawExplicitAndWildCardExtends() {
|
|
||||||
ProviderMetadata md = AnonymousProviderMetadata.forClientMappedToAsyncClientOnEndpoint(
|
|
||||||
IntegrationTestClient.class, IntegrationTestAsyncClient.class, "http://localhost");
|
|
||||||
|
|
||||||
TypeToken<? extends Context> wildCardExtendsType = new TypeToken<RestContext<? extends IntegrationTestClient, ? extends IntegrationTestAsyncClient>>() {
|
|
||||||
private static final long serialVersionUID = 1L;
|
|
||||||
};
|
|
||||||
|
|
||||||
md = md.toBuilder().apiMetadata(md.getApiMetadata().toBuilder().context(wildCardExtendsType).build()).build();
|
|
||||||
|
|
||||||
ExpectedBindingsWithWildCardExtends bindings = injectorFor(md).getInstance(ExpectedBindingsWithWildCardExtends.class);
|
|
||||||
assertEquals(bindings.raw, bindings.explicit);
|
|
||||||
assertEquals(bindings.explicit, bindings.wildcardExtends);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -27,6 +27,7 @@ import static com.google.common.util.concurrent.Uninterruptibles.sleepUninterrup
|
||||||
import static javax.servlet.http.HttpServletResponse.SC_OK;
|
import static javax.servlet.http.HttpServletResponse.SC_OK;
|
||||||
import static org.jclouds.Constants.PROPERTY_RELAX_HOSTNAME;
|
import static org.jclouds.Constants.PROPERTY_RELAX_HOSTNAME;
|
||||||
import static org.jclouds.Constants.PROPERTY_TRUST_ALL_CERTS;
|
import static org.jclouds.Constants.PROPERTY_TRUST_ALL_CERTS;
|
||||||
|
import static org.jclouds.providers.AnonymousProviderMetadata.forApiOnEndpoint;
|
||||||
import static org.jclouds.util.Closeables2.closeQuietly;
|
import static org.jclouds.util.Closeables2.closeQuietly;
|
||||||
import static org.jclouds.util.Strings2.toStringAndClose;
|
import static org.jclouds.util.Strings2.toStringAndClose;
|
||||||
|
|
||||||
|
@ -52,7 +53,6 @@ import org.eclipse.jetty.server.ssl.SslSelectChannelConnector;
|
||||||
import org.eclipse.jetty.util.ssl.SslContextFactory;
|
import org.eclipse.jetty.util.ssl.SslContextFactory;
|
||||||
import org.jclouds.ContextBuilder;
|
import org.jclouds.ContextBuilder;
|
||||||
import org.jclouds.io.ByteStreams2;
|
import org.jclouds.io.ByteStreams2;
|
||||||
import org.jclouds.providers.AnonymousProviderMetadata;
|
|
||||||
import org.jclouds.utils.TestUtils;
|
import org.jclouds.utils.TestUtils;
|
||||||
import org.testng.annotations.AfterClass;
|
import org.testng.annotations.AfterClass;
|
||||||
import org.testng.annotations.BeforeClass;
|
import org.testng.annotations.BeforeClass;
|
||||||
|
@ -248,9 +248,7 @@ public abstract class BaseJettyTest {
|
||||||
properties.setProperty(PROPERTY_TRUST_ALL_CERTS, "true");
|
properties.setProperty(PROPERTY_TRUST_ALL_CERTS, "true");
|
||||||
properties.setProperty(PROPERTY_RELAX_HOSTNAME, "true");
|
properties.setProperty(PROPERTY_RELAX_HOSTNAME, "true");
|
||||||
return ContextBuilder
|
return ContextBuilder
|
||||||
.newBuilder(
|
.newBuilder(forApiOnEndpoint(IntegrationTestClient.class, "http://localhost:" + testPort))
|
||||||
AnonymousProviderMetadata.forClientMappedToAsyncClientOnEndpoint(IntegrationTestClient.class,
|
|
||||||
IntegrationTestAsyncClient.class, "http://localhost:" + testPort))
|
|
||||||
.modules(ImmutableSet.<Module> copyOf(connectionModules)).overrides(properties);
|
.modules(ImmutableSet.<Module> copyOf(connectionModules)).overrides(properties);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,209 +0,0 @@
|
||||||
/*
|
|
||||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
||||||
* contributor license agreements. See the NOTICE file distributed with
|
|
||||||
* this work for additional information regarding copyright ownership.
|
|
||||||
* The ASF licenses this file to You 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.http;
|
|
||||||
|
|
||||||
import static com.google.common.util.concurrent.Futures.immediateFuture;
|
|
||||||
|
|
||||||
import java.io.Closeable;
|
|
||||||
import java.lang.annotation.ElementType;
|
|
||||||
import java.lang.annotation.Retention;
|
|
||||||
import java.lang.annotation.RetentionPolicy;
|
|
||||||
import java.lang.annotation.Target;
|
|
||||||
|
|
||||||
import javax.inject.Singleton;
|
|
||||||
import javax.ws.rs.GET;
|
|
||||||
import javax.ws.rs.HEAD;
|
|
||||||
import javax.ws.rs.HeaderParam;
|
|
||||||
import javax.ws.rs.HttpMethod;
|
|
||||||
import javax.ws.rs.POST;
|
|
||||||
import javax.ws.rs.PUT;
|
|
||||||
import javax.ws.rs.Path;
|
|
||||||
import javax.ws.rs.PathParam;
|
|
||||||
|
|
||||||
import org.jclouds.Fallbacks.FalseOnNotFoundOr404;
|
|
||||||
import org.jclouds.http.functions.ParseSax;
|
|
||||||
import org.jclouds.http.options.HttpRequestOptions;
|
|
||||||
import org.jclouds.io.Payload;
|
|
||||||
import org.jclouds.rest.annotations.BinderParam;
|
|
||||||
import org.jclouds.rest.annotations.Fallback;
|
|
||||||
import org.jclouds.rest.annotations.MapBinder;
|
|
||||||
import org.jclouds.rest.annotations.PayloadParam;
|
|
||||||
import org.jclouds.rest.annotations.RequestFilters;
|
|
||||||
import org.jclouds.rest.annotations.ResponseParser;
|
|
||||||
import org.jclouds.rest.annotations.XMLResponseParser;
|
|
||||||
import org.jclouds.rest.binders.BindToJsonPayload;
|
|
||||||
import org.jclouds.rest.binders.BindToStringPayload;
|
|
||||||
import org.jclouds.util.Strings2;
|
|
||||||
|
|
||||||
import com.google.common.base.Function;
|
|
||||||
import com.google.common.collect.Multimap;
|
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
|
||||||
import com.google.inject.Provides;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sample test for the behaviour of our Integration Test jetty server.
|
|
||||||
*
|
|
||||||
* @see IntegrationTestClient
|
|
||||||
*/
|
|
||||||
public interface IntegrationTestAsyncClient extends Closeable {
|
|
||||||
@Target({ ElementType.METHOD })
|
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
|
||||||
@HttpMethod("ROWDY")
|
|
||||||
public @interface ROWDY {
|
|
||||||
}
|
|
||||||
|
|
||||||
@ROWDY
|
|
||||||
@Path("/objects/{id}")
|
|
||||||
ListenableFuture<String> rowdy(@PathParam("id") String path);
|
|
||||||
|
|
||||||
@HEAD
|
|
||||||
@Path("/objects/{id}")
|
|
||||||
@Fallback(FalseOnNotFoundOr404.class)
|
|
||||||
ListenableFuture<Boolean> exists(@PathParam("id") String path);
|
|
||||||
|
|
||||||
@GET
|
|
||||||
@Path("/objects/{id}")
|
|
||||||
ListenableFuture<String> download(@PathParam("id") String id);
|
|
||||||
|
|
||||||
ListenableFuture<HttpResponse> invoke(HttpRequest request);
|
|
||||||
|
|
||||||
@GET
|
|
||||||
@Path("/{path}")
|
|
||||||
ListenableFuture<String> synch(@PathParam("path") String id);
|
|
||||||
|
|
||||||
@GET
|
|
||||||
@Path("/objects/{id}")
|
|
||||||
@Fallback(FooOnException.class)
|
|
||||||
ListenableFuture<String> downloadException(@PathParam("id") String id, HttpRequestOptions options);
|
|
||||||
|
|
||||||
static class FooOnException implements org.jclouds.Fallback<String> {
|
|
||||||
public ListenableFuture<String> create(Throwable t) throws Exception {
|
|
||||||
return immediateFuture("foo");
|
|
||||||
}
|
|
||||||
|
|
||||||
public String createOrPropagate(Throwable t) throws Exception {
|
|
||||||
return "foo";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@GET
|
|
||||||
@Path("/objects/{id}")
|
|
||||||
@Fallback(FooOnException.class)
|
|
||||||
ListenableFuture<String> synchException(@PathParam("id") String id, @HeaderParam("Range") String header);
|
|
||||||
|
|
||||||
@PUT
|
|
||||||
@Path("/objects/{id}")
|
|
||||||
ListenableFuture<String> upload(@PathParam("id") String id, @BinderParam(BindToStringPayload.class) String toPut);
|
|
||||||
|
|
||||||
@POST
|
|
||||||
@Path("/objects/{id}")
|
|
||||||
ListenableFuture<String> post(@PathParam("id") String id, @BinderParam(BindToStringPayload.class) String toPut);
|
|
||||||
|
|
||||||
@POST
|
|
||||||
@Path("/objects/{id}")
|
|
||||||
ListenableFuture<String> postAsInputStream(@PathParam("id") String id,
|
|
||||||
@BinderParam(BindToInputStreamPayload.class) String toPut);
|
|
||||||
|
|
||||||
static class BindToInputStreamPayload extends BindToStringPayload {
|
|
||||||
@Override
|
|
||||||
public <R extends HttpRequest> R bindToRequest(R request, Object payload) {
|
|
||||||
request.setPayload(Strings2.toInputStream(payload.toString()));
|
|
||||||
request.getPayload().getContentMetadata().setContentLength((long) payload.toString().getBytes().length);
|
|
||||||
return request;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Singleton
|
|
||||||
static class ResponsePayload implements Function<HttpResponse, Multimap<String, String>> {
|
|
||||||
|
|
||||||
public Multimap<String, String> apply(HttpResponse from) {
|
|
||||||
return from.getHeaders();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@POST
|
|
||||||
@Path("/objects/{id}")
|
|
||||||
@ResponseParser(ResponsePayload.class)
|
|
||||||
ListenableFuture<Multimap<String, String>> postPayloadAndReturnHeaders(@PathParam("id") String id, Payload payload);
|
|
||||||
|
|
||||||
@POST
|
|
||||||
@Path("/objects/{id}")
|
|
||||||
@MapBinder(BindToJsonPayload.class)
|
|
||||||
ListenableFuture<String> postJson(@PathParam("id") String id, @PayloadParam("key") String toPut);
|
|
||||||
|
|
||||||
@GET
|
|
||||||
@Path("/objects/{id}")
|
|
||||||
@RequestFilters(Filter.class)
|
|
||||||
ListenableFuture<String> downloadFilter(@PathParam("id") String id, @HeaderParam("filterme") String header);
|
|
||||||
|
|
||||||
static class Filter implements HttpRequestFilter {
|
|
||||||
public HttpRequest filter(HttpRequest request) throws HttpException {
|
|
||||||
if (request.getHeaders().containsKey("filterme")) {
|
|
||||||
request = request.toBuilder().replaceHeader("test", "test").build();
|
|
||||||
}
|
|
||||||
return request;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@GET
|
|
||||||
@Path("/objects/{id}")
|
|
||||||
ListenableFuture<String> download(@PathParam("id") String id, @HeaderParam("test") String header);
|
|
||||||
|
|
||||||
@GET
|
|
||||||
@Path("/objects/{id}")
|
|
||||||
@XMLResponseParser(BarHandler.class)
|
|
||||||
ListenableFuture<String> downloadAndParse(@PathParam("id") String id);
|
|
||||||
|
|
||||||
public static class BarHandler extends ParseSax.HandlerWithResult<String> {
|
|
||||||
|
|
||||||
private String bar = null;
|
|
||||||
private StringBuilder currentText = new StringBuilder();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void endElement(String uri, String name, String qName) {
|
|
||||||
if (qName.equals("bar")) {
|
|
||||||
bar = currentText.toString();
|
|
||||||
}
|
|
||||||
currentText = new StringBuilder();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void characters(char ch[], int start, int length) {
|
|
||||||
currentText.append(ch, start, length);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getResult() {
|
|
||||||
return bar;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@POST
|
|
||||||
@Path("/objects/{id}")
|
|
||||||
ListenableFuture<Void> postNothing(@PathParam("id") String id);
|
|
||||||
|
|
||||||
@PUT
|
|
||||||
@Path("/objects/{id}")
|
|
||||||
ListenableFuture<Void> putNothing(@PathParam("id") String id);
|
|
||||||
|
|
||||||
@Provides
|
|
||||||
StringBuilder newStringBuilder();
|
|
||||||
|
|
||||||
}
|
|
|
@ -15,6 +15,7 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.jclouds.http.handlers;
|
package org.jclouds.http.handlers;
|
||||||
|
|
||||||
import static org.jclouds.reflect.Reflection2.method;
|
import static org.jclouds.reflect.Reflection2.method;
|
||||||
import static org.testng.Assert.assertEquals;
|
import static org.testng.Assert.assertEquals;
|
||||||
import static org.testng.Assert.assertTrue;
|
import static org.testng.Assert.assertTrue;
|
||||||
|
@ -26,7 +27,6 @@ import org.jclouds.ContextBuilder;
|
||||||
import org.jclouds.http.HttpCommand;
|
import org.jclouds.http.HttpCommand;
|
||||||
import org.jclouds.http.HttpRequest;
|
import org.jclouds.http.HttpRequest;
|
||||||
import org.jclouds.http.HttpResponse;
|
import org.jclouds.http.HttpResponse;
|
||||||
import org.jclouds.http.IntegrationTestAsyncClient;
|
|
||||||
import org.jclouds.http.IntegrationTestClient;
|
import org.jclouds.http.IntegrationTestClient;
|
||||||
import org.jclouds.io.Payloads;
|
import org.jclouds.io.Payloads;
|
||||||
import org.jclouds.providers.AnonymousProviderMetadata;
|
import org.jclouds.providers.AnonymousProviderMetadata;
|
||||||
|
@ -129,7 +129,7 @@ public class BackoffLimitedRetryHandlerTest {
|
||||||
|
|
||||||
|
|
||||||
private HttpCommand createCommand() throws SecurityException, NoSuchMethodException {
|
private HttpCommand createCommand() throws SecurityException, NoSuchMethodException {
|
||||||
Invokable<IntegrationTestAsyncClient, String> method = method(IntegrationTestAsyncClient.class, "download", String.class);
|
Invokable<IntegrationTestClient, String> method = method(IntegrationTestClient.class, "download", String.class);
|
||||||
|
|
||||||
return new HttpCommand(processor.apply(Invocation.create(method, ImmutableList.<Object> of("1"))));
|
return new HttpCommand(processor.apply(Invocation.create(method, ImmutableList.<Object> of("1"))));
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,14 +22,13 @@ import static org.easymock.EasyMock.createMock;
|
||||||
import static org.easymock.EasyMock.expect;
|
import static org.easymock.EasyMock.expect;
|
||||||
import static org.easymock.EasyMock.replay;
|
import static org.easymock.EasyMock.replay;
|
||||||
import static org.easymock.EasyMock.verify;
|
import static org.easymock.EasyMock.verify;
|
||||||
|
import static org.jclouds.providers.AnonymousProviderMetadata.forApiOnEndpoint;
|
||||||
|
|
||||||
import org.jclouds.ContextBuilder;
|
import org.jclouds.ContextBuilder;
|
||||||
import org.jclouds.http.HttpCommand;
|
import org.jclouds.http.HttpCommand;
|
||||||
import org.jclouds.http.HttpRequest;
|
import org.jclouds.http.HttpRequest;
|
||||||
import org.jclouds.http.HttpResponse;
|
import org.jclouds.http.HttpResponse;
|
||||||
import org.jclouds.http.IntegrationTestAsyncClient;
|
|
||||||
import org.jclouds.http.IntegrationTestClient;
|
import org.jclouds.http.IntegrationTestClient;
|
||||||
import org.jclouds.providers.AnonymousProviderMetadata;
|
|
||||||
import org.jclouds.rest.internal.BaseRestApiTest.MockModule;
|
import org.jclouds.rest.internal.BaseRestApiTest.MockModule;
|
||||||
import org.testng.annotations.Test;
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
@ -42,10 +41,8 @@ import com.google.inject.Module;
|
||||||
*/
|
*/
|
||||||
@Test(groups = "unit")
|
@Test(groups = "unit")
|
||||||
public class RedirectionRetryHandlerTest {
|
public class RedirectionRetryHandlerTest {
|
||||||
Injector injector = ContextBuilder.newBuilder(
|
Injector injector = ContextBuilder.newBuilder(forApiOnEndpoint(IntegrationTestClient.class, "http://localhost"))
|
||||||
AnonymousProviderMetadata.forClientMappedToAsyncClientOnEndpoint(IntegrationTestClient.class,
|
.modules(ImmutableSet.<Module>of(new MockModule())).buildInjector();
|
||||||
IntegrationTestAsyncClient.class, "http://localhost")).modules(
|
|
||||||
ImmutableSet.<Module> of(new MockModule())).buildInjector();
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void test302DoesNotRetry() {
|
public void test302DoesNotRetry() {
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.providers.config;
|
package org.jclouds.providers.config;
|
||||||
|
|
||||||
|
import static org.jclouds.providers.AnonymousProviderMetadata.forApiOnEndpoint;
|
||||||
import static org.testng.Assert.assertEquals;
|
import static org.testng.Assert.assertEquals;
|
||||||
|
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
@ -28,13 +29,11 @@ import org.jclouds.Context;
|
||||||
import org.jclouds.apis.ApiMetadata;
|
import org.jclouds.apis.ApiMetadata;
|
||||||
import org.jclouds.domain.Credentials;
|
import org.jclouds.domain.Credentials;
|
||||||
import org.jclouds.domain.LoginCredentials;
|
import org.jclouds.domain.LoginCredentials;
|
||||||
import org.jclouds.http.IntegrationTestAsyncClient;
|
|
||||||
import org.jclouds.http.IntegrationTestClient;
|
import org.jclouds.http.IntegrationTestClient;
|
||||||
import org.jclouds.internal.FilterStringsBoundToInjectorByName;
|
import org.jclouds.internal.FilterStringsBoundToInjectorByName;
|
||||||
import org.jclouds.javax.annotation.Nullable;
|
import org.jclouds.javax.annotation.Nullable;
|
||||||
import org.jclouds.location.Iso3166;
|
import org.jclouds.location.Iso3166;
|
||||||
import org.jclouds.location.Provider;
|
import org.jclouds.location.Provider;
|
||||||
import org.jclouds.providers.AnonymousProviderMetadata;
|
|
||||||
import org.jclouds.providers.ProviderMetadata;
|
import org.jclouds.providers.ProviderMetadata;
|
||||||
import org.jclouds.rest.annotations.Api;
|
import org.jclouds.rest.annotations.Api;
|
||||||
import org.jclouds.rest.annotations.ApiVersion;
|
import org.jclouds.rest.annotations.ApiVersion;
|
||||||
|
@ -94,9 +93,8 @@ public class BindProviderMetadataContextAndCredentialsTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testExpectedBindingsWhenCredentialIsNotNull() {
|
public void testExpectedBindingsWhenCredentialIsNotNull() {
|
||||||
|
ProviderMetadata md = forApiOnEndpoint(IntegrationTestClient.class, "http://localhost");
|
||||||
|
|
||||||
ProviderMetadata md = AnonymousProviderMetadata.forClientMappedToAsyncClientOnEndpoint(
|
|
||||||
IntegrationTestClient.class, IntegrationTestAsyncClient.class, "http://localhost");
|
|
||||||
Supplier<Credentials> creds = Suppliers.<Credentials> ofInstance(LoginCredentials.builder().user("user")
|
Supplier<Credentials> creds = Suppliers.<Credentials> ofInstance(LoginCredentials.builder().user("user")
|
||||||
.password("password").build());
|
.password("password").build());
|
||||||
|
|
||||||
|
@ -108,9 +106,8 @@ public class BindProviderMetadataContextAndCredentialsTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testExpectedBindingsWhenCredentialIsNull() {
|
public void testExpectedBindingsWhenCredentialIsNull() {
|
||||||
|
ProviderMetadata md = forApiOnEndpoint(IntegrationTestClient.class, "http://localhost");
|
||||||
|
|
||||||
ProviderMetadata md = AnonymousProviderMetadata.forClientMappedToAsyncClientOnEndpoint(
|
|
||||||
IntegrationTestClient.class, IntegrationTestAsyncClient.class, "http://localhost");
|
|
||||||
Supplier<Credentials> creds = Suppliers.<Credentials> ofInstance(LoginCredentials.builder().user("user").build());
|
Supplier<Credentials> creds = Suppliers.<Credentials> ofInstance(LoginCredentials.builder().user("user").build());
|
||||||
|
|
||||||
ExpectedBindings bindings = Guice.createInjector(new BindProviderMetadataContextAndCredentials(md, creds))
|
ExpectedBindings bindings = Guice.createInjector(new BindProviderMetadataContextAndCredentials(md, creds))
|
||||||
|
@ -121,9 +118,8 @@ public class BindProviderMetadataContextAndCredentialsTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testExpectedBindingsWhenBuildVersionAbsent() {
|
public void testExpectedBindingsWhenBuildVersionAbsent() {
|
||||||
|
ProviderMetadata md = forApiOnEndpoint(IntegrationTestClient.class, "http://localhost");
|
||||||
|
|
||||||
ProviderMetadata md = AnonymousProviderMetadata.forClientMappedToAsyncClientOnEndpoint(
|
|
||||||
IntegrationTestClient.class, IntegrationTestAsyncClient.class, "http://localhost");
|
|
||||||
ApiMetadata apiMd = md.getApiMetadata().toBuilder().buildVersion(null).build();
|
ApiMetadata apiMd = md.getApiMetadata().toBuilder().buildVersion(null).build();
|
||||||
md = md.toBuilder().apiMetadata(apiMd).build();
|
md = md.toBuilder().apiMetadata(apiMd).build();
|
||||||
Supplier<Credentials> creds = Suppliers.<Credentials> ofInstance(LoginCredentials.builder().user("user").build());
|
Supplier<Credentials> creds = Suppliers.<Credentials> ofInstance(LoginCredentials.builder().user("user").build());
|
||||||
|
@ -135,9 +131,8 @@ public class BindProviderMetadataContextAndCredentialsTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testProviderOverridesApiMetadataProperty() {
|
public void testProviderOverridesApiMetadataProperty() {
|
||||||
|
ProviderMetadata md = forApiOnEndpoint(IntegrationTestClient.class, "http://localhost");
|
||||||
|
|
||||||
ProviderMetadata md = AnonymousProviderMetadata.forClientMappedToAsyncClientOnEndpoint(
|
|
||||||
IntegrationTestClient.class, IntegrationTestAsyncClient.class, "http://localhost");
|
|
||||||
Properties defaultProps = md.getDefaultProperties();
|
Properties defaultProps = md.getDefaultProperties();
|
||||||
defaultProps.setProperty(Constants.PROPERTY_SESSION_INTERVAL, Integer.MAX_VALUE + "");
|
defaultProps.setProperty(Constants.PROPERTY_SESSION_INTERVAL, Integer.MAX_VALUE + "");
|
||||||
md = md.toBuilder().defaultProperties(defaultProps).build();
|
md = md.toBuilder().defaultProperties(defaultProps).build();
|
||||||
|
|
|
@ -17,14 +17,13 @@
|
||||||
package org.jclouds.providers.internal;
|
package org.jclouds.providers.internal;
|
||||||
|
|
||||||
import static org.jclouds.Constants.PROPERTY_ISO3166_CODES;
|
import static org.jclouds.Constants.PROPERTY_ISO3166_CODES;
|
||||||
|
import static org.jclouds.providers.AnonymousProviderMetadata.forApiOnEndpoint;
|
||||||
import static org.testng.Assert.assertEquals;
|
import static org.testng.Assert.assertEquals;
|
||||||
|
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
|
||||||
import org.jclouds.Constants;
|
import org.jclouds.Constants;
|
||||||
import org.jclouds.http.IntegrationTestAsyncClient;
|
|
||||||
import org.jclouds.http.IntegrationTestClient;
|
import org.jclouds.http.IntegrationTestClient;
|
||||||
import org.jclouds.providers.AnonymousProviderMetadata;
|
|
||||||
import org.jclouds.providers.ProviderMetadata;
|
import org.jclouds.providers.ProviderMetadata;
|
||||||
import org.testng.annotations.Test;
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
@ -35,8 +34,7 @@ public class UpdateProviderMetadataFromPropertiesTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testProviderMetadataWithUpdatedEndpointUpdatesAndRetainsAllDefaultPropertiesExceptEndpoint() {
|
public void testProviderMetadataWithUpdatedEndpointUpdatesAndRetainsAllDefaultPropertiesExceptEndpoint() {
|
||||||
ProviderMetadata md = AnonymousProviderMetadata.forClientMappedToAsyncClientOnEndpoint(
|
ProviderMetadata md = forApiOnEndpoint(IntegrationTestClient.class, "http://localhost");
|
||||||
IntegrationTestClient.class, IntegrationTestAsyncClient.class, "http://localhost");
|
|
||||||
|
|
||||||
Properties props = new Properties();
|
Properties props = new Properties();
|
||||||
props.putAll(md.getDefaultProperties());
|
props.putAll(md.getDefaultProperties());
|
||||||
|
@ -50,8 +48,7 @@ public class UpdateProviderMetadataFromPropertiesTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testProviderMetadataWithUpdatedIso3166CodesUpdatesAndRetainsAllDefaultPropertiesExceptIso3166Codes() {
|
public void testProviderMetadataWithUpdatedIso3166CodesUpdatesAndRetainsAllDefaultPropertiesExceptIso3166Codes() {
|
||||||
ProviderMetadata md = AnonymousProviderMetadata.forClientMappedToAsyncClientOnEndpoint(
|
ProviderMetadata md = forApiOnEndpoint(IntegrationTestClient.class, "http://localhost");
|
||||||
IntegrationTestClient.class, IntegrationTestAsyncClient.class, "http://localhost");
|
|
||||||
|
|
||||||
Properties props = new Properties();
|
Properties props = new Properties();
|
||||||
props.putAll(md.getDefaultProperties());
|
props.putAll(md.getDefaultProperties());
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.rest;
|
package org.jclouds.rest;
|
||||||
|
|
||||||
|
import static org.jclouds.providers.AnonymousProviderMetadata.forApiOnEndpoint;
|
||||||
import static org.jclouds.reflect.Reflection2.method;
|
import static org.jclouds.reflect.Reflection2.method;
|
||||||
|
|
||||||
import javax.ws.rs.POST;
|
import javax.ws.rs.POST;
|
||||||
|
@ -23,10 +24,8 @@ import javax.ws.rs.PathParam;
|
||||||
|
|
||||||
import org.jclouds.ContextBuilder;
|
import org.jclouds.ContextBuilder;
|
||||||
import org.jclouds.http.HttpRequest;
|
import org.jclouds.http.HttpRequest;
|
||||||
import org.jclouds.http.IntegrationTestAsyncClient;
|
|
||||||
import org.jclouds.http.IntegrationTestClient;
|
import org.jclouds.http.IntegrationTestClient;
|
||||||
import org.jclouds.predicates.validators.AllLowerCaseValidator;
|
import org.jclouds.predicates.validators.AllLowerCaseValidator;
|
||||||
import org.jclouds.providers.AnonymousProviderMetadata;
|
|
||||||
import org.jclouds.reflect.Invocation;
|
import org.jclouds.reflect.Invocation;
|
||||||
import org.jclouds.rest.annotations.ParamValidators;
|
import org.jclouds.rest.annotations.ParamValidators;
|
||||||
import org.jclouds.rest.internal.RestAnnotationProcessor;
|
import org.jclouds.rest.internal.RestAnnotationProcessor;
|
||||||
|
@ -109,10 +108,8 @@ public class InputParamValidatorTest {
|
||||||
|
|
||||||
@BeforeClass
|
@BeforeClass
|
||||||
void setupFactory() {
|
void setupFactory() {
|
||||||
injector = ContextBuilder
|
injector = ContextBuilder.newBuilder(forApiOnEndpoint(IntegrationTestClient.class, "http://localhost:9999"))
|
||||||
.newBuilder(
|
.buildInjector();
|
||||||
AnonymousProviderMetadata.forClientMappedToAsyncClientOnEndpoint(IntegrationTestClient.class, IntegrationTestAsyncClient.class,
|
|
||||||
"http://localhost:9999")).buildInjector();
|
|
||||||
restAnnotationProcessor = injector.getInstance(RestAnnotationProcessor.class);
|
restAnnotationProcessor = injector.getInstance(RestAnnotationProcessor.class);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,13 +20,13 @@ import static org.easymock.EasyMock.createMock;
|
||||||
import static org.easymock.EasyMock.expect;
|
import static org.easymock.EasyMock.expect;
|
||||||
import static org.easymock.EasyMock.replay;
|
import static org.easymock.EasyMock.replay;
|
||||||
import static org.easymock.EasyMock.verify;
|
import static org.easymock.EasyMock.verify;
|
||||||
import static org.jclouds.providers.AnonymousProviderMetadata.forClientMappedToAsyncClientOnEndpoint;
|
|
||||||
|
|
||||||
import java.io.Closeable;
|
import java.io.Closeable;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
import org.jclouds.ContextBuilder;
|
import org.jclouds.ContextBuilder;
|
||||||
import org.jclouds.concurrent.config.ExecutorServiceModule;
|
import org.jclouds.concurrent.config.ExecutorServiceModule;
|
||||||
|
import org.jclouds.providers.AnonymousProviderMetadata;
|
||||||
import org.jclouds.providers.ProviderMetadata;
|
import org.jclouds.providers.ProviderMetadata;
|
||||||
import org.testng.annotations.Test;
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
@ -45,11 +45,7 @@ public class ClosableApiTest {
|
||||||
interface DelegatingApi extends Closeable {
|
interface DelegatingApi extends Closeable {
|
||||||
}
|
}
|
||||||
|
|
||||||
interface DelegatingAsyncApi extends Closeable {
|
ProviderMetadata provider = AnonymousProviderMetadata.forApiOnEndpoint(DelegatingApi.class, "http://mock");
|
||||||
}
|
|
||||||
|
|
||||||
ProviderMetadata provider = forClientMappedToAsyncClientOnEndpoint(DelegatingApi.class, DelegatingAsyncApi.class,
|
|
||||||
"http://mock");
|
|
||||||
|
|
||||||
public void testApiClosesExecutorServiceOnClose() throws IOException {
|
public void testApiClosesExecutorServiceOnClose() throws IOException {
|
||||||
ListeningExecutorService executor = createMock(ListeningExecutorService.class);
|
ListeningExecutorService executor = createMock(ListeningExecutorService.class);
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.rest.annotationparsing;
|
package org.jclouds.rest.annotationparsing;
|
||||||
|
|
||||||
import static org.jclouds.providers.AnonymousProviderMetadata.forClientMappedToAsyncClientOnEndpoint;
|
import static org.jclouds.providers.AnonymousProviderMetadata.forApiOnEndpoint;
|
||||||
import static org.testng.Assert.assertTrue;
|
import static org.testng.Assert.assertTrue;
|
||||||
|
|
||||||
import javax.ws.rs.FormParam;
|
import javax.ws.rs.FormParam;
|
||||||
|
@ -29,17 +29,15 @@ import org.jclouds.Fallbacks.FalseOnNotFoundOr404;
|
||||||
import org.jclouds.http.HttpRequest;
|
import org.jclouds.http.HttpRequest;
|
||||||
import org.jclouds.http.HttpResponse;
|
import org.jclouds.http.HttpResponse;
|
||||||
import org.jclouds.providers.ProviderMetadata;
|
import org.jclouds.providers.ProviderMetadata;
|
||||||
import org.jclouds.rest.ConfiguresRestClient;
|
import org.jclouds.rest.ConfiguresHttpApi;
|
||||||
import org.jclouds.rest.annotations.Delegate;
|
import org.jclouds.rest.annotations.Delegate;
|
||||||
import org.jclouds.rest.annotations.Fallback;
|
import org.jclouds.rest.annotations.Fallback;
|
||||||
import org.jclouds.rest.annotations.Payload;
|
import org.jclouds.rest.annotations.Payload;
|
||||||
import org.jclouds.rest.annotations.PayloadParam;
|
import org.jclouds.rest.annotations.PayloadParam;
|
||||||
import org.jclouds.rest.config.RestClientModule;
|
import org.jclouds.rest.config.HttpApiModule;
|
||||||
import org.jclouds.rest.internal.BaseRestApiExpectTest;
|
import org.jclouds.rest.internal.BaseRestApiExpectTest;
|
||||||
import org.testng.annotations.Test;
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableMap;
|
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
|
||||||
import com.google.inject.Module;
|
import com.google.inject.Module;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -57,35 +55,18 @@ public class DelegateAnnotationExpectTest extends BaseRestApiExpectTest<Delegate
|
||||||
DiskApi getDiskApiForProject(@PayloadParam("project") @PathParam("project") String projectName);
|
DiskApi getDiskApiForProject(@PayloadParam("project") @PathParam("project") String projectName);
|
||||||
}
|
}
|
||||||
|
|
||||||
interface DelegatingAsyncApi {
|
|
||||||
@Delegate
|
|
||||||
DiskAsyncApi getDiskApiForProjectForm(@FormParam("project") String projectName);
|
|
||||||
|
|
||||||
@Delegate
|
|
||||||
@Path("/projects/{project}")
|
|
||||||
DiskAsyncApi getDiskApiForProject(@PayloadParam("project") @PathParam("project") String projectName);
|
|
||||||
}
|
|
||||||
|
|
||||||
interface DiskApi {
|
interface DiskApi {
|
||||||
void form();
|
|
||||||
|
|
||||||
void syncAll();
|
|
||||||
|
|
||||||
boolean exists(@PathParam("disk") String diskName);
|
|
||||||
}
|
|
||||||
|
|
||||||
interface DiskAsyncApi {
|
|
||||||
@POST
|
@POST
|
||||||
ListenableFuture<Void> form();
|
void form();
|
||||||
|
|
||||||
@POST
|
@POST
|
||||||
@Payload("<Sync>{project}</Sync>")
|
@Payload("<Sync>{project}</Sync>")
|
||||||
ListenableFuture<Void> syncAll();
|
void syncAll();
|
||||||
|
|
||||||
@HEAD
|
@HEAD
|
||||||
@Path("/disks/{disk}")
|
@Path("/disks/{disk}")
|
||||||
@Fallback(FalseOnNotFoundOr404.class)
|
@Fallback(FalseOnNotFoundOr404.class)
|
||||||
ListenableFuture<Boolean> exists(@PathParam("disk") String diskName);
|
boolean exists(@PathParam("disk") String diskName);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testDelegatingCallTakesIntoConsiderationAndCalleeFormParam() {
|
public void testDelegatingCallTakesIntoConsiderationAndCalleeFormParam() {
|
||||||
|
@ -121,22 +102,16 @@ public class DelegateAnnotationExpectTest extends BaseRestApiExpectTest<Delegate
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ProviderMetadata createProviderMetadata() {
|
public ProviderMetadata createProviderMetadata() {
|
||||||
return forClientMappedToAsyncClientOnEndpoint(DelegatingApi.class, DelegatingAsyncApi.class, "http://mock");
|
return forApiOnEndpoint(DelegatingApi.class, "http://mock");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Module createModule() {
|
protected Module createModule() {
|
||||||
return new DelegatingRestClientModule();
|
return new DelegatingHttpApiModule();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ConfiguresRestClient
|
@ConfiguresHttpApi
|
||||||
static class DelegatingRestClientModule extends RestClientModule<DelegatingApi, DelegatingAsyncApi> {
|
static class DelegatingHttpApiModule extends HttpApiModule<DelegatingApi> {
|
||||||
|
|
||||||
public DelegatingRestClientModule() {
|
|
||||||
// right now, we have to define the delegates by hand as opposed to
|
|
||||||
// reflection looking for coordinated annotations
|
|
||||||
super(ImmutableMap.<Class<?>, Class<?>> of(DiskApi.class, DiskAsyncApi.class));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.rest.annotationparsing;
|
package org.jclouds.rest.annotationparsing;
|
||||||
|
|
||||||
import static org.jclouds.providers.AnonymousProviderMetadata.forClientMappedToAsyncClientOnEndpoint;
|
import static org.jclouds.providers.AnonymousProviderMetadata.forApiOnEndpoint;
|
||||||
import static org.testng.Assert.assertEquals;
|
import static org.testng.Assert.assertEquals;
|
||||||
import static org.testng.Assert.assertTrue;
|
import static org.testng.Assert.assertTrue;
|
||||||
|
|
||||||
|
@ -38,7 +38,6 @@ import org.testng.annotations.Test;
|
||||||
|
|
||||||
import com.google.common.base.Function;
|
import com.google.common.base.Function;
|
||||||
import com.google.common.base.Functions;
|
import com.google.common.base.Functions;
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests the use of the {@link JAXBResponseParser} annotation.
|
* Tests the use of the {@link JAXBResponseParser} annotation.
|
||||||
|
@ -67,36 +66,26 @@ public class JAXBResponseParserAnnotationExpectTest extends
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface TestJAXBApi extends Closeable {
|
public interface TestJAXBApi extends Closeable {
|
||||||
TestJAXBDomain jaxbGetWithAnnotation();
|
|
||||||
|
|
||||||
Object jaxbGetWithAnnotationAndCustomClass();
|
|
||||||
|
|
||||||
TestJAXBDomain jaxbGetWithAcceptHeader();
|
|
||||||
|
|
||||||
String jaxbGetWithTransformer();
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface TestJAXBAsyncApi extends Closeable {
|
|
||||||
@GET
|
@GET
|
||||||
@Path("/jaxb/annotation")
|
@Path("/jaxb/annotation")
|
||||||
@JAXBResponseParser
|
@JAXBResponseParser
|
||||||
ListenableFuture<TestJAXBDomain> jaxbGetWithAnnotation();
|
TestJAXBDomain jaxbGetWithAnnotation();
|
||||||
|
|
||||||
@GET
|
@GET
|
||||||
@Path("/jaxb/custom")
|
@Path("/jaxb/custom")
|
||||||
@JAXBResponseParser(TestJAXBDomain.class)
|
@JAXBResponseParser(TestJAXBDomain.class)
|
||||||
ListenableFuture<Object> jaxbGetWithAnnotationAndCustomClass();
|
Object jaxbGetWithAnnotationAndCustomClass();
|
||||||
|
|
||||||
@GET
|
@GET
|
||||||
@Path("/jaxb/header")
|
@Path("/jaxb/header")
|
||||||
@Consumes(MediaType.APPLICATION_XML)
|
@Consumes(MediaType.APPLICATION_XML)
|
||||||
ListenableFuture<TestJAXBDomain> jaxbGetWithAcceptHeader();
|
TestJAXBDomain jaxbGetWithAcceptHeader();
|
||||||
|
|
||||||
@GET
|
@GET
|
||||||
@Path("/jaxb/transformer")
|
@Path("/jaxb/transformer")
|
||||||
@JAXBResponseParser(TestJAXBDomain.class)
|
@JAXBResponseParser(TestJAXBDomain.class)
|
||||||
@Transform(ToString.class)
|
@Transform(ToString.class)
|
||||||
ListenableFuture<String> jaxbGetWithTransformer();
|
String jaxbGetWithTransformer();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class ToString implements Function<Object, String> {
|
private static class ToString implements Function<Object, String> {
|
||||||
|
@ -150,7 +139,6 @@ public class JAXBResponseParserAnnotationExpectTest extends
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ProviderMetadata createProviderMetadata() {
|
public ProviderMetadata createProviderMetadata() {
|
||||||
return forClientMappedToAsyncClientOnEndpoint(TestJAXBApi.class, TestJAXBAsyncApi.class, "http://mock");
|
return forApiOnEndpoint(TestJAXBApi.class, "http://mock");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,6 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.rest.annotationparsing;
|
package org.jclouds.rest.annotationparsing;
|
||||||
|
|
||||||
import static org.jclouds.providers.AnonymousProviderMetadata.forClientMappedToAsyncClientOnEndpoint;
|
|
||||||
import static org.testng.Assert.assertEquals;
|
import static org.testng.Assert.assertEquals;
|
||||||
|
|
||||||
import java.io.Closeable;
|
import java.io.Closeable;
|
||||||
|
@ -27,10 +26,11 @@ import javax.inject.Named;
|
||||||
|
|
||||||
import org.jclouds.http.HttpRequest;
|
import org.jclouds.http.HttpRequest;
|
||||||
import org.jclouds.http.HttpResponse;
|
import org.jclouds.http.HttpResponse;
|
||||||
|
import org.jclouds.providers.AnonymousProviderMetadata;
|
||||||
import org.jclouds.providers.ProviderMetadata;
|
import org.jclouds.providers.ProviderMetadata;
|
||||||
import org.jclouds.rest.AuthorizationException;
|
import org.jclouds.rest.AuthorizationException;
|
||||||
import org.jclouds.rest.ConfiguresRestClient;
|
import org.jclouds.rest.ConfiguresHttpApi;
|
||||||
import org.jclouds.rest.config.RestClientModule;
|
import org.jclouds.rest.config.HttpApiModule;
|
||||||
import org.jclouds.rest.internal.BaseRestApiExpectTest;
|
import org.jclouds.rest.internal.BaseRestApiExpectTest;
|
||||||
import org.testng.annotations.Test;
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
@ -64,23 +64,6 @@ public class ProvidesAnnotationExpectTest extends BaseRestApiExpectTest<Provides
|
||||||
Set<String> noSuchElementException();
|
Set<String> noSuchElementException();
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ProvidingAsyncApi extends Closeable {
|
|
||||||
@Provides
|
|
||||||
Set<String> set();
|
|
||||||
|
|
||||||
@Named("bar")
|
|
||||||
@Provides
|
|
||||||
Set<String> foo();
|
|
||||||
|
|
||||||
@Named("exception")
|
|
||||||
@Provides
|
|
||||||
Set<String> exception();
|
|
||||||
|
|
||||||
@Named("NoSuchElementException")
|
|
||||||
@Provides
|
|
||||||
Set<String> noSuchElementException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testProvidesWithGeneric() {
|
public void testProvidesWithGeneric() {
|
||||||
ProvidingApi client = requestsSendResponses(ImmutableMap.<HttpRequest, HttpResponse> of());
|
ProvidingApi client = requestsSendResponses(ImmutableMap.<HttpRequest, HttpResponse> of());
|
||||||
|
@ -110,16 +93,16 @@ public class ProvidesAnnotationExpectTest extends BaseRestApiExpectTest<Provides
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ProviderMetadata createProviderMetadata() {
|
public ProviderMetadata createProviderMetadata() {
|
||||||
return forClientMappedToAsyncClientOnEndpoint(ProvidingApi.class, ProvidingAsyncApi.class, "http://mock");
|
return AnonymousProviderMetadata.forApiOnEndpoint(ProvidingApi.class, "http://mock");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Module createModule() {
|
protected Module createModule() {
|
||||||
return new ProvidingRestClientModule();
|
return new ProvidingHttpApiModule();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ConfiguresRestClient
|
@ConfiguresHttpApi
|
||||||
static class ProvidingRestClientModule extends RestClientModule<ProvidingApi, ProvidingAsyncApi> {
|
static class ProvidingHttpApiModule extends HttpApiModule<ProvidingApi> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void configure() {
|
protected void configure() {
|
||||||
|
|
|
@ -1,114 +0,0 @@
|
||||||
/*
|
|
||||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
||||||
* contributor license agreements. See the NOTICE file distributed with
|
|
||||||
* this work for additional information regarding copyright ownership.
|
|
||||||
* The ASF licenses this file to You 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.config;
|
|
||||||
|
|
||||||
import static com.google.common.base.Predicates.not;
|
|
||||||
import static com.google.common.collect.Maps.filterEntries;
|
|
||||||
import static org.testng.Assert.assertEquals;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Map.Entry;
|
|
||||||
|
|
||||||
import org.jclouds.rest.HttpAsyncClient;
|
|
||||||
import org.jclouds.rest.HttpClient;
|
|
||||||
import org.testng.annotations.Test;
|
|
||||||
|
|
||||||
import com.google.common.base.Predicate;
|
|
||||||
import com.google.common.cache.Cache;
|
|
||||||
import com.google.common.cache.CacheBuilder;
|
|
||||||
import com.google.common.collect.ImmutableMap;
|
|
||||||
import com.google.common.reflect.Invokable;
|
|
||||||
import com.google.common.reflect.TypeToken;
|
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
|
||||||
|
|
||||||
@Test(groups = "unit")
|
|
||||||
public class MappedHttpInvocationModuleTest {
|
|
||||||
interface Sync {
|
|
||||||
String get();
|
|
||||||
}
|
|
||||||
|
|
||||||
private interface Async {
|
|
||||||
ListenableFuture<String> get();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testPutInvokablesWhenInterfacesMatch() {
|
|
||||||
Cache<Invokable<?, ?>, Invokable<?, ?>> cache = CacheBuilder.newBuilder().build();
|
|
||||||
SyncToAsyncHttpInvocationModule.putInvokables(Sync.class, Async.class, cache);
|
|
||||||
|
|
||||||
assertEquals(cache.size(), 1);
|
|
||||||
|
|
||||||
Invokable<?, ?> sync = cache.asMap().keySet().iterator().next();
|
|
||||||
assertEquals(sync.getOwnerType().getRawType(), Sync.class);
|
|
||||||
assertEquals(sync.getName(), "get");
|
|
||||||
assertEquals(sync.getReturnType(), TypeToken.of(String.class));
|
|
||||||
|
|
||||||
Invokable<?, ?> async = cache.getIfPresent(sync);
|
|
||||||
assertEquals(async.getOwnerType().getRawType(), Async.class);
|
|
||||||
assertEquals(async.getName(), "get");
|
|
||||||
assertEquals(async.getReturnType(), new TypeToken<ListenableFuture<String>>() {
|
|
||||||
private static final long serialVersionUID = 1L;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private interface AsyncWithException {
|
|
||||||
ListenableFuture<String> get() throws IOException;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(expectedExceptions = IllegalArgumentException.class, expectedExceptionsMessageRegExp = ".* has different typed exceptions than target .*")
|
|
||||||
public void testPutInvokablesWhenInterfacesMatchExceptExceptions() {
|
|
||||||
Cache<Invokable<?, ?>, Invokable<?, ?>> cache = CacheBuilder.newBuilder().build();
|
|
||||||
SyncToAsyncHttpInvocationModule.putInvokables(Sync.class, AsyncWithException.class, cache);
|
|
||||||
}
|
|
||||||
|
|
||||||
private interface AsyncWithMisnamedMethod {
|
|
||||||
ListenableFuture<String> got();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(expectedExceptions = IllegalArgumentException.class, expectedExceptionsMessageRegExp = "no such method .*")
|
|
||||||
public void testPutInvokablesWhenTargetMethodNotFound() {
|
|
||||||
Cache<Invokable<?, ?>, Invokable<?, ?>> cache = CacheBuilder.newBuilder().build();
|
|
||||||
SyncToAsyncHttpInvocationModule.putInvokables(Sync.class, AsyncWithMisnamedMethod.class, cache);
|
|
||||||
}
|
|
||||||
|
|
||||||
static final Predicate<Entry<Invokable<?, ?>, Invokable<?, ?>>> isHttpInvokable = new Predicate<Map.Entry<Invokable<?, ?>, Invokable<?, ?>>>() {
|
|
||||||
public boolean apply(Map.Entry<Invokable<?, ?>, Invokable<?, ?>> in) {
|
|
||||||
return in.getKey().getOwnerType().getRawType().equals(HttpClient.class)
|
|
||||||
&& in.getValue().getOwnerType().getRawType().equals(HttpAsyncClient.class);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
public void testSeedKnownSync2AsyncIncludesHttpClientByDefault() {
|
|
||||||
Map<Invokable<?, ?>, Invokable<?, ?>> cache = SyncToAsyncHttpInvocationModule.seedKnownSync2AsyncInvokables(
|
|
||||||
ImmutableMap.<Class<?>, Class<?>> of()).asMap();
|
|
||||||
|
|
||||||
assertEquals(cache.size(), 6);
|
|
||||||
assertEquals(filterEntries(cache, isHttpInvokable), cache);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testSeedKnownSync2AsyncInvokablesInterfacesMatch() {
|
|
||||||
Map<Invokable<?, ?>, Invokable<?, ?>> cache = SyncToAsyncHttpInvocationModule.seedKnownSync2AsyncInvokables(
|
|
||||||
ImmutableMap.<Class<?>, Class<?>> of(Sync.class, Async.class)).asMap();
|
|
||||||
|
|
||||||
assertEquals(cache.size(), 7);
|
|
||||||
|
|
||||||
cache = filterEntries(cache, not(isHttpInvokable));
|
|
||||||
|
|
||||||
assertEquals(cache.size(), 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,25 +0,0 @@
|
||||||
/*
|
|
||||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
||||||
* contributor license agreements. See the NOTICE file distributed with
|
|
||||||
* this work for additional information regarding copyright ownership.
|
|
||||||
* The ASF licenses this file to You 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.internal;
|
|
||||||
|
|
||||||
import org.testng.annotations.Test;
|
|
||||||
|
|
||||||
@Test(groups = "unit")
|
|
||||||
// TODO: remove once abiquo no longer uses this.
|
|
||||||
public abstract class BaseAsyncClientTest<T> extends BaseRestAnnotationProcessingTest<T> {
|
|
||||||
|
|
||||||
}
|
|
|
@ -557,8 +557,6 @@ public abstract class BaseRestApiExpectTest<S> {
|
||||||
ApiMetadata am = builder.getApiMetadata();
|
ApiMetadata am = builder.getApiMetadata();
|
||||||
if (am instanceof HttpApiMetadata) {
|
if (am instanceof HttpApiMetadata) {
|
||||||
this.api = HttpApiMetadata.class.cast(am).getApi();
|
this.api = HttpApiMetadata.class.cast(am).getApi();
|
||||||
} else if (am instanceof org.jclouds.rest.RestApiMetadata) {
|
|
||||||
this.api = org.jclouds.rest.RestApiMetadata.class.cast(am).getApi();
|
|
||||||
} else {
|
} else {
|
||||||
throw new UnsupportedOperationException("unsupported base type: " + am);
|
throw new UnsupportedOperationException("unsupported base type: " + am);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,46 +0,0 @@
|
||||||
/*
|
|
||||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
||||||
* contributor license agreements. See the NOTICE file distributed with
|
|
||||||
* this work for additional information regarding copyright ownership.
|
|
||||||
* The ASF licenses this file to You 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.internal;
|
|
||||||
import static org.jclouds.reflect.Reflection2.typeToken;
|
|
||||||
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import org.jclouds.View;
|
|
||||||
import org.jclouds.apis.ApiMetadata;
|
|
||||||
import org.jclouds.apis.Apis;
|
|
||||||
import org.jclouds.apis.internal.BaseApiMetadataTest;
|
|
||||||
import org.jclouds.rest.RestApiMetadata;
|
|
||||||
import org.jclouds.rest.RestContext;
|
|
||||||
import org.testng.annotations.Test;
|
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableSet;
|
|
||||||
import com.google.common.reflect.TypeToken;
|
|
||||||
|
|
||||||
@Test(groups = "unit")
|
|
||||||
public abstract class BaseRestApiMetadataTest extends BaseApiMetadataTest {
|
|
||||||
|
|
||||||
public BaseRestApiMetadataTest(RestApiMetadata toTest, Set<TypeToken<? extends View>> views) {
|
|
||||||
super(toTest, views);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testContextAssignableFromRestContext() {
|
|
||||||
Set<ApiMetadata> all = ImmutableSet.copyOf(Apis.contextAssignableFrom(typeToken(RestContext.class)));
|
|
||||||
assert all.contains(toTest) : String.format("%s not found in %s", toTest, all);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,171 +0,0 @@
|
||||||
/*
|
|
||||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
||||||
* contributor license agreements. See the NOTICE file distributed with
|
|
||||||
* this work for additional information regarding copyright ownership.
|
|
||||||
* The ASF licenses this file to You 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.internal;
|
|
||||||
|
|
||||||
import static org.easymock.EasyMock.anyObject;
|
|
||||||
import static org.easymock.EasyMock.createMock;
|
|
||||||
import static org.easymock.EasyMock.eq;
|
|
||||||
import static org.easymock.EasyMock.expect;
|
|
||||||
import static org.easymock.EasyMock.replay;
|
|
||||||
import static org.easymock.EasyMock.verify;
|
|
||||||
import static org.jclouds.reflect.Reflection2.method;
|
|
||||||
import static org.testng.Assert.assertEquals;
|
|
||||||
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
import javax.inject.Named;
|
|
||||||
|
|
||||||
import org.jclouds.http.HttpCommand;
|
|
||||||
import org.jclouds.http.HttpCommandExecutorService;
|
|
||||||
import org.jclouds.http.HttpRequest;
|
|
||||||
import org.jclouds.http.HttpResponse;
|
|
||||||
import org.jclouds.reflect.Invocation;
|
|
||||||
import org.jclouds.rest.config.InvocationConfig;
|
|
||||||
import org.jclouds.rest.internal.InvokeSyncToAsyncHttpMethod.InvokeAndTransform;
|
|
||||||
import org.testng.annotations.AfterMethod;
|
|
||||||
import org.testng.annotations.BeforeClass;
|
|
||||||
import org.testng.annotations.BeforeMethod;
|
|
||||||
import org.testng.annotations.Test;
|
|
||||||
|
|
||||||
import com.google.common.base.Function;
|
|
||||||
import com.google.common.base.Functions;
|
|
||||||
import com.google.common.base.Optional;
|
|
||||||
import com.google.common.collect.ImmutableList;
|
|
||||||
import com.google.common.collect.ImmutableMap;
|
|
||||||
import com.google.common.util.concurrent.Futures;
|
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
|
||||||
import com.google.common.util.concurrent.ListeningExecutorService;
|
|
||||||
import com.google.common.util.concurrent.MoreExecutors;
|
|
||||||
import com.google.common.util.concurrent.TimeLimiter;
|
|
||||||
|
|
||||||
@Test(groups = "unit", singleThreaded = true)
|
|
||||||
public class InvokeMappedHttpMethodTest {
|
|
||||||
|
|
||||||
public interface ThingApi {
|
|
||||||
HttpResponse get();
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface ThingAsyncApi {
|
|
||||||
@Named("ns:get")
|
|
||||||
ListenableFuture<HttpResponse> get();
|
|
||||||
}
|
|
||||||
|
|
||||||
private Invocation get;
|
|
||||||
private Invocation asyncGet;
|
|
||||||
private Function<Invocation, Invocation> sync2async;
|
|
||||||
private HttpRequest getRequest = HttpRequest.builder().method("GET").endpoint("http://get").build();
|
|
||||||
private HttpCommand getCommand = new HttpCommand(getRequest);
|
|
||||||
private Function<Invocation, HttpRequest> toRequest;
|
|
||||||
|
|
||||||
@BeforeClass
|
|
||||||
void setupInvocations() throws SecurityException, NoSuchMethodException {
|
|
||||||
get = Invocation.create(method(ThingApi.class, "get"), ImmutableList.of());
|
|
||||||
asyncGet = Invocation.create(method(ThingAsyncApi.class, "get"), ImmutableList.of());
|
|
||||||
sync2async = Functions.forMap(ImmutableMap.of(get, asyncGet));
|
|
||||||
toRequest = Functions.forMap(ImmutableMap.of(asyncGet, getRequest));
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
private Function<HttpRequest, Function<HttpResponse, ?>> transformerForRequest = Function.class.cast(Functions
|
|
||||||
.constant(Functions.identity()));
|
|
||||||
private ListeningExecutorService userThreads = MoreExecutors.sameThreadExecutor();
|
|
||||||
|
|
||||||
private HttpResponse response = HttpResponse.builder().statusCode(200).payload("foo").build();
|
|
||||||
private HttpCommandExecutorService http;
|
|
||||||
private TimeLimiter timeLimiter;
|
|
||||||
@SuppressWarnings("rawtypes")
|
|
||||||
private org.jclouds.Fallback fallback;
|
|
||||||
private InvocationConfig config;
|
|
||||||
private InvokeSyncToAsyncHttpMethod invokeHttpMethod;
|
|
||||||
|
|
||||||
private ListenableFuture<HttpResponse> future;
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
@BeforeMethod
|
|
||||||
void createMocks() {
|
|
||||||
http = createMock(HttpCommandExecutorService.class);
|
|
||||||
timeLimiter = createMock(TimeLimiter.class);
|
|
||||||
fallback = createMock(org.jclouds.Fallback.class);
|
|
||||||
config = createMock(InvocationConfig.class);
|
|
||||||
future = createMock(ListenableFuture.class);
|
|
||||||
invokeHttpMethod = new InvokeSyncToAsyncHttpMethod(sync2async, toRequest, http, transformerForRequest, timeLimiter, config,
|
|
||||||
userThreads);
|
|
||||||
expect(config.getCommandName(asyncGet)).andReturn("ns:get");
|
|
||||||
expect(config.getFallback(asyncGet)).andReturn(fallback);
|
|
||||||
}
|
|
||||||
|
|
||||||
@AfterMethod
|
|
||||||
void verifyMocks() {
|
|
||||||
verify(http, timeLimiter, fallback, config, future);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testMethodWithTimeoutRunsTimeLimiter() throws Exception {
|
|
||||||
expect(config.getTimeoutNanos(asyncGet)).andReturn(Optional.of(250000000l));
|
|
||||||
InvokeAndTransform invoke = invokeHttpMethod.new InvokeAndTransform("ns:get", getCommand);
|
|
||||||
expect(timeLimiter.callWithTimeout(invoke, 250000000, TimeUnit.NANOSECONDS, true)).andReturn(response);
|
|
||||||
replay(http, timeLimiter, fallback, config, future);
|
|
||||||
invokeHttpMethod.apply(get);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testMethodWithNoTimeoutCallGetDirectly() throws Exception {
|
|
||||||
expect(config.getTimeoutNanos(asyncGet)).andReturn(Optional.<Long> absent());
|
|
||||||
expect(http.invoke(new HttpCommand(getRequest))).andReturn(response);
|
|
||||||
replay(http, timeLimiter, fallback, config, future);
|
|
||||||
invokeHttpMethod.apply(get);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testAsyncMethodSubmitsRequest() throws Exception {
|
|
||||||
expect(http.submit(new HttpCommand(getRequest))).andReturn(future);
|
|
||||||
future.addListener(anyObject(Runnable.class), eq(userThreads));
|
|
||||||
replay(http, timeLimiter, fallback, config, future);
|
|
||||||
invokeHttpMethod.apply(asyncGet);
|
|
||||||
}
|
|
||||||
|
|
||||||
private HttpResponse fallbackResponse = HttpResponse.builder().statusCode(200).payload("bar").build();
|
|
||||||
|
|
||||||
public void testDirectCallRunsFallbackCreateOrPropagate() throws Exception {
|
|
||||||
IllegalStateException exception = new IllegalStateException();
|
|
||||||
expect(config.getTimeoutNanos(asyncGet)).andReturn(Optional.<Long> absent());
|
|
||||||
expect(http.invoke(new HttpCommand(getRequest))).andThrow(exception);
|
|
||||||
expect(fallback.createOrPropagate(exception)).andReturn(fallbackResponse);
|
|
||||||
replay(http, timeLimiter, fallback, config, future);
|
|
||||||
assertEquals(invokeHttpMethod.apply(get), fallbackResponse);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testTimeLimitedRunsFallbackCreateOrPropagate() throws Exception {
|
|
||||||
IllegalStateException exception = new IllegalStateException();
|
|
||||||
expect(config.getTimeoutNanos(asyncGet)).andReturn(Optional.of(250000000l));
|
|
||||||
InvokeAndTransform invoke = invokeHttpMethod.new InvokeAndTransform("ns:get", getCommand);
|
|
||||||
expect(timeLimiter.callWithTimeout(invoke, 250000000, TimeUnit.NANOSECONDS, true)).andThrow(exception);
|
|
||||||
expect(fallback.createOrPropagate(exception)).andReturn(fallbackResponse);
|
|
||||||
replay(http, timeLimiter, fallback, config, future);
|
|
||||||
assertEquals(invokeHttpMethod.apply(get), fallbackResponse);
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public void testSubmitRunsFallbackCreateOnGet() throws Exception {
|
|
||||||
IllegalStateException exception = new IllegalStateException();
|
|
||||||
expect(http.submit(new HttpCommand(getRequest))).andReturn(
|
|
||||||
Futures.<HttpResponse> immediateFailedFuture(exception));
|
|
||||||
expect(fallback.create(exception)).andReturn(Futures.<HttpResponse> immediateFuture(fallbackResponse));
|
|
||||||
// not using the field, as you can see above we are making an immediate
|
|
||||||
// failed future instead.
|
|
||||||
future = createMock(ListenableFuture.class);
|
|
||||||
replay(http, timeLimiter, fallback, config, future);
|
|
||||||
assertEquals(ListenableFuture.class.cast(invokeHttpMethod.apply(asyncGet)).get(), fallbackResponse);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -18,8 +18,11 @@ package org.jclouds.rest.internal;
|
||||||
|
|
||||||
import static com.google.common.base.Charsets.UTF_8;
|
import static com.google.common.base.Charsets.UTF_8;
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
|
||||||
|
import static javax.ws.rs.core.MediaType.APPLICATION_XML;
|
||||||
import static org.jclouds.io.Payloads.newInputStreamPayload;
|
import static org.jclouds.io.Payloads.newInputStreamPayload;
|
||||||
import static org.jclouds.io.Payloads.newStringPayload;
|
import static org.jclouds.io.Payloads.newStringPayload;
|
||||||
|
import static org.jclouds.providers.AnonymousProviderMetadata.forApiOnEndpoint;
|
||||||
import static org.jclouds.reflect.Reflection2.method;
|
import static org.jclouds.reflect.Reflection2.method;
|
||||||
import static org.testng.Assert.assertEquals;
|
import static org.testng.Assert.assertEquals;
|
||||||
import static org.testng.Assert.assertNull;
|
import static org.testng.Assert.assertNull;
|
||||||
|
@ -38,6 +41,7 @@ import java.lang.annotation.Target;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.net.URLEncoder;
|
import java.net.URLEncoder;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
@ -45,6 +49,7 @@ import java.util.Map;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
|
|
||||||
import javax.inject.Named;
|
import javax.inject.Named;
|
||||||
import javax.inject.Qualifier;
|
import javax.inject.Qualifier;
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
|
@ -90,10 +95,8 @@ import org.jclouds.io.PayloadEnclosing;
|
||||||
import org.jclouds.io.Payloads;
|
import org.jclouds.io.Payloads;
|
||||||
import org.jclouds.javax.annotation.Nullable;
|
import org.jclouds.javax.annotation.Nullable;
|
||||||
import org.jclouds.logging.config.NullLoggingModule;
|
import org.jclouds.logging.config.NullLoggingModule;
|
||||||
import org.jclouds.providers.AnonymousProviderMetadata;
|
|
||||||
import org.jclouds.reflect.Invocation;
|
import org.jclouds.reflect.Invocation;
|
||||||
import org.jclouds.reflect.InvocationSuccess;
|
import org.jclouds.rest.ConfiguresHttpApi;
|
||||||
import org.jclouds.rest.ConfiguresRestClient;
|
|
||||||
import org.jclouds.rest.InvocationContext;
|
import org.jclouds.rest.InvocationContext;
|
||||||
import org.jclouds.rest.annotations.BinderParam;
|
import org.jclouds.rest.annotations.BinderParam;
|
||||||
import org.jclouds.rest.annotations.Delegate;
|
import org.jclouds.rest.annotations.Delegate;
|
||||||
|
@ -119,8 +122,7 @@ import org.jclouds.rest.annotations.WrapWith;
|
||||||
import org.jclouds.rest.binders.BindAsHostPrefix;
|
import org.jclouds.rest.binders.BindAsHostPrefix;
|
||||||
import org.jclouds.rest.binders.BindToJsonPayload;
|
import org.jclouds.rest.binders.BindToJsonPayload;
|
||||||
import org.jclouds.rest.binders.BindToStringPayload;
|
import org.jclouds.rest.binders.BindToStringPayload;
|
||||||
import org.jclouds.rest.config.RestClientModule;
|
import org.jclouds.rest.config.HttpApiModule;
|
||||||
import org.jclouds.rest.functions.ImplicitOptionalConverter;
|
|
||||||
import org.jclouds.util.Strings2;
|
import org.jclouds.util.Strings2;
|
||||||
import org.testng.Assert;
|
import org.testng.Assert;
|
||||||
import org.testng.annotations.BeforeClass;
|
import org.testng.annotations.BeforeClass;
|
||||||
|
@ -144,7 +146,6 @@ import com.google.common.io.ByteSource;
|
||||||
import com.google.common.io.Files;
|
import com.google.common.io.Files;
|
||||||
import com.google.common.net.HttpHeaders;
|
import com.google.common.net.HttpHeaders;
|
||||||
import com.google.common.reflect.Invokable;
|
import com.google.common.reflect.Invokable;
|
||||||
import com.google.common.util.concurrent.Futures;
|
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
import com.google.inject.AbstractModule;
|
import com.google.inject.AbstractModule;
|
||||||
import com.google.inject.ConfigurationException;
|
import com.google.inject.ConfigurationException;
|
||||||
|
@ -152,19 +153,12 @@ import com.google.inject.Injector;
|
||||||
import com.google.inject.Module;
|
import com.google.inject.Module;
|
||||||
import com.google.inject.Provides;
|
import com.google.inject.Provides;
|
||||||
import com.google.inject.TypeLiteral;
|
import com.google.inject.TypeLiteral;
|
||||||
/**
|
|
||||||
* Tests behavior of {@code RestAnnotationProcessor}
|
|
||||||
*/
|
|
||||||
// NOTE:without testName, this will not call @Before* and fail w/NPE during
|
|
||||||
// surefire
|
|
||||||
@Test(groups = "unit", testName = "RestAnnotationProcessorTest")
|
@Test(groups = "unit", testName = "RestAnnotationProcessorTest")
|
||||||
public class RestAnnotationProcessorTest extends BaseRestApiTest {
|
public class RestAnnotationProcessorTest extends BaseRestApiTest {
|
||||||
|
|
||||||
@ConfiguresRestClient
|
@ConfiguresHttpApi
|
||||||
protected static class CallerModule extends RestClientModule<Caller, AsyncCaller> {
|
protected static class CallerModule extends HttpApiModule<Caller> {
|
||||||
CallerModule() {
|
|
||||||
super(ImmutableMap.<Class<?>, Class<?>> of(Callee.class, AsyncCallee.class, Callee2.class, AsyncCallee2.class));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void configure() {
|
protected void configure() {
|
||||||
|
@ -176,39 +170,37 @@ public class RestAnnotationProcessorTest extends BaseRestApiTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Path("/client/{jclouds.api-version}")
|
@Path("/client/{jclouds.api-version}")
|
||||||
public interface AsyncCallee extends Closeable {
|
public interface Callee extends Closeable {
|
||||||
@GET
|
@GET
|
||||||
@Path("/{path}")
|
@Path("/{path}")
|
||||||
ListenableFuture<Void> onePath(@PathParam("path") String path);
|
void onePath(@PathParam("path") String path);
|
||||||
|
|
||||||
@POST
|
@POST
|
||||||
ListenableFuture<Void> testWithoutProducesAndConsumes();
|
void testWithoutProducesAndConsumes();
|
||||||
|
|
||||||
@POST
|
@POST
|
||||||
@Produces(MediaType.APPLICATION_XML)
|
@Produces(APPLICATION_XML)
|
||||||
@Consumes(MediaType.APPLICATION_XML)
|
@Consumes(APPLICATION_XML)
|
||||||
ListenableFuture<Void> testProducesAndConsumesOnMethod();
|
void testProducesAndConsumesOnMethod();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Path("/client/{jclouds.api-version}")
|
@Path("/client/{jclouds.api-version}")
|
||||||
@Produces(MediaType.APPLICATION_XML)
|
@Produces(APPLICATION_XML)
|
||||||
@Consumes(MediaType.APPLICATION_XML)
|
@Consumes(APPLICATION_XML)
|
||||||
public interface AsyncCalleeWithProducesAndConsumesOnClass extends Closeable {
|
public interface CalleeWithProducesAndConsumesOnClass extends Closeable {
|
||||||
@POST
|
@POST
|
||||||
ListenableFuture<Void> testProducesAndConsumesOnClass();
|
void testProducesAndConsumesOnClass();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Path("/client/{jclouds.api-version}")
|
@Path("/client/{jclouds.api-version}")
|
||||||
public interface AsyncCallee2 {
|
public interface Callee2 {
|
||||||
@GET
|
@GET
|
||||||
@Path("/{path}/2")
|
@Path("/{path}/2")
|
||||||
ListenableFuture<Void> onePath(@PathParam("path") String path);
|
void onePath(@PathParam("path") String path);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Endpoint(Localhost2.class)
|
@Endpoint(Localhost2.class)
|
||||||
public interface Caller extends Closeable {
|
public interface Caller extends Closeable {
|
||||||
|
|
||||||
// tests that we can pull from suppliers
|
|
||||||
@Provides
|
@Provides
|
||||||
@Localhost2
|
@Localhost2
|
||||||
URI getURI();
|
URI getURI();
|
||||||
|
@ -233,98 +225,21 @@ public class RestAnnotationProcessorTest extends BaseRestApiTest {
|
||||||
Callee getCalleeWithHeader(@EndpointParam URI endpoint, @HeaderParam("header") String header);
|
Callee getCalleeWithHeader(@EndpointParam URI endpoint, @HeaderParam("header") String header);
|
||||||
|
|
||||||
@Delegate
|
@Delegate
|
||||||
|
@Produces(APPLICATION_JSON)
|
||||||
|
@Consumes(APPLICATION_JSON)
|
||||||
Callee getCalleeWithoutProducesAndConsumes();
|
Callee getCalleeWithoutProducesAndConsumes();
|
||||||
|
|
||||||
@Delegate
|
@Delegate
|
||||||
|
@Produces(APPLICATION_JSON)
|
||||||
|
@Consumes(APPLICATION_JSON)
|
||||||
Callee getCalleeWithProducesAndConsumesOnMethod();
|
Callee getCalleeWithProducesAndConsumesOnMethod();
|
||||||
|
|
||||||
@Delegate
|
@Delegate
|
||||||
|
@Produces(APPLICATION_JSON)
|
||||||
|
@Consumes(APPLICATION_JSON)
|
||||||
CalleeWithProducesAndConsumesOnClass getCalleeWithProducesAndConsumesOnClass();
|
CalleeWithProducesAndConsumesOnClass getCalleeWithProducesAndConsumesOnClass();
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface Callee extends Closeable {
|
|
||||||
void onePath(String path);
|
|
||||||
void testWithoutProducesAndConsumes();
|
|
||||||
void testProducesAndConsumesOnMethod();
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface CalleeWithProducesAndConsumesOnClass extends Closeable {
|
|
||||||
void testProducesAndConsumesOnClass();
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface Callee2 {
|
|
||||||
void onePath(String path);
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface AsyncCaller extends Closeable {
|
|
||||||
@Provides
|
|
||||||
@Localhost2
|
|
||||||
URI getURI();
|
|
||||||
|
|
||||||
@Delegate
|
|
||||||
AsyncCallee getCallee();
|
|
||||||
|
|
||||||
@Delegate
|
|
||||||
AsyncCallee2 getCallee2();
|
|
||||||
|
|
||||||
@Delegate
|
|
||||||
AsyncCallee getCallee(@EndpointParam URI endpoint);
|
|
||||||
|
|
||||||
@Delegate
|
|
||||||
Optional<AsyncCallee> getOptionalCallee(@EndpointParam URI endpoint);
|
|
||||||
|
|
||||||
@Delegate
|
|
||||||
@Path("/testing/testing/{wibble}")
|
|
||||||
AsyncCallee getCalleeWithPath(@EndpointParam URI endpoint, @PathParam("wibble") String wibble);
|
|
||||||
|
|
||||||
@Delegate
|
|
||||||
AsyncCallee getCalleeWithHeader(@EndpointParam URI endpoint, @HeaderParam("header") String header);
|
|
||||||
|
|
||||||
@Delegate
|
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
|
||||||
@Consumes(MediaType.APPLICATION_JSON)
|
|
||||||
AsyncCallee getCalleeWithoutProducesAndConsumes();
|
|
||||||
|
|
||||||
@Delegate
|
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
|
||||||
@Consumes(MediaType.APPLICATION_JSON)
|
|
||||||
AsyncCallee getCalleeWithProducesAndConsumesOnMethod();
|
|
||||||
|
|
||||||
@Delegate
|
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
|
||||||
@Consumes(MediaType.APPLICATION_JSON)
|
|
||||||
AsyncCalleeWithProducesAndConsumesOnClass getCalleeWithProducesAndConsumesOnClass();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testAsyncDelegateIsLazyLoadedAndRequestIncludesVersionAndPath() throws InterruptedException,
|
|
||||||
ExecutionException {
|
|
||||||
Injector child = injectorForCaller(new HttpCommandExecutorService() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ListenableFuture<HttpResponse> submit(HttpCommand command) {
|
|
||||||
return Futures.immediateFuture(invoke(command));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public HttpResponse invoke(HttpCommand command) {
|
|
||||||
assertEquals(command.getCurrentRequest().getRequestLine(),
|
|
||||||
"GET http://localhost:9999/client/1/foo HTTP/1.1");
|
|
||||||
return HttpResponse.builder().build();
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
try {
|
|
||||||
child.getInstance(AsyncCallee.class);
|
|
||||||
fail("Callee shouldn't be bound yet");
|
|
||||||
} catch (ConfigurationException e) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
child.getInstance(AsyncCaller.class).getCallee().onePath("foo").get();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testDelegateIsLazyLoadedAndRequestIncludesVersionAndPath() throws InterruptedException,
|
public void testDelegateIsLazyLoadedAndRequestIncludesVersionAndPath() throws InterruptedException,
|
||||||
ExecutionException {
|
ExecutionException {
|
||||||
Injector child = injectorForCaller(new HttpCommandExecutorService() {
|
Injector child = injectorForCaller(new HttpCommandExecutorService() {
|
||||||
|
@ -332,7 +247,7 @@ public class RestAnnotationProcessorTest extends BaseRestApiTest {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ListenableFuture<HttpResponse> submit(HttpCommand command) {
|
public ListenableFuture<HttpResponse> submit(HttpCommand command) {
|
||||||
return Futures.immediateFuture(invoke(command));
|
throw new AssertionError();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -361,43 +276,13 @@ public class RestAnnotationProcessorTest extends BaseRestApiTest {
|
||||||
child.getInstance(Caller.class).getCallee().onePath("foo");
|
child.getInstance(Caller.class).getCallee().onePath("foo");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testAsyncDelegateIsLazyLoadedAndRequestIncludesEndpointVersionAndPath() throws InterruptedException,
|
public void testDelegateWithPathParamIsLazyLoadedAndRequestIncludesEndpointVersionAndPath()
|
||||||
ExecutionException {
|
|
||||||
Injector child = injectorForCaller(new HttpCommandExecutorService() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ListenableFuture<HttpResponse> submit(HttpCommand command) {
|
|
||||||
return Futures.immediateFuture(invoke(command));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public HttpResponse invoke(HttpCommand command) {
|
|
||||||
assertEquals(command.getCurrentRequest().getRequestLine(), "GET http://howdyboys/client/1/foo HTTP/1.1");
|
|
||||||
return HttpResponse.builder().build();
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
try {
|
|
||||||
child.getInstance(AsyncCallee.class);
|
|
||||||
fail("Callee shouldn't be bound yet");
|
|
||||||
} catch (ConfigurationException e) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
child.getInstance(AsyncCaller.class).getCallee(URI.create("http://howdyboys")).onePath("foo").get();
|
|
||||||
|
|
||||||
assertEquals(child.getInstance(AsyncCaller.class).getURI(), URI.create("http://localhost:1111"));
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testAsyncDelegateWithPathParamIsLazyLoadedAndRequestIncludesEndpointVersionAndPath()
|
|
||||||
throws InterruptedException, ExecutionException {
|
throws InterruptedException, ExecutionException {
|
||||||
Injector child = injectorForCaller(new HttpCommandExecutorService() {
|
Injector child = injectorForCaller(new HttpCommandExecutorService() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ListenableFuture<HttpResponse> submit(HttpCommand command) {
|
public ListenableFuture<HttpResponse> submit(HttpCommand command) {
|
||||||
return Futures.immediateFuture(invoke(command));
|
throw new AssertionError("jclouds no longer uses the submit method");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -410,25 +295,25 @@ public class RestAnnotationProcessorTest extends BaseRestApiTest {
|
||||||
});
|
});
|
||||||
|
|
||||||
try {
|
try {
|
||||||
child.getInstance(AsyncCallee.class);
|
child.getInstance(Callee.class);
|
||||||
fail("Callee shouldn't be bound yet");
|
fail("Callee shouldn't be bound yet");
|
||||||
} catch (ConfigurationException e) {
|
} catch (ConfigurationException e) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
child.getInstance(AsyncCaller.class).getCalleeWithPath(URI.create("http://howdyboys"), "thepathparam")
|
child.getInstance(Caller.class).getCalleeWithPath(URI.create("http://howdyboys"), "thepathparam")
|
||||||
.onePath("foo").get();
|
.onePath("foo");
|
||||||
|
|
||||||
assertEquals(child.getInstance(AsyncCaller.class).getURI(), URI.create("http://localhost:1111"));
|
assertEquals(child.getInstance(Caller.class).getURI(), URI.create("http://localhost:1111"));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testAsyncDelegateWithHeaderParamIsLazyLoadedAndRequestIncludesEndpointVersionAndHeader()
|
public void testDelegateWithHeaderParamIsLazyLoadedAndRequestIncludesEndpointVersionAndHeader()
|
||||||
throws InterruptedException, ExecutionException {
|
throws InterruptedException, ExecutionException {
|
||||||
Injector child = injectorForCaller(new HttpCommandExecutorService() {
|
Injector child = injectorForCaller(new HttpCommandExecutorService() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ListenableFuture<HttpResponse> submit(HttpCommand command) {
|
public ListenableFuture<HttpResponse> submit(HttpCommand command) {
|
||||||
return Futures.immediateFuture(invoke(command));
|
throw new AssertionError("jclouds no longer uses the submit method");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -440,116 +325,113 @@ public class RestAnnotationProcessorTest extends BaseRestApiTest {
|
||||||
});
|
});
|
||||||
|
|
||||||
try {
|
try {
|
||||||
child.getInstance(AsyncCallee.class);
|
child.getInstance(Callee.class);
|
||||||
fail("Callee shouldn't be bound yet");
|
fail("Callee shouldn't be bound yet");
|
||||||
} catch (ConfigurationException e) {
|
} catch (ConfigurationException e) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
child.getInstance(AsyncCaller.class).getCalleeWithHeader(URI.create("http://howdyboys"), "theheaderparam")
|
child.getInstance(Caller.class).getCalleeWithHeader(URI.create("http://howdyboys"), "theheaderparam")
|
||||||
.onePath("foo").get();
|
.onePath("foo");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testAsyncDelegateWithoutProducesAndConsumes()
|
public void testDelegateWithoutProducesAndConsumes()
|
||||||
throws InterruptedException, ExecutionException {
|
throws InterruptedException, ExecutionException {
|
||||||
Injector child = injectorForCaller(new HttpCommandExecutorService() {
|
Injector child = injectorForCaller(new HttpCommandExecutorService() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ListenableFuture<HttpResponse> submit(HttpCommand command) {
|
public ListenableFuture<HttpResponse> submit(HttpCommand command) {
|
||||||
return Futures.immediateFuture(invoke(command));
|
throw new AssertionError("jclouds no longer uses the submit method");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public HttpResponse invoke(HttpCommand command) {
|
public HttpResponse invoke(HttpCommand command) {
|
||||||
assertEquals(
|
assertEquals(
|
||||||
command.getCurrentRequest().getPayload().getContentMetadata().getContentType(),
|
command.getCurrentRequest().getPayload().getContentMetadata().getContentType(),
|
||||||
MediaType.APPLICATION_JSON);
|
APPLICATION_JSON);
|
||||||
assertTrue(command.getCurrentRequest().getHeaders().get("Accept").contains(MediaType.APPLICATION_JSON));
|
assertTrue(command.getCurrentRequest().getHeaders().get("Accept").contains(APPLICATION_JSON));
|
||||||
return HttpResponse.builder().build();
|
return HttpResponse.builder().build();
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
try {
|
try {
|
||||||
child.getInstance(AsyncCallee.class);
|
child.getInstance(Callee.class);
|
||||||
fail("Callee shouldn't be bound yet");
|
fail("Callee shouldn't be bound yet");
|
||||||
} catch (ConfigurationException e) {
|
} catch (ConfigurationException e) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
child.getInstance(AsyncCaller.class).getCalleeWithoutProducesAndConsumes()
|
child.getInstance(Caller.class).getCalleeWithoutProducesAndConsumes().testWithoutProducesAndConsumes();
|
||||||
.testWithoutProducesAndConsumes().get();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testAsyncDelegateWithProducesAndConsumesOnMethodIsLazyLoaded()
|
public void testDelegateWithProducesAndConsumesOnMethodIsLazyLoaded()
|
||||||
throws InterruptedException, ExecutionException {
|
throws InterruptedException, ExecutionException {
|
||||||
Injector child = injectorForCaller(new HttpCommandExecutorService() {
|
Injector child = injectorForCaller(new HttpCommandExecutorService() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ListenableFuture<HttpResponse> submit(HttpCommand command) {
|
public ListenableFuture<HttpResponse> submit(HttpCommand command) {
|
||||||
return Futures.immediateFuture(invoke(command));
|
throw new AssertionError("jclouds no longer uses the submit method");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public HttpResponse invoke(HttpCommand command) {
|
public HttpResponse invoke(HttpCommand command) {
|
||||||
assertEquals(
|
assertEquals(
|
||||||
command.getCurrentRequest().getPayload().getContentMetadata().getContentType(),
|
command.getCurrentRequest().getPayload().getContentMetadata().getContentType(),
|
||||||
MediaType.APPLICATION_XML);
|
APPLICATION_XML);
|
||||||
assertTrue(command.getCurrentRequest().getHeaders().get("Accept").contains(MediaType.APPLICATION_XML));
|
assertTrue(command.getCurrentRequest().getHeaders().get("Accept").contains(APPLICATION_XML));
|
||||||
return HttpResponse.builder().build();
|
return HttpResponse.builder().build();
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
try {
|
try {
|
||||||
child.getInstance(AsyncCallee.class);
|
child.getInstance(Callee.class);
|
||||||
fail("Callee shouldn't be bound yet");
|
fail("Callee shouldn't be bound yet");
|
||||||
} catch (ConfigurationException e) {
|
} catch (ConfigurationException e) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
child.getInstance(AsyncCaller.class).getCalleeWithProducesAndConsumesOnMethod()
|
child.getInstance(Caller.class).getCalleeWithProducesAndConsumesOnMethod().testProducesAndConsumesOnMethod();
|
||||||
.testProducesAndConsumesOnMethod().get();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testAsyncDelegateWithProducesAndConsumesOnClassIsLazyLoaded()
|
public void testDelegateWithProducesAndConsumesOnClassIsLazyLoaded()
|
||||||
throws InterruptedException, ExecutionException {
|
throws InterruptedException, ExecutionException {
|
||||||
Injector child = injectorForCaller(new HttpCommandExecutorService() {
|
Injector child = injectorForCaller(new HttpCommandExecutorService() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ListenableFuture<HttpResponse> submit(HttpCommand command) {
|
public ListenableFuture<HttpResponse> submit(HttpCommand command) {
|
||||||
return Futures.immediateFuture(invoke(command));
|
throw new AssertionError("jclouds no longer uses the submit method");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public HttpResponse invoke(HttpCommand command) {
|
public HttpResponse invoke(HttpCommand command) {
|
||||||
assertEquals(
|
assertEquals(
|
||||||
command.getCurrentRequest().getPayload().getContentMetadata().getContentType(),
|
command.getCurrentRequest().getPayload().getContentMetadata().getContentType(),
|
||||||
MediaType.APPLICATION_XML);
|
APPLICATION_XML);
|
||||||
assertTrue(command.getCurrentRequest().getHeaders().get("Accept").contains(MediaType.APPLICATION_XML));
|
assertTrue(command.getCurrentRequest().getHeaders().get("Accept").contains(APPLICATION_XML));
|
||||||
return HttpResponse.builder().build();
|
return HttpResponse.builder().build();
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
try {
|
try {
|
||||||
child.getInstance(AsyncCallee.class);
|
child.getInstance(Callee.class);
|
||||||
fail("Callee shouldn't be bound yet");
|
fail("Callee shouldn't be bound yet");
|
||||||
} catch (ConfigurationException e) {
|
} catch (ConfigurationException e) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
child.getInstance(AsyncCaller.class).getCalleeWithProducesAndConsumesOnClass()
|
child.getInstance(Caller.class).getCalleeWithProducesAndConsumesOnClass().testProducesAndConsumesOnClass();
|
||||||
.testProducesAndConsumesOnClass().get();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testAsyncDelegateIsLazyLoadedAndRequestIncludesEndpointVersionAndPathOptionalPresent()
|
public void testDelegateIsLazyLoadedAndRequestIncludesEndpointVersionAndPathOptionalPresent()
|
||||||
throws InterruptedException, ExecutionException {
|
throws InterruptedException, ExecutionException {
|
||||||
Injector child = injectorForCaller(new HttpCommandExecutorService() {
|
Injector child = injectorForCaller(new HttpCommandExecutorService() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ListenableFuture<HttpResponse> submit(HttpCommand command) {
|
public ListenableFuture<HttpResponse> submit(HttpCommand command) {
|
||||||
return Futures.immediateFuture(invoke(command));
|
throw new AssertionError("jclouds no longer uses the submit method");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -561,59 +443,15 @@ public class RestAnnotationProcessorTest extends BaseRestApiTest {
|
||||||
});
|
});
|
||||||
|
|
||||||
try {
|
try {
|
||||||
child.getInstance(AsyncCallee.class);
|
child.getInstance(Callee.class);
|
||||||
fail("Callee shouldn't be bound yet");
|
fail("Callee shouldn't be bound yet");
|
||||||
} catch (ConfigurationException e) {
|
} catch (ConfigurationException e) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
child.getInstance(AsyncCaller.class).getOptionalCallee(URI.create("http://howdyboys")).get().onePath("foo").get();
|
child.getInstance(Caller.class).getOptionalCallee(URI.create("http://howdyboys")).get().onePath("foo");
|
||||||
|
|
||||||
assertEquals(child.getInstance(AsyncCaller.class).getURI(), URI.create("http://localhost:1111"));
|
assertEquals(child.getInstance(Caller.class).getURI(), URI.create("http://localhost:1111"));
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testAsyncDelegateIsLazyLoadedAndRequestIncludesEndpointVersionAndPathCanOverrideOptionalBehaviour()
|
|
||||||
throws InterruptedException, ExecutionException {
|
|
||||||
Injector child = injectorForCaller(new HttpCommandExecutorService() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ListenableFuture<HttpResponse> submit(HttpCommand command) {
|
|
||||||
return Futures.immediateFuture(invoke(command));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public HttpResponse invoke(HttpCommand command) {
|
|
||||||
assertEquals(command.getCurrentRequest().getRequestLine(), "GET http://howdyboys/client/1/foo HTTP/1.1");
|
|
||||||
return HttpResponse.builder().build();
|
|
||||||
}
|
|
||||||
|
|
||||||
}, new AbstractModule() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void configure() {
|
|
||||||
bind(ImplicitOptionalConverter.class).toInstance(new ImplicitOptionalConverter() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Optional<Object> apply(InvocationSuccess input) {
|
|
||||||
return Optional.absent();
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
try {
|
|
||||||
child.getInstance(AsyncCallee.class);
|
|
||||||
fail("Callee shouldn't be bound yet");
|
|
||||||
} catch (ConfigurationException e) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
assert !child.getInstance(AsyncCaller.class).getOptionalCallee(URI.create("http://howdyboys")).isPresent();
|
|
||||||
|
|
||||||
assertEquals(child.getInstance(AsyncCaller.class).getURI(), URI.create("http://localhost:1111"));
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -623,7 +461,7 @@ public class RestAnnotationProcessorTest extends BaseRestApiTest {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ListenableFuture<HttpResponse> submit(HttpCommand command) {
|
public ListenableFuture<HttpResponse> submit(HttpCommand command) {
|
||||||
return Futures.immediateFuture(invoke(command));
|
throw new AssertionError("jclouds no longer uses the submit method");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -646,13 +484,12 @@ public class RestAnnotationProcessorTest extends BaseRestApiTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
private Injector injectorForCaller(HttpCommandExecutorService service, Module... modules) {
|
private Injector injectorForCaller(HttpCommandExecutorService service, Module... modules) {
|
||||||
return ContextBuilder
|
return ContextBuilder.newBuilder(forApiOnEndpoint(Caller.class, "http://localhost:9999"))
|
||||||
.newBuilder(
|
.modules(ImmutableSet.<Module> builder()
|
||||||
AnonymousProviderMetadata.forClientMappedToAsyncClientOnEndpoint(Caller.class, AsyncCaller.class,
|
.add(new MockModule(service))
|
||||||
"http://localhost:9999"))
|
.add(new NullLoggingModule())
|
||||||
.modules(
|
.add(new CallerModule())
|
||||||
ImmutableSet.<Module> builder().add(new MockModule(service)).add(new NullLoggingModule())
|
.addAll(Arrays.asList(modules)).build()).buildInjector();
|
||||||
.add(new CallerModule()).addAll(ImmutableSet.<Module> copyOf(modules)).build()).buildInjector();
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1256,12 +1093,12 @@ public class RestAnnotationProcessorTest extends BaseRestApiTest {
|
||||||
@GET
|
@GET
|
||||||
@Path("/")
|
@Path("/")
|
||||||
@Consumes("application/json")
|
@Consumes("application/json")
|
||||||
ListenableFuture<Map<String, String>> testGeneric2();
|
Map<String, String> testGeneric2();
|
||||||
|
|
||||||
@GET
|
@GET
|
||||||
@Path("/")
|
@Path("/")
|
||||||
@Consumes("application/json")
|
@Consumes("application/json")
|
||||||
ListenableFuture<? extends Map<String, String>> testGeneric3();
|
Map<String, String> testGeneric3();
|
||||||
|
|
||||||
@GET
|
@GET
|
||||||
@Path("/")
|
@Path("/")
|
||||||
|
@ -1283,30 +1120,30 @@ public class RestAnnotationProcessorTest extends BaseRestApiTest {
|
||||||
@Path("/")
|
@Path("/")
|
||||||
@Unwrap
|
@Unwrap
|
||||||
@Consumes("application/json")
|
@Consumes("application/json")
|
||||||
ListenableFuture<String> testUnwrap2();
|
String testUnwrap2();
|
||||||
|
|
||||||
@GET
|
@GET
|
||||||
@Path("/")
|
@Path("/")
|
||||||
@Unwrap
|
@Unwrap
|
||||||
@Consumes("application/json")
|
@Consumes("application/json")
|
||||||
ListenableFuture<Set<String>> testUnwrap3();
|
Set<String> testUnwrap3();
|
||||||
|
|
||||||
@GET
|
@GET
|
||||||
@Path("/")
|
@Path("/")
|
||||||
@Unwrap
|
@Unwrap
|
||||||
@Consumes("application/json")
|
@Consumes("application/json")
|
||||||
ListenableFuture<? extends Set<String>> testUnwrap4();
|
Set<String> testUnwrap4();
|
||||||
|
|
||||||
@GET
|
@GET
|
||||||
@Path("/")
|
@Path("/")
|
||||||
@SelectJson("jobid")
|
@SelectJson("jobid")
|
||||||
ListenableFuture<Long> selectLong();
|
Long selectLong();
|
||||||
|
|
||||||
@GET
|
@GET
|
||||||
@Path("/")
|
@Path("/")
|
||||||
@SelectJson("jobid")
|
@SelectJson("jobid")
|
||||||
@Transform(AddOne.class)
|
@Transform(AddOne.class)
|
||||||
ListenableFuture<Long> selectLongAddOne();
|
Long selectLongAddOne();
|
||||||
|
|
||||||
static class AddOne implements Function<Long, Long> {
|
static class AddOne implements Function<Long, Long> {
|
||||||
|
|
||||||
|
@ -1321,7 +1158,7 @@ public class RestAnnotationProcessorTest extends BaseRestApiTest {
|
||||||
@SelectJson("runit")
|
@SelectJson("runit")
|
||||||
@OnlyElement
|
@OnlyElement
|
||||||
@Consumes("application/json")
|
@Consumes("application/json")
|
||||||
ListenableFuture<String> selectOnlyElement();
|
String selectOnlyElement();
|
||||||
|
|
||||||
@Target({ ElementType.METHOD })
|
@Target({ ElementType.METHOD })
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@ -1331,11 +1168,11 @@ public class RestAnnotationProcessorTest extends BaseRestApiTest {
|
||||||
|
|
||||||
@ROWDY
|
@ROWDY
|
||||||
@Path("/strings/{id}")
|
@Path("/strings/{id}")
|
||||||
ListenableFuture<Boolean> rowdy(@PathParam("id") String path);
|
Boolean rowdy(@PathParam("id") String path);
|
||||||
|
|
||||||
@ROWDY
|
@ROWDY
|
||||||
@Path("/ints/{id}")
|
@Path("/ints/{id}")
|
||||||
ListenableFuture<Boolean> rowdy(@PathParam("id") int path);
|
Boolean rowdy(@PathParam("id") int path);
|
||||||
}
|
}
|
||||||
|
|
||||||
static class View {
|
static class View {
|
||||||
|
@ -1594,9 +1431,7 @@ public class RestAnnotationProcessorTest extends BaseRestApiTest {
|
||||||
// Now let's create a new injector with the property set. Use that to create the annotation processor.
|
// Now let's create a new injector with the property set. Use that to create the annotation processor.
|
||||||
Properties overrides = new Properties();
|
Properties overrides = new Properties();
|
||||||
overrides.setProperty(Constants.PROPERTY_STRIP_EXPECT_HEADER, "true");
|
overrides.setProperty(Constants.PROPERTY_STRIP_EXPECT_HEADER, "true");
|
||||||
Injector injector = ContextBuilder.newBuilder(
|
Injector injector = ContextBuilder.newBuilder(forApiOnEndpoint(Callee.class, "http://localhost:9999"))
|
||||||
AnonymousProviderMetadata.forClientMappedToAsyncClientOnEndpoint(Callee.class, AsyncCallee.class,
|
|
||||||
"http://localhost:9999"))
|
|
||||||
.modules(ImmutableSet.<Module> of(new MockModule(), new NullLoggingModule(), new AbstractModule() {
|
.modules(ImmutableSet.<Module> of(new MockModule(), new NullLoggingModule(), new AbstractModule() {
|
||||||
protected void configure() {
|
protected void configure() {
|
||||||
bind(new TypeLiteral<Supplier<URI>>() {
|
bind(new TypeLiteral<Supplier<URI>>() {
|
||||||
|
@ -1931,31 +1766,31 @@ public class RestAnnotationProcessorTest extends BaseRestApiTest {
|
||||||
|
|
||||||
public interface TestTransformers {
|
public interface TestTransformers {
|
||||||
@GET
|
@GET
|
||||||
ListenableFuture<Integer> noTransformer();
|
Integer noTransformer();
|
||||||
|
|
||||||
@GET
|
@GET
|
||||||
@ResponseParser(ReturnStringIf2xx.class)
|
@ResponseParser(ReturnStringIf2xx.class)
|
||||||
ListenableFuture<Void> oneTransformer();
|
void oneTransformer();
|
||||||
|
|
||||||
@GET
|
@GET
|
||||||
@ResponseParser(ReturnStringIf200Context.class)
|
@ResponseParser(ReturnStringIf200Context.class)
|
||||||
ListenableFuture<Void> oneTransformerWithContext();
|
void oneTransformerWithContext();
|
||||||
|
|
||||||
@GET
|
@GET
|
||||||
ListenableFuture<InputStream> futureInputStream();
|
InputStream futureInputStream();
|
||||||
|
|
||||||
@GET
|
@GET
|
||||||
ListenableFuture<URI> futureUri();
|
URI futureUri();
|
||||||
|
|
||||||
@PUT
|
@PUT
|
||||||
ListenableFuture<Void> put(Payload payload);
|
void put(Payload payload);
|
||||||
|
|
||||||
@PUT
|
@PUT
|
||||||
@Headers(keys = "Transfer-Encoding", values = "chunked")
|
@Headers(keys = "Transfer-Encoding", values = "chunked")
|
||||||
ListenableFuture<Void> putXfer(Payload payload);
|
void putXfer(Payload payload);
|
||||||
|
|
||||||
@PUT
|
@PUT
|
||||||
ListenableFuture<Void> put(PayloadEnclosing payload);
|
void put(PayloadEnclosing payload);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testPutPayloadEnclosing() throws SecurityException, NoSuchMethodException, IOException {
|
public void testPutPayloadEnclosing() throws SecurityException, NoSuchMethodException, IOException {
|
||||||
|
@ -2149,48 +1984,48 @@ public class RestAnnotationProcessorTest extends BaseRestApiTest {
|
||||||
@GET
|
@GET
|
||||||
@VirtualHost
|
@VirtualHost
|
||||||
@Path("/{id}")
|
@Path("/{id}")
|
||||||
ListenableFuture<String> get(@PathParam("id") String id, HttpRequestOptions options);
|
String get(@PathParam("id") String id, HttpRequestOptions options);
|
||||||
|
|
||||||
@GET
|
@GET
|
||||||
@VirtualHost
|
@VirtualHost
|
||||||
@Path("/{id}")
|
@Path("/{id}")
|
||||||
ListenableFuture<String> get(@PathParam("id") String id, HttpRequestOptions... options);
|
String get(@PathParam("id") String id, HttpRequestOptions... options);
|
||||||
|
|
||||||
@GET
|
@GET
|
||||||
@Path("/{id}")
|
@Path("/{id}")
|
||||||
@ResponseParser(ReturnStringIf2xx.class)
|
@ResponseParser(ReturnStringIf2xx.class)
|
||||||
ListenableFuture<String> get(@PathParam("id") String id, @HeaderParam(HttpHeaders.HOST) String host);
|
String get(@PathParam("id") String id, @HeaderParam(HttpHeaders.HOST) String host);
|
||||||
|
|
||||||
@GET
|
@GET
|
||||||
@Path("/{id}")
|
@Path("/{id}")
|
||||||
@QueryParams(keys = "max-keys", values = "0")
|
@QueryParams(keys = "max-keys", values = "0")
|
||||||
ListenableFuture<String> getQuery(@PathParam("id") String id);
|
String getQuery(@PathParam("id") String id);
|
||||||
|
|
||||||
@GET
|
@GET
|
||||||
@Path("/{id}")
|
@Path("/{id}")
|
||||||
@QueryParams(keys = "acl")
|
@QueryParams(keys = "acl")
|
||||||
ListenableFuture<String> getQueryNull(@PathParam("id") String id);
|
String getQueryNull(@PathParam("id") String id);
|
||||||
|
|
||||||
@GET
|
@GET
|
||||||
@Path("/{id}")
|
@Path("/{id}")
|
||||||
@QueryParams(keys = "acl", values = "")
|
@QueryParams(keys = "acl", values = "")
|
||||||
ListenableFuture<String> getQueryEmpty(@PathParam("id") String id);
|
String getQueryEmpty(@PathParam("id") String id);
|
||||||
|
|
||||||
@PUT
|
@PUT
|
||||||
@Path("/{id}")
|
@Path("/{id}")
|
||||||
ListenableFuture<String> put(@PathParam("id") @ParamParser(FirstCharacter.class) String id,
|
String put(@PathParam("id") @ParamParser(FirstCharacter.class) String id,
|
||||||
@BinderParam(BindToStringPayload.class) String payload);
|
@BinderParam(BindToStringPayload.class) String payload);
|
||||||
|
|
||||||
@PUT
|
@PUT
|
||||||
@Path("/{id}")
|
@Path("/{id}")
|
||||||
@VirtualHost
|
@VirtualHost
|
||||||
ListenableFuture<String> putOptions(@PathParam("id") String id, HttpRequestOptions options);
|
String putOptions(@PathParam("id") String id, HttpRequestOptions options);
|
||||||
|
|
||||||
@PUT
|
@PUT
|
||||||
@Path("/{id}")
|
@Path("/{id}")
|
||||||
@Headers(keys = "foo", values = "--{id}--")
|
@Headers(keys = "foo", values = "--{id}--")
|
||||||
@ResponseParser(ReturnTrueIf2xx.class)
|
@ResponseParser(ReturnTrueIf2xx.class)
|
||||||
ListenableFuture<String> putHeader(@PathParam("id") String id,
|
String putHeader(@PathParam("id") String id,
|
||||||
@BinderParam(BindToStringPayload.class) String payload);
|
@BinderParam(BindToStringPayload.class) String payload);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2335,7 +2170,7 @@ public class RestAnnotationProcessorTest extends BaseRestApiTest {
|
||||||
@GET
|
@GET
|
||||||
@Path("/{id}")
|
@Path("/{id}")
|
||||||
@VirtualHost
|
@VirtualHost
|
||||||
public ListenableFuture<String> get(@PathParam("id") String id, String foo) {
|
public String get(@PathParam("id") String id, String foo) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2356,11 +2191,11 @@ public class RestAnnotationProcessorTest extends BaseRestApiTest {
|
||||||
@GET
|
@GET
|
||||||
@Path("/{id}")
|
@Path("/{id}")
|
||||||
@VirtualHost
|
@VirtualHost
|
||||||
ListenableFuture<String> get(@PathParam("id") String id, String foo);
|
String get(@PathParam("id") String id, String foo);
|
||||||
|
|
||||||
@GET
|
@GET
|
||||||
@Path("/{id}")
|
@Path("/{id}")
|
||||||
ListenableFuture<String> getPrefix(@PathParam("id") String id, @BinderParam(BindAsHostPrefix.class) String foo);
|
String getPrefix(@PathParam("id") String id, @BinderParam(BindAsHostPrefix.class) String foo);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2501,7 +2336,7 @@ public class RestAnnotationProcessorTest extends BaseRestApiTest {
|
||||||
|
|
||||||
@PUT
|
@PUT
|
||||||
@Path("/{foo}")
|
@Path("/{foo}")
|
||||||
ListenableFuture<Void> putWithPath(@PathParam("foo") String path,
|
void putWithPath(@PathParam("foo") String path,
|
||||||
@BinderParam(BindToStringPayload.class) String content);
|
@BinderParam(BindToStringPayload.class) String content);
|
||||||
|
|
||||||
@PUT
|
@PUT
|
||||||
|
@ -2653,9 +2488,7 @@ public class RestAnnotationProcessorTest extends BaseRestApiTest {
|
||||||
@BeforeClass
|
@BeforeClass
|
||||||
void setupFactory() {
|
void setupFactory() {
|
||||||
injector = ContextBuilder
|
injector = ContextBuilder
|
||||||
.newBuilder(
|
.newBuilder(forApiOnEndpoint(Callee.class, "http://localhost:9999"))
|
||||||
AnonymousProviderMetadata.forClientMappedToAsyncClientOnEndpoint(Callee.class, AsyncCallee.class,
|
|
||||||
"http://localhost:9999"))
|
|
||||||
.modules(ImmutableSet.<Module> of(new MockModule(), new NullLoggingModule(), new AbstractModule() {
|
.modules(ImmutableSet.<Module> of(new MockModule(), new NullLoggingModule(), new AbstractModule() {
|
||||||
protected void configure() {
|
protected void configure() {
|
||||||
bind(new TypeLiteral<Supplier<URI>>() {
|
bind(new TypeLiteral<Supplier<URI>>() {
|
||||||
|
|
Loading…
Reference in New Issue