refactored internal code and tests to use FunctionalReflection

This commit is contained in:
Adrian Cole 2013-01-06 23:17:14 -08:00
parent bd9e998b12
commit 3089111621
127 changed files with 1618 additions and 2301 deletions

View File

@ -33,6 +33,7 @@ import org.jclouds.blobstore.domain.Blob;
import org.jclouds.blobstore.functions.BlobToHttpGetOptions;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.options.GetOptions;
import org.jclouds.reflect.Invocation;
import org.jclouds.rest.internal.RestAnnotationProcessor;
import com.google.common.collect.ImmutableList;
@ -53,9 +54,9 @@ public class AtmosBlobRequestSigner implements BlobRequestSigner {
private final Invokable<?, ?> createMethod;
@Inject
public AtmosBlobRequestSigner(RestAnnotationProcessor.Factory processor, BlobToObject blobToObject,
public AtmosBlobRequestSigner(RestAnnotationProcessor processor, BlobToObject blobToObject,
BlobToHttpGetOptions blob2ObjectGetOptions) throws SecurityException, NoSuchMethodException {
this.processor = checkNotNull(processor, "processor").declaring(AtmosAsyncClient.class);
this.processor = checkNotNull(processor, "processor");
this.blobToObject = checkNotNull(blobToObject, "blobToObject");
this.blob2ObjectGetOptions = checkNotNull(blob2ObjectGetOptions, "blob2ObjectGetOptions");
this.getMethod = Invokable.from(AtmosAsyncClient.class.getMethod("readFile", String.class, GetOptions[].class));
@ -68,7 +69,8 @@ public class AtmosBlobRequestSigner implements BlobRequestSigner {
public HttpRequest signGetBlob(String container, String name) {
checkNotNull(container, "container");
checkNotNull(name, "name");
return cleanRequest(processor.createRequest(getMethod, ImmutableList.<Object> of(getPath(container, name))));
return cleanRequest(processor.apply(Invocation.create(getMethod,
ImmutableList.<Object> of(getPath(container, name)))));
}
@Override
@ -80,8 +82,8 @@ public class AtmosBlobRequestSigner implements BlobRequestSigner {
public HttpRequest signPutBlob(String container, Blob blob) {
checkNotNull(container, "container");
checkNotNull(blob, "blob");
return cleanRequest(processor.createRequest(createMethod,
ImmutableList.<Object> of(container, blobToObject.apply(blob))));
return cleanRequest(processor.apply(Invocation.create(createMethod,
ImmutableList.<Object> of(container, blobToObject.apply(blob)))));
}
@Override
@ -93,7 +95,8 @@ public class AtmosBlobRequestSigner implements BlobRequestSigner {
public HttpRequest signRemoveBlob(String container, String name) {
checkNotNull(container, "container");
checkNotNull(name, "name");
return cleanRequest(processor.createRequest(deleteMethod, ImmutableList.<Object> of(getPath(container, name))));
return cleanRequest(processor.apply(Invocation.create(deleteMethod,
ImmutableList.<Object> of(getPath(container, name)))));
}
private String getPath(String container, String name) {
@ -104,8 +107,8 @@ public class AtmosBlobRequestSigner implements BlobRequestSigner {
public HttpRequest signGetBlob(String container, String name, org.jclouds.blobstore.options.GetOptions options) {
checkNotNull(container, "container");
checkNotNull(name, "name");
return cleanRequest(processor.createRequest(getMethod,
ImmutableList.of(getPath(container, name), blob2ObjectGetOptions.apply(checkNotNull(options, "options")))));
return cleanRequest(processor.apply(Invocation.create(getMethod,
ImmutableList.of(getPath(container, name), blob2ObjectGetOptions.apply(checkNotNull(options, "options"))))));
}
}

View File

@ -79,7 +79,7 @@ public class ParseObjectFromHeadersAndHttpContent implements Function<HttpRespon
@Override
public ParseObjectFromHeadersAndHttpContent setContext(HttpRequest request) {
this.uri = request.getEndpoint();
return setPath(GeneratedHttpRequest.class.cast(request).getArgs().get(0).toString());
return setPath(GeneratedHttpRequest.class.cast(request).getInvocation().getArgs().get(0).toString());
}
private ParseObjectFromHeadersAndHttpContent setPath(String path) {

View File

@ -20,7 +20,6 @@ package org.jclouds.cloudsigma.binders;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import java.util.Map;
@ -58,7 +57,6 @@ public class BindCloneDriveOptionsToPlainTextString implements MapBinder {
checkArgument(checkNotNull(request, "request") instanceof GeneratedHttpRequest,
"this binder is only valid for GeneratedHttpRequests!");
GeneratedHttpRequest gRequest = GeneratedHttpRequest.class.cast(request);
checkState(gRequest.getArgs() != null, "args should be initialized at this point");
CloneDriveOptions options = findOptionsInArgsOrNull(gRequest);
if (options != null) {
@ -76,7 +74,7 @@ public class BindCloneDriveOptionsToPlainTextString implements MapBinder {
}
static CloneDriveOptions findOptionsInArgsOrNull(GeneratedHttpRequest gRequest) {
for (Object arg : gRequest.getArgs()) {
for (Object arg : gRequest.getInvocation().getArgs()) {
if (arg instanceof CloneDriveOptions) {
return (CloneDriveOptions) arg;
} else if (arg instanceof CloneDriveOptions[]) {

View File

@ -18,64 +18,59 @@
*/
package org.jclouds.cloudsigma.binders;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.verify;
import static org.testng.Assert.assertEquals;
import java.io.IOException;
import java.net.URI;
import java.util.List;
import java.util.Map;
import org.jclouds.cloudsigma.options.CloneDriveOptions;
import org.jclouds.io.MutableContentMetadata;
import org.jclouds.io.Payload;
import org.jclouds.reflect.Invocation;
import org.jclouds.rest.internal.GeneratedHttpRequest;
import org.testng.annotations.Test;
import com.google.common.base.Throwables;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.reflect.Invokable;
import com.google.inject.Guice;
/**
*
* @author Adrian Cole
*/
@Test(groups = { "unit" })
@Test(groups = "unit")
public class BindCloneDriveOptionsToPlainTextStringTest {
private static final BindCloneDriveOptionsToPlainTextString binder = Guice.createInjector().getInstance(
BindCloneDriveOptionsToPlainTextString.class);
public void testDefault() throws IOException {
assertInputAndArgsCreatesPayload(ImmutableMap.<String, Object>of("name", "newdrive"), ImmutableList.<Object> of(),
"name newdrive");
String expected = "name newdrive";
GeneratedHttpRequest request = requestForArgs(ImmutableList.<Object> of());
Map<String, Object> map = ImmutableMap.<String, Object> of("name", "newdrive");
assertEquals(binder.bindToRequest(request, map).getPayload().getRawContent(), expected);
}
public void testWithSize() throws IOException {
assertInputAndArgsCreatesPayload(ImmutableMap.<String, Object>of("name", "newdrive"),
ImmutableList.<Object> of(new CloneDriveOptions().size(1024)), "name newdrive\nsize 1024");
String expected = "name newdrive\nsize 1024";
GeneratedHttpRequest request = requestForArgs(ImmutableList.<Object> of(new CloneDriveOptions().size(1024)));
Map<String, Object> map = ImmutableMap.<String, Object> of("name", "newdrive");
assertEquals(binder.bindToRequest(request, map).getPayload().getRawContent(), expected);
}
protected void assertInputAndArgsCreatesPayload(ImmutableMap<String, Object> inputMap, List<Object> args,
String expected) {
GeneratedHttpRequest request = createMock(GeneratedHttpRequest.class);
expect(request.getArgs()).andReturn(args).atLeastOnce();
request.setPayload(expected);
Payload payload = createMock(Payload.class);
expect(request.getPayload()).andReturn(payload);
MutableContentMetadata md = createMock(MutableContentMetadata.class);
expect(payload.getContentMetadata()).andReturn(md);
md.setContentType("text/plain");
replay(request);
replay(payload);
replay(md);
binder.bindToRequest(request, inputMap);
verify(request);
verify(payload);
verify(md);
protected GeneratedHttpRequest requestForArgs(List<Object> args) {
try {
Invocation invocation = Invocation.create(Invokable.from(String.class.getDeclaredMethod("toString")), args);
return GeneratedHttpRequest.builder().method("POST").endpoint(URI.create("http://localhost/key"))
.invocation(invocation).build();
} catch (SecurityException e) {
throw Throwables.propagate(e);
} catch (NoSuchMethodException e) {
throw Throwables.propagate(e);
}
}
}

View File

@ -187,7 +187,7 @@ public class CreateVolumeResponseHandler extends ParseSax.HandlerForGeneratedReq
}
public static String findAvailabilityZoneInArgsOrNull(GeneratedHttpRequest gRequest, Set<String> zones) {
for (Object arg : gRequest.getArgs()) {
for (Object arg : gRequest.getInvocation().getArgs()) {
if (arg instanceof String) {
String zone = (String) arg;
if (zones.contains(zone))

View File

@ -18,9 +18,6 @@
*/
package org.jclouds.ec2.xml;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
import static org.testng.Assert.assertEquals;
import java.io.InputStream;
@ -28,11 +25,8 @@ import java.io.InputStream;
import org.jclouds.date.DateService;
import org.jclouds.ec2.domain.Attachment;
import org.jclouds.http.functions.ParseSax;
import org.jclouds.rest.internal.GeneratedHttpRequest;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableList;
/**
* Tests behavior of {@code AttachmentHandler}
*
@ -56,9 +50,6 @@ public class AttachmentHandlerTest extends BaseEC2HandlerTest {
}
private void addDefaultRegionToHandler(ParseSax.HandlerWithResult<?> handler) {
GeneratedHttpRequest request = createMock(GeneratedHttpRequest.class);
expect(request.getArgs()).andReturn(ImmutableList.<Object> of());
replay(request);
handler.setContext(request);
}
}

View File

@ -18,9 +18,6 @@
*/
package org.jclouds.ec2.xml;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
import static org.testng.Assert.assertEquals;
import java.io.InputStream;
@ -28,11 +25,8 @@ import java.io.InputStream;
import org.jclouds.date.DateService;
import org.jclouds.ec2.domain.BundleTask;
import org.jclouds.http.functions.ParseSax;
import org.jclouds.rest.internal.GeneratedHttpRequest;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableList;
/**
* Tests behavior of {@code BundleTaskHandler}
*
@ -71,9 +65,6 @@ public class BundleTaskHandlerTest extends BaseEC2HandlerTest {
}
private void addDefaultRegionToHandler(ParseSax.HandlerWithResult<?> handler) {
GeneratedHttpRequest request = createMock(GeneratedHttpRequest.class);
expect(request.getArgs()).andReturn(ImmutableList.<Object>of());
replay(request);
handler.setContext(request);
}
}

View File

@ -18,9 +18,6 @@
*/
package org.jclouds.ec2.xml;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
import static org.testng.Assert.assertEquals;
import java.io.InputStream;
@ -30,10 +27,8 @@ import org.jclouds.date.DateService;
import org.jclouds.ec2.domain.Attachment;
import org.jclouds.ec2.domain.Volume;
import org.jclouds.http.functions.ParseSax;
import org.jclouds.rest.internal.GeneratedHttpRequest;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Sets;
/**
@ -62,9 +57,6 @@ public class CreateVolumeResponseHandlerTest extends BaseEC2HandlerTest {
}
private void addDefaultRegionToHandler(ParseSax.HandlerWithResult<?> handler) {
GeneratedHttpRequest request = createMock(GeneratedHttpRequest.class);
expect(request.getArgs()).andReturn(ImmutableList.<Object>of()).atLeastOnce();
replay(request);
handler.setContext(request);
}
}

View File

@ -18,9 +18,6 @@
*/
package org.jclouds.ec2.xml;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
import static org.testng.Assert.assertEquals;
import java.io.InputStream;
@ -29,7 +26,6 @@ import java.util.Set;
import org.jclouds.ec2.domain.PublicIpInstanceIdPair;
import org.jclouds.http.functions.ParseSax;
import org.jclouds.rest.internal.GeneratedHttpRequest;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableList;
@ -58,9 +54,6 @@ public class DescribeAddressesResponseHandlerTest extends BaseEC2HandlerTest {
}
private void addDefaultRegionToHandler(ParseSax.HandlerWithResult<?> handler) {
GeneratedHttpRequest request = createMock(GeneratedHttpRequest.class);
expect(request.getArgs()).andReturn(ImmutableList.<Object>of()).atLeastOnce();
replay(request);
handler.setContext(request);
}
}

View File

@ -18,9 +18,6 @@
*/
package org.jclouds.ec2.xml;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
import static org.testng.Assert.assertEquals;
import java.io.InputStream;
@ -28,10 +25,8 @@ import java.io.InputStream;
import org.jclouds.date.DateService;
import org.jclouds.ec2.domain.BundleTask;
import org.jclouds.http.functions.ParseSax;
import org.jclouds.rest.internal.GeneratedHttpRequest;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
/**
@ -58,9 +53,6 @@ public class DescribeBundleTasksResponseHandlerTest extends BaseEC2HandlerTest {
}
private void addDefaultRegionToHandler(ParseSax.HandlerWithResult<?> handler) {
GeneratedHttpRequest request = createMock(GeneratedHttpRequest.class);
expect(request.getArgs()).andReturn(ImmutableList.<Object>of());
replay(request);
handler.setContext(request);
}
}

View File

@ -17,10 +17,6 @@
* under the License.
*/
package org.jclouds.ec2.xml;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
import static org.testng.Assert.assertEquals;
import java.io.InputStream;
@ -28,10 +24,8 @@ import java.util.Set;
import org.jclouds.ec2.domain.KeyPair;
import org.jclouds.http.functions.ParseSax;
import org.jclouds.rest.internal.GeneratedHttpRequest;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
/**
@ -56,9 +50,6 @@ public class DescribeKeyPairsResponseHandlerTest extends BaseEC2HandlerTest {
}
private void addDefaultRegionToHandler(ParseSax.HandlerWithResult<?> handler) {
GeneratedHttpRequest request = createMock(GeneratedHttpRequest.class);
expect(request.getArgs()).andReturn(ImmutableList.<Object> of());
replay(request);
handler.setContext(request);
}
}

View File

@ -18,9 +18,6 @@
*/
package org.jclouds.ec2.xml;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
import static org.testng.Assert.assertEquals;
import java.io.InputStream;
@ -30,10 +27,8 @@ import org.jclouds.ec2.domain.IpPermission;
import org.jclouds.ec2.domain.IpProtocol;
import org.jclouds.ec2.domain.SecurityGroup;
import org.jclouds.http.functions.ParseSax;
import org.jclouds.rest.internal.GeneratedHttpRequest;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.LinkedHashMultimap;
@ -91,9 +86,6 @@ public class DescribeSecurityGroupsResponseHandlerTest extends BaseEC2HandlerTes
}
private void addDefaultRegionToHandler(ParseSax.HandlerWithResult<?> handler) {
GeneratedHttpRequest request = createMock(GeneratedHttpRequest.class);
expect(request.getArgs()).andReturn(ImmutableList.<Object> of()).atLeastOnce();
replay(request);
handler.setContext(request);
}
}

View File

@ -18,9 +18,6 @@
*/
package org.jclouds.ec2.xml;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
import static org.testng.Assert.assertEquals;
import java.io.InputStream;
@ -29,10 +26,8 @@ import java.util.Set;
import org.jclouds.date.DateService;
import org.jclouds.ec2.domain.Snapshot;
import org.jclouds.http.functions.ParseSax;
import org.jclouds.rest.internal.GeneratedHttpRequest;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Sets;
/**
@ -61,9 +56,6 @@ public class DescribeSnapshotsResponseHandlerTest extends BaseEC2HandlerTest {
}
private void addDefaultRegionToHandler(ParseSax.HandlerWithResult<?> handler) {
GeneratedHttpRequest request = createMock(GeneratedHttpRequest.class);
expect(request.getArgs()).andReturn(ImmutableList.<Object>of());
replay(request);
handler.setContext(request);
}
}

View File

@ -18,9 +18,6 @@
*/
package org.jclouds.ec2.xml;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
import static org.testng.Assert.assertEquals;
import java.io.InputStream;
@ -30,10 +27,8 @@ import org.jclouds.date.DateService;
import org.jclouds.ec2.domain.Attachment;
import org.jclouds.ec2.domain.Volume;
import org.jclouds.http.functions.ParseSax;
import org.jclouds.rest.internal.GeneratedHttpRequest;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Sets;
/**
@ -69,9 +64,6 @@ public class DescribeVolumesResponseHandlerTest extends BaseEC2HandlerTest {
}
private void addDefaultRegionToHandler(ParseSax.HandlerWithResult<?> handler) {
GeneratedHttpRequest request = createMock(GeneratedHttpRequest.class);
expect(request.getArgs()).andReturn(ImmutableList.<Object>of()).atLeastOnce();
replay(request);
handler.setContext(request);
}
}

View File

@ -18,9 +18,6 @@
*/
package org.jclouds.ec2.xml;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
import static org.testng.Assert.assertEquals;
import java.io.InputStream;
@ -30,11 +27,9 @@ import org.jclouds.date.DateService;
import org.jclouds.ec2.domain.InstanceState;
import org.jclouds.ec2.domain.InstanceStateChange;
import org.jclouds.http.functions.ParseSax;
import org.jclouds.rest.internal.GeneratedHttpRequest;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
/**
@ -95,9 +90,6 @@ public class InstanceStateChangeHandlerTest extends BaseEC2HandlerTest {
}
private void addDefaultRegionToHandler(ParseSax.HandlerWithResult<?> handler) {
GeneratedHttpRequest request = createMock(GeneratedHttpRequest.class);
expect(request.getArgs()).andReturn(ImmutableList.<Object>of()).atLeastOnce();
replay(request);
handler.setContext(request);
}
}

View File

@ -17,10 +17,6 @@
* under the License.
*/
package org.jclouds.ec2.xml;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
import static org.testng.Assert.assertEquals;
import java.io.IOException;
@ -29,11 +25,8 @@ import java.io.InputStream;
import org.jclouds.crypto.SshKeys;
import org.jclouds.ec2.domain.KeyPair;
import org.jclouds.http.functions.ParseSax;
import org.jclouds.rest.internal.GeneratedHttpRequest;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableList;
/**
* Tests behavior of {@code KeyPairResponseHandler}
*
@ -84,9 +77,6 @@ public class KeyPairResponseHandlerTest extends BaseEC2HandlerTest {
}
private void addDefaultRegionToHandler(ParseSax.HandlerWithResult<?> handler) {
GeneratedHttpRequest request = createMock(GeneratedHttpRequest.class);
expect(request.getArgs()).andReturn(ImmutableList.<Object> of()).atLeastOnce();
replay(request);
handler.setContext(request);
}
}

View File

@ -18,9 +18,6 @@
*/
package org.jclouds.ec2.xml;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
import static org.testng.Assert.assertEquals;
import java.io.InputStream;
@ -32,11 +29,9 @@ import org.jclouds.ec2.domain.Reservation;
import org.jclouds.ec2.domain.RootDeviceType;
import org.jclouds.ec2.domain.RunningInstance;
import org.jclouds.http.functions.ParseSax;
import org.jclouds.rest.internal.GeneratedHttpRequest;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
/**
@ -112,9 +107,6 @@ public class RunInstancesResponseHandlerTest extends BaseEC2HandlerTest {
}
private void addDefaultRegionToHandler(ParseSax.HandlerWithResult<?> handler) {
GeneratedHttpRequest request = createMock(GeneratedHttpRequest.class);
expect(request.getArgs()).andReturn(ImmutableList.<Object> of()).atLeastOnce();
replay(request);
handler.setContext(request);
}
}

View File

@ -18,9 +18,6 @@
*/
package org.jclouds.ec2.xml;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
import static org.testng.Assert.assertEquals;
import java.io.InputStream;
@ -28,11 +25,8 @@ import java.io.InputStream;
import org.jclouds.date.DateService;
import org.jclouds.ec2.domain.Snapshot;
import org.jclouds.http.functions.ParseSax;
import org.jclouds.rest.internal.GeneratedHttpRequest;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableList;
/**
* Tests behavior of {@code SnapshotHandler}
*
@ -56,9 +50,6 @@ public class SnapshotHandlerTest extends BaseEC2HandlerTest {
}
private void addDefaultRegionToHandler(ParseSax.HandlerWithResult<?> handler) {
GeneratedHttpRequest request = createMock(GeneratedHttpRequest.class);
expect(request.getArgs()).andReturn(ImmutableList.<Object>of()).atLeastOnce();
replay(request);
handler.setContext(request);
}
}

View File

@ -20,7 +20,6 @@ package org.jclouds.openstack.keystone.v2_0.binders;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import java.util.Map;
@ -37,8 +36,8 @@ import org.jclouds.rest.internal.GeneratedHttpRequest;
import com.google.common.base.Predicates;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables;
import com.google.common.collect.ImmutableMap.Builder;
import com.google.common.collect.Iterables;
/**
*
@ -58,7 +57,7 @@ public class BindAuthToJsonPayload extends BindToJsonPayload implements MapBinde
}
protected void addCredentialsInArgsOrNull(GeneratedHttpRequest gRequest, Builder<String, Object> builder) {
for (Object arg : Iterables.filter(gRequest.getArgs(), Predicates.notNull())) {
for (Object arg : Iterables.filter(gRequest.getInvocation().getArgs(), Predicates.notNull())) {
if (arg.getClass().isAnnotationPresent(CredentialType.class)) {
builder.put(arg.getClass().getAnnotation(CredentialType.class).value(), arg);
}
@ -70,7 +69,6 @@ public class BindAuthToJsonPayload extends BindToJsonPayload implements MapBinde
checkArgument(checkNotNull(request, "request") instanceof GeneratedHttpRequest,
"this binder is only valid for GeneratedHttpRequests!");
GeneratedHttpRequest gRequest = (GeneratedHttpRequest) request;
checkState(gRequest.getArgs() != null, "args should be initialized at this point");
Builder<String, Object> builder = ImmutableMap.builder();
addCredentialsInArgsOrNull(gRequest, builder);

View File

@ -19,26 +19,28 @@
package org.jclouds.openstack.v2_0.functions;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.collect.Iterables.any;
import static org.jclouds.openstack.v2_0.predicates.ExtensionPredicates.namespaceOrAliasEquals;
import static org.jclouds.util.Optionals2.unwrapIfOptional;
import java.net.URI;
import java.util.List;
import java.util.Set;
import javax.inject.Inject;
import org.jclouds.internal.ClassInvokerArgsAndReturnVal;
import org.jclouds.openstack.v2_0.domain.Extension;
import org.jclouds.openstack.v2_0.predicates.ExtensionPredicates;
import org.jclouds.reflect.InvocationSuccess;
import org.jclouds.rest.functions.ImplicitOptionalConverter;
import com.google.common.base.Optional;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.Iterables;
import com.google.common.collect.Multimap;
/**
* We use the annotation {@link org.jclouds.openstack.services.Extension} to
* bind a class that implements an extension API to an {@link Extension}.
* We use the annotation {@link org.jclouds.openstack.services.Extension} to bind a class that implements an extension
* API to an {@link Extension}.
*
* @author Adrian Cole
*
@ -47,36 +49,36 @@ public class PresentWhenExtensionAnnotationNamespaceEqualsAnyNamespaceInExtensio
ImplicitOptionalConverter {
private final LoadingCache<String, Set<? extends Extension>> extensions;
private final Multimap<URI, URI> aliases;
@Inject
public PresentWhenExtensionAnnotationNamespaceEqualsAnyNamespaceInExtensionsSet(
LoadingCache<String, Set<? extends Extension>> extensions,
Multimap<URI, URI> aliases) {
LoadingCache<String, Set<? extends Extension>> extensions, Multimap<URI, URI> aliases) {
this.extensions = checkNotNull(extensions, "extensions");
this.aliases = aliases == null ? ImmutableMultimap.<URI, URI>of() : ImmutableMultimap.copyOf(aliases);
this.aliases = aliases == null ? ImmutableMultimap.<URI, URI> of() : ImmutableMultimap.copyOf(aliases);
}
@Override
public Optional<Object> apply(ClassInvokerArgsAndReturnVal input) {
Optional<org.jclouds.openstack.v2_0.services.Extension> ext = Optional.fromNullable(input.getClazz().getAnnotation(
org.jclouds.openstack.v2_0.services.Extension.class));
public Optional<Object> apply(InvocationSuccess input) {
Class<?> target = unwrapIfOptional(input.getInvocation().getInvokable().getReturnType());
Optional<org.jclouds.openstack.v2_0.services.Extension> ext = Optional.fromNullable(target
.getAnnotation(org.jclouds.openstack.v2_0.services.Extension.class));
if (ext.isPresent()) {
URI namespace = URI.create(ext.get().namespace());
if (input.getArgs().isEmpty()) {
if (Iterables.any(extensions.getUnchecked(""),
ExtensionPredicates.namespaceOrAliasEquals(namespace, aliases.get(namespace))))
return Optional.of(input.getReturnVal());
} else if (input.getArgs().size() == 1) {
if (Iterables.any(extensions.getUnchecked(checkNotNull(input.getArgs().get(0), "arg[0] in %s", input).toString()),
ExtensionPredicates.namespaceOrAliasEquals(namespace, aliases.get(namespace))))
return Optional.of(input.getReturnVal());
List<Object> args = input.getInvocation().getArgs();
if (args.isEmpty()) {
if (any(extensions.getUnchecked(""), namespaceOrAliasEquals(namespace, aliases.get(namespace))))
return input.getResult();
} else if (args.size() == 1) {
String arg0 = checkNotNull(args.get(0), "arg[0] in %s", input).toString();
if (any(extensions.getUnchecked(arg0), namespaceOrAliasEquals(namespace, aliases.get(namespace))))
return input.getResult();
} else {
throw new RuntimeException(String.format("expecting zero or one args %s", input));
}
return Optional.absent();
} else {
// No extension annotation, should check whether to return absent
return Optional.of(input.getReturnVal());
return input.getResult();
}
}

View File

@ -3,12 +3,14 @@ package org.jclouds.openstack.v2_0.functions;
import static org.testng.Assert.assertEquals;
import java.net.URI;
import java.util.List;
import java.util.Set;
import org.jclouds.date.internal.SimpleDateFormatDateService;
import org.jclouds.internal.ClassInvokerArgsAndReturnVal;
import org.jclouds.openstack.v2_0.ServiceType;
import org.jclouds.openstack.v2_0.domain.Extension;
import org.jclouds.reflect.Invocation;
import org.jclouds.reflect.InvocationSuccess;
import org.jclouds.rest.annotations.Delegate;
import org.testng.annotations.Test;
@ -63,34 +65,31 @@ public class PresentWhenExtensionAnnotationNamespaceEqualsAnyNamespaceInExtensio
}
ClassInvokerArgsAndReturnVal getFloatingIPExtension() throws SecurityException, NoSuchMethodException {
return ClassInvokerArgsAndReturnVal
.builder()
.clazz(FloatingIPAsyncApi.class)
.invoker(
Invokable.from(NovaAsyncApi.class.getDeclaredMethod("getFloatingIPExtensionForZone", String.class)))
.args(ImmutableList.<Object> of("zone")).returnVal("foo").build();
InvocationSuccess getFloatingIPExtension(List<Object> args) throws SecurityException, NoSuchMethodException {
return InvocationSuccess.create(Invocation.create(
Invokable.from(NovaAsyncApi.class.getDeclaredMethod("getFloatingIPExtensionForZone", String.class)),
args), "foo");
}
ClassInvokerArgsAndReturnVal getKeyPairExtension() throws SecurityException, NoSuchMethodException {
return ClassInvokerArgsAndReturnVal.builder().clazz(KeyPairAsyncApi.class)
.invoker(Invokable.from(NovaAsyncApi.class.getDeclaredMethod("getKeyPairExtensionForZone", String.class)))
.args(ImmutableList.<Object> of("zone")).returnVal("foo").build();
InvocationSuccess getKeyPairExtension(List<Object> args) throws SecurityException, NoSuchMethodException {
return InvocationSuccess.create(Invocation.create(
Invokable.from(NovaAsyncApi.class.getDeclaredMethod("getKeyPairExtensionForZone", String.class)),
args), "foo");
}
public void testPresentWhenExtensionsIncludeNamespaceFromAnnotationAbsentWhenNot() throws SecurityException, NoSuchMethodException {
assertEquals(whenExtensionsInZoneInclude("zone", keypairs, floatingIps).apply(getFloatingIPExtension()), Optional.of("foo"));
assertEquals(whenExtensionsInZoneInclude("zone", keypairs, floatingIps).apply(getKeyPairExtension()), Optional.of("foo"));
assertEquals(whenExtensionsInZoneInclude("zone", keypairs).apply(getFloatingIPExtension()), Optional.absent());
assertEquals(whenExtensionsInZoneInclude("zone", floatingIps).apply(getKeyPairExtension()), Optional.absent());
assertEquals(whenExtensionsInZoneInclude("zone", keypairs, floatingIps).apply(getFloatingIPExtension(ImmutableList.<Object> of("zone"))), Optional.of("foo"));
assertEquals(whenExtensionsInZoneInclude("zone", keypairs, floatingIps).apply(getKeyPairExtension(ImmutableList.<Object> of("zone"))), Optional.of("foo"));
assertEquals(whenExtensionsInZoneInclude("zone", keypairs).apply(getFloatingIPExtension(ImmutableList.<Object> of("zone"))), Optional.absent());
assertEquals(whenExtensionsInZoneInclude("zone", floatingIps).apply(getKeyPairExtension(ImmutableList.<Object> of("zone"))), Optional.absent());
}
public void testZoneWithoutExtensionsReturnsAbsent() throws SecurityException, NoSuchMethodException {
assertEquals(whenExtensionsInZoneInclude("zone", floatingIps).apply(
getFloatingIPExtension().toBuilder().args(ImmutableList.<Object> of("differentzone")).build()), Optional.absent());
getFloatingIPExtension(ImmutableList.<Object> of("differentzone"))), Optional.absent());
assertEquals(whenExtensionsInZoneInclude("zone", keypairs).apply(
getKeyPairExtension().toBuilder().args(ImmutableList.<Object> of("differentzone")).build()), Optional.absent());
getKeyPairExtension(ImmutableList.<Object> of("differentzone"))), Optional.absent());
}
/**
@ -107,9 +106,9 @@ public class PresentWhenExtensionAnnotationNamespaceEqualsAnyNamespaceInExtensio
.getNamespace());
assertEquals(whenExtensionsAndAliasesInZoneInclude("zone", ImmutableSet.of(keypairsWithDifferentNamespace), aliases).apply(
getKeyPairExtension()), Optional.of("foo"));
getKeyPairExtension(ImmutableList.<Object> of("zone"))), Optional.of("foo"));
assertEquals(whenExtensionsAndAliasesInZoneInclude("zone", ImmutableSet.of(keypairsWithDifferentNamespace), aliases).apply(
getFloatingIPExtension()), Optional.absent());
getFloatingIPExtension(ImmutableList.<Object> of("zone"))), Optional.absent());
}

View File

@ -20,6 +20,8 @@ package org.jclouds.openstack.nova.v2_0.binders;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Predicates.instanceOf;
import static com.google.common.collect.Iterables.find;
import java.util.Map;
@ -33,9 +35,7 @@ import org.jclouds.rest.MapBinder;
import org.jclouds.rest.binders.BindToJsonPayload;
import org.jclouds.rest.internal.GeneratedHttpRequest;
import com.google.common.base.Predicates;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables;
import com.google.common.collect.ImmutableMap.Builder;
/**
@ -63,7 +63,7 @@ public class BindSecurityGroupRuleToJsonPayload extends BindToJsonPayload implem
"this binder is only valid for GeneratedHttpRequests!");
GeneratedHttpRequest gRequest = (GeneratedHttpRequest) request;
Ingress ingress = Ingress.class.cast(Iterables.find(gRequest.getArgs(), Predicates.instanceOf(Ingress.class)));
Ingress ingress = Ingress.class.cast(find(gRequest.getInvocation().getArgs(), instanceOf(Ingress.class)));
payload.put("ip_protocol", ingress.getIpProtocol().toString());
payload.put("from_port", ingress.getFromPort() + "");
payload.put("to_port", ingress.getToPort() + "");

View File

@ -29,6 +29,7 @@ import org.jclouds.blobstore.domain.Blob;
import org.jclouds.blobstore.functions.BlobToHttpGetOptions;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.options.GetOptions;
import org.jclouds.reflect.Invocation;
import org.jclouds.rest.internal.RestAnnotationProcessor;
import org.jclouds.s3.S3AsyncClient;
import org.jclouds.s3.blobstore.functions.BlobToObject;
@ -37,13 +38,14 @@ import org.jclouds.s3.options.PutObjectOptions;
import com.google.common.collect.ImmutableList;
import com.google.common.reflect.Invokable;
import com.google.common.reflect.TypeToken;
/**
*
* @author Adrian Cole
*/
@Singleton
public class S3BlobRequestSigner implements BlobRequestSigner {
public class S3BlobRequestSigner<T extends S3AsyncClient> implements BlobRequestSigner {
private final RestAnnotationProcessor processor;
private final BlobToObject blobToObject;
private final BlobToHttpGetOptions blob2HttpGetOptions;
@ -51,26 +53,30 @@ public class S3BlobRequestSigner implements BlobRequestSigner {
private final Invokable<?, ?> getMethod;
private final Invokable<?, ?> deleteMethod;
private final Invokable<?, ?> createMethod;
private final Class<T> interfaceType;
@Inject
public S3BlobRequestSigner(RestAnnotationProcessor.Factory processor, BlobToObject blobToObject,
BlobToHttpGetOptions blob2HttpGetOptions) throws SecurityException, NoSuchMethodException {
this.processor = checkNotNull(processor, "processor").declaring(S3AsyncClient.class);
public S3BlobRequestSigner(RestAnnotationProcessor processor, BlobToObject blobToObject,
BlobToHttpGetOptions blob2HttpGetOptions, Class<T> interfaceType) throws SecurityException,
NoSuchMethodException {
this.processor = checkNotNull(processor, "processor");
this.interfaceType = checkNotNull(interfaceType, "interfaceType");
this.blobToObject = checkNotNull(blobToObject, "blobToObject");
this.blob2HttpGetOptions = checkNotNull(blob2HttpGetOptions, "blob2HttpGetOptions");
this.getMethod = Invokable.from(S3AsyncClient.class.getMethod("getObject", String.class, String.class,
GetOptions[].class));
this.deleteMethod = Invokable.from(S3AsyncClient.class.getMethod("deleteObject", String.class, String.class));
this.createMethod = Invokable.from(S3AsyncClient.class.getMethod("putObject", String.class, S3Object.class,
PutObjectOptions[].class));
this.getMethod = TypeToken.of(interfaceType).method(
interfaceType.getMethod("getObject", String.class, String.class, GetOptions[].class));
this.deleteMethod = TypeToken.of(interfaceType).method(
interfaceType.getMethod("deleteObject", String.class, String.class));
this.createMethod = TypeToken.of(interfaceType).method(
interfaceType.getMethod("putObject", String.class, S3Object.class, PutObjectOptions[].class));
}
@Override
public HttpRequest signGetBlob(String container, String name) {
checkNotNull(container, "container");
checkNotNull(name, "name");
return cleanRequest(processor.createRequest(getMethod, ImmutableList.<Object> of(container, name)));
return cleanRequest(processor.apply(Invocation.create(interfaceType, getMethod,
ImmutableList.<Object> of(container, name))));
}
@Override
@ -82,8 +88,8 @@ public class S3BlobRequestSigner implements BlobRequestSigner {
public HttpRequest signPutBlob(String container, Blob blob) {
checkNotNull(container, "container");
checkNotNull(blob, "blob");
return cleanRequest(processor.createRequest(createMethod,
ImmutableList.<Object> of(container, blobToObject.apply(blob))));
return cleanRequest(processor.apply(Invocation.create(interfaceType, createMethod,
ImmutableList.<Object> of(container, blobToObject.apply(blob)))));
}
@Override
@ -95,14 +101,15 @@ public class S3BlobRequestSigner implements BlobRequestSigner {
public HttpRequest signRemoveBlob(String container, String name) {
checkNotNull(container, "container");
checkNotNull(name, "name");
return cleanRequest(processor.createRequest(deleteMethod, ImmutableList.<Object> of(container, name)));
return cleanRequest(processor.apply(Invocation.create(interfaceType, deleteMethod,
ImmutableList.<Object> of(container, name))));
}
@Override
public HttpRequest signGetBlob(String container, String name, org.jclouds.blobstore.options.GetOptions options) {
checkNotNull(container, "container");
checkNotNull(name, "name");
return cleanRequest(processor.createRequest(getMethod,
ImmutableList.of(container, name, blob2HttpGetOptions.apply(checkNotNull(options, "options")))));
return cleanRequest(processor.apply(Invocation.create(interfaceType, getMethod,
ImmutableList.of(container, name, blob2HttpGetOptions.apply(checkNotNull(options, "options"))))));
}
}

View File

@ -28,10 +28,12 @@ import org.jclouds.blobstore.BlobStore;
import org.jclouds.blobstore.attr.ConsistencyModel;
import org.jclouds.blobstore.config.BlobStoreMapModule;
import org.jclouds.domain.Location;
import org.jclouds.s3.S3AsyncClient;
import org.jclouds.s3.S3Client;
import org.jclouds.s3.blobstore.S3AsyncBlobStore;
import org.jclouds.s3.blobstore.S3BlobRequestSigner;
import org.jclouds.s3.blobstore.S3BlobStore;
import org.jclouds.s3.blobstore.S3BlobStoreContext;
import org.jclouds.s3.blobstore.functions.LocationFromBucketName;
import org.jclouds.s3.domain.AccessControlList;
@ -57,11 +59,16 @@ public class S3BlobStoreContextModule extends AbstractModule {
bind(ConsistencyModel.class).toInstance(ConsistencyModel.EVENTUAL);
bind(AsyncBlobStore.class).to(S3AsyncBlobStore.class).in(Scopes.SINGLETON);
bind(BlobStore.class).to(S3BlobStore.class).in(Scopes.SINGLETON);
bind(BlobRequestSigner.class).to(S3BlobRequestSigner.class);
bind(new TypeLiteral<Function<String, Location>>() {
}).to(LocationFromBucketName.class);
bindRequestSigner();
}
protected void bindRequestSigner() {
bind(BlobRequestSigner.class).to(new TypeLiteral<S3BlobRequestSigner<S3AsyncClient>>() {
});
}
@Provides
@Singleton
protected LoadingCache<String, AccessControlList> bucketAcls(final S3Client client) {

View File

@ -59,7 +59,7 @@ public class BlobToObjectMetadata implements Function<BlobMetadata, MutableObjec
@Override
public BlobToObjectMetadata setContext(HttpRequest request) {
checkArgument(request instanceof GeneratedHttpRequest, "note this handler requires a GeneratedHttpRequest");
return setBucket(GeneratedHttpRequest.class.cast(request).getArgs().get(0).toString());
return setBucket(GeneratedHttpRequest.class.cast(request).getInvocation().getArgs().get(0).toString());
}
private BlobToObjectMetadata setBucket(String bucket) {

View File

@ -48,24 +48,23 @@ public class S3Utils {
public static String validateBucketName(String bucketName) {
checkNotNull(bucketName, "bucketName");
checkArgument(
BUCKET_NAME_PATTERN.matcher(bucketName).matches(),
"bucketName name must start with a number or letter and can only contain lowercase letters, numbers, periods (.), underscores (_), and dashes (-)");
BUCKET_NAME_PATTERN.matcher(bucketName).matches(),
"bucketName name must start with a number or letter and can only contain lowercase letters, numbers, periods (.), underscores (_), and dashes (-)");
checkArgument(bucketName.length() > 2 && bucketName.length() < 256,
"bucketName name must be between 3 and 255 characters long");
checkArgument(!IP_PATTERN.matcher(bucketName).matches(),
"bucketName name cannot be ip address style");
"bucketName name must be between 3 and 255 characters long");
checkArgument(!IP_PATTERN.matcher(bucketName).matches(), "bucketName name cannot be ip address style");
return bucketName;
}
/**
* This implementation invokes {@link S3Client#deleteBucketIfEmpty} followed by
* {@link S3Client#bucketExists} until it is true.
* This implementation invokes {@link S3Client#deleteBucketIfEmpty} followed by {@link S3Client#bucketExists} until
* it is true.
*/
public static boolean deleteAndVerifyContainerGone(S3Client sync, String container) {
sync.deleteBucketIfEmpty(container);
return !sync.bucketExists(container);
}
private static final Predicate<Annotation> ANNOTATIONTYPE_BUCKET = new Predicate<Annotation>() {
public boolean apply(Annotation input) {
return input.annotationType().equals(Bucket.class);
@ -78,9 +77,10 @@ public class S3Utils {
String bucketName = null;
for (int i = 0; i < request.getInvoker().getParameters().size(); i++) {
if (any(Arrays.asList(request.getInvoker().getParameters().get(i).getAnnotations()), ANNOTATIONTYPE_BUCKET)) {
bucketName = (String) request.getArgs().get(i);
for (int i = 0; i < request.getInvocation().getInvokable().getParameters().size(); i++) {
if (any(Arrays.asList(request.getInvocation().getInvokable().getParameters().get(i).getAnnotations()),
ANNOTATIONTYPE_BUCKET)) {
bucketName = (String) request.getInvocation().getArgs().get(i);
break;
}
}

View File

@ -64,7 +64,7 @@ public class LocationConstraintHandler extends ParseSax.HandlerWithResult<String
@Override
public LocationConstraintHandler setContext(HttpRequest request) {
super.setContext(request);
setBucket(GeneratedHttpRequest.class.cast(getRequest()).getArgs().get(0).toString());
setBucket(GeneratedHttpRequest.class.cast(getRequest()).getInvocation().getArgs().get(0).toString());
return this;
}

View File

@ -27,12 +27,14 @@ import static org.testng.Assert.assertFalse;
import org.jclouds.aws.AWSResponseException;
import org.jclouds.aws.domain.AWSError;
import org.jclouds.reflect.Invocation;
import org.jclouds.rest.internal.GeneratedHttpRequest;
import org.jclouds.s3.S3Client;
import org.jclouds.s3.options.PutBucketOptions;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import com.google.common.collect.Lists;
import com.google.common.reflect.Invokable;
/**
@ -45,14 +47,12 @@ public class FalseIfBucketAlreadyOwnedByYouOrOperationAbortedWhenBucketExistsTes
@BeforeClass
void setUp() throws SecurityException, NoSuchMethodException {
putBucket = GeneratedHttpRequest
.builder()
putBucket = GeneratedHttpRequest.builder()
.method("PUT")
.endpoint("https://adriancole-blobstore113.s3.amazonaws.com/")
.declaring(S3Client.class)
.invoker(Invokable.from(
S3Client.class.getMethod("putBucketInRegion", String.class, String.class, PutBucketOptions[].class)))
.args(new Object[] { null, "bucket" }).build();
.invocation(
Invocation.create(Invokable.from(S3Client.class.getMethod("putBucketInRegion", String.class,
String.class, PutBucketOptions[].class)), Lists.<Object> newArrayList(null, "bucket"))).build();
}
@Test

View File

@ -40,7 +40,6 @@ import org.jclouds.blobstore.binders.BindMapToHeadersWithPrefix;
import org.jclouds.blobstore.domain.PageSet;
import org.jclouds.http.functions.ParseETagHeader;
import org.jclouds.http.options.GetOptions;
import org.jclouds.openstack.filters.AuthenticateRequest;
import org.jclouds.openstack.swift.SwiftFallbacks.TrueOn404FalseOn409;
import org.jclouds.openstack.swift.binders.BindIterableToHeadersWithContainerDeleteMetadataPrefix;
import org.jclouds.openstack.swift.binders.BindMapToHeadersWithContainerMetadataPrefix;
@ -60,12 +59,10 @@ import org.jclouds.openstack.swift.options.CreateContainerOptions;
import org.jclouds.openstack.swift.options.ListContainerOptions;
import org.jclouds.openstack.swift.reference.SwiftHeaders;
import org.jclouds.rest.annotations.BinderParam;
import org.jclouds.rest.annotations.Endpoint;
import org.jclouds.rest.annotations.Fallback;
import org.jclouds.rest.annotations.Headers;
import org.jclouds.rest.annotations.ParamParser;
import org.jclouds.rest.annotations.QueryParams;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.ResponseParser;
import com.google.common.annotations.Beta;
@ -79,8 +76,6 @@ import com.google.inject.Provides;
* @see <a href="http://www.rackspacecloud.com/cf-devguide-20090812.pdf" />
* @author Adrian Cole
*/
@RequestFilters(AuthenticateRequest.class)
@Endpoint(Storage.class)
public interface CommonSwiftAsyncClient {
@Provides
SwiftObject newSwiftObject();

View File

@ -45,6 +45,7 @@ import org.jclouds.openstack.swift.CommonSwiftAsyncClient;
import org.jclouds.openstack.swift.TemporaryUrlKey;
import org.jclouds.openstack.swift.blobstore.functions.BlobToObject;
import org.jclouds.openstack.swift.domain.SwiftObject;
import org.jclouds.reflect.Invocation;
import org.jclouds.rest.internal.RestAnnotationProcessor;
import com.google.common.base.Supplier;
@ -53,6 +54,7 @@ import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.io.ByteProcessor;
import com.google.common.reflect.Invokable;
import com.google.common.reflect.TypeToken;
import com.google.inject.Provider;
/**
@ -73,6 +75,7 @@ public class SwiftBlobSigner<T extends CommonSwiftAsyncClient> implements BlobRe
private final Invokable<?, ?> getMethod;
private final Invokable<?, ?> deleteMethod;
private final Invokable<?, ?> createMethod;
private final Class<T> interfaceType;
/**
* create a signer for this subtype of swift
@ -83,9 +86,10 @@ public class SwiftBlobSigner<T extends CommonSwiftAsyncClient> implements BlobRe
@Inject
protected SwiftBlobSigner(BlobToObject blobToObject, BlobToHttpGetOptions blob2HttpGetOptions, Crypto crypto,
@TimeStamp Provider<Long> unixEpochTimestampProvider,
@TemporaryUrlKey Supplier<String> temporaryUrlKeySupplier, RestAnnotationProcessor.Factory processor,
Class<T> clazz) throws SecurityException, NoSuchMethodException {
this.processor = checkNotNull(processor, "processor").declaring(clazz);
@TemporaryUrlKey Supplier<String> temporaryUrlKeySupplier, RestAnnotationProcessor processor,
Class<T> interfaceType) throws SecurityException, NoSuchMethodException {
this.processor = checkNotNull(processor, "processor");
this.interfaceType = checkNotNull(interfaceType, "interfaceType");
this.crypto = checkNotNull(crypto, "crypto");
this.unixEpochTimestampProvider = checkNotNull(unixEpochTimestampProvider, "unixEpochTimestampProvider");
@ -94,23 +98,28 @@ public class SwiftBlobSigner<T extends CommonSwiftAsyncClient> implements BlobRe
this.blobToObject = checkNotNull(blobToObject, "blobToObject");
this.blob2HttpGetOptions = checkNotNull(blob2HttpGetOptions, "blob2HttpGetOptions");
this.getMethod = Invokable.from(clazz.getMethod("getObject", String.class, String.class, GetOptions[].class));
this.deleteMethod = Invokable.from(clazz.getMethod("removeObject", String.class, String.class));
this.createMethod = Invokable.from(clazz.getMethod("putObject", String.class, SwiftObject.class));
this.getMethod = TypeToken.of(interfaceType).method(
interfaceType.getMethod("getObject", String.class, String.class, GetOptions[].class));
this.deleteMethod = TypeToken.of(interfaceType).method(
interfaceType.getMethod("removeObject", String.class, String.class));
this.createMethod = TypeToken.of(interfaceType).method(
interfaceType.getMethod("putObject", String.class, SwiftObject.class));
}
@Override
public HttpRequest signGetBlob(String container, String name) {
checkNotNull(container, "container");
checkNotNull(name, "name");
return cleanRequest(processor.createRequest(getMethod, ImmutableList.<Object> of(container, name)));
return cleanRequest(processor.apply(Invocation.create(interfaceType, getMethod,
ImmutableList.<Object> of(container, name))));
}
@Override
public HttpRequest signGetBlob(String container, String name, long timeInSeconds) {
checkNotNull(container, "container");
checkNotNull(name, "name");
HttpRequest request = processor.createRequest(getMethod, ImmutableList.<Object> of(container, name));
HttpRequest request = processor.apply(Invocation.create(interfaceType, getMethod,
ImmutableList.<Object> of(container, name)));
return cleanRequest(signForTemporaryAccess(request, timeInSeconds));
}
@ -118,24 +127,24 @@ public class SwiftBlobSigner<T extends CommonSwiftAsyncClient> implements BlobRe
public HttpRequest signGetBlob(String container, String name, org.jclouds.blobstore.options.GetOptions options) {
checkNotNull(container, "container");
checkNotNull(name, "name");
return cleanRequest(processor.createRequest(getMethod,
ImmutableList.of(container, name, blob2HttpGetOptions.apply(checkNotNull(options, "options")))));
return cleanRequest(processor.apply(Invocation.create(interfaceType, getMethod,
ImmutableList.of(container, name, blob2HttpGetOptions.apply(checkNotNull(options, "options"))))));
}
@Override
public HttpRequest signPutBlob(String container, Blob blob) {
checkNotNull(container, "container");
checkNotNull(blob, "blob");
return cleanRequest(processor.createRequest(createMethod,
ImmutableList.<Object> of(container, blobToObject.apply(blob))));
return cleanRequest(processor.apply(Invocation.create(interfaceType, createMethod,
ImmutableList.<Object> of(container, blobToObject.apply(blob)))));
}
@Override
public HttpRequest signPutBlob(String container, Blob blob, long timeInSeconds) {
checkNotNull(container, "container");
checkNotNull(blob, "blob");
HttpRequest request = processor.createRequest(createMethod,
ImmutableList.<Object> of(container, blobToObject.apply(blob)));
HttpRequest request = processor.apply(Invocation.create(interfaceType, createMethod,
ImmutableList.<Object> of(container, blobToObject.apply(blob))));
return cleanRequest(signForTemporaryAccess(request, timeInSeconds));
}
@ -143,7 +152,8 @@ public class SwiftBlobSigner<T extends CommonSwiftAsyncClient> implements BlobRe
public HttpRequest signRemoveBlob(String container, String name) {
checkNotNull(container, "container");
checkNotNull(name, "name");
return cleanRequest(processor.createRequest(deleteMethod, ImmutableList.<Object> of(container, name)));
return cleanRequest(processor.apply(Invocation.create(interfaceType, deleteMethod,
ImmutableList.<Object> of(container, name))));
}
private HttpRequest signForTemporaryAccess(HttpRequest request, long timeInSeconds) {

View File

@ -45,7 +45,7 @@ public class ParseContainerMetadataFromHeaders implements Function<HttpResponse,
private GeneratedHttpRequest request;
public ContainerMetadata apply(HttpResponse from) {
return ContainerMetadata.builder().name(request.getArgs().get(0).toString())
return ContainerMetadata.builder().name(request.getInvocation().getArgs().get(0).toString())
.readACL(from.getFirstHeaderOrNull(SwiftHeaders.CONTAINER_READ))
.bytes(Long.valueOf(from.getFirstHeaderOrNull(SwiftHeaders.CONTAINER_BYTES_USED)))
.count(Long.valueOf(from.getFirstHeaderOrNull(SwiftHeaders.CONTAINER_OBJECT_COUNT)))

View File

@ -73,7 +73,7 @@ public class ParseObjectInfoFromHeaders implements Function<HttpResponse, Mutabl
public ParseObjectInfoFromHeaders setContext(HttpRequest request) {
blobMetadataParser.setContext(request);
checkArgument(request instanceof GeneratedHttpRequest, "note this handler requires a GeneratedHttpRequest");
return setContainer(GeneratedHttpRequest.class.cast(request).getArgs().get(0).toString());
return setContainer(GeneratedHttpRequest.class.cast(request).getInvocation().getArgs().get(0).toString());
}
private ParseObjectInfoFromHeaders setContainer(String container) {

View File

@ -25,6 +25,7 @@ import static org.jclouds.http.Uris.uriBuilder;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Type;
import java.util.List;
import java.util.SortedSet;
import javax.inject.Inject;
@ -52,10 +53,12 @@ import com.google.inject.TypeLiteral;
* @author Adrian Cole
*/
public class ParseObjectInfoListFromJsonResponse extends ParseJson<PageSet<ObjectInfo>> implements
InvocationContext<ParseObjectInfoListFromJsonResponse> {
InvocationContext<ParseObjectInfoListFromJsonResponse> {
private GeneratedHttpRequest request;
private List<Object> args;
private String container;
private GeneratedHttpRequest request;
private ListContainerOptions options;
@Inject
public ParseObjectInfoListFromJsonResponse(Json json) {
@ -64,26 +67,20 @@ public class ParseObjectInfoListFromJsonResponse extends ParseJson<PageSet<Objec
}
public PageSet<ObjectInfo> apply(InputStream stream) {
checkState(request != null, "request should be initialized at this point");
checkState(request.getArgs() != null, "request.getArgs() should be initialized at this point");
checkArgument(request.getArgs().get(0) instanceof String, "arg[0] must be a container name");
checkArgument(request.getArgs().get(1) instanceof ListContainerOptions[],
"arg[1] must be an array of ListContainerOptions");
ListContainerOptions[] optionsList = (ListContainerOptions[]) request.getArgs().get(1);
ListContainerOptions options = optionsList.length > 0 ? optionsList[0] : ListContainerOptions.NONE;
checkState(args != null, "request should be initialized at this point");
Type listType = new TypeToken<SortedSet<ObjectInfoImpl>>() {
}.getType();
try {
SortedSet<ObjectInfoImpl> list = apply(stream, listType);
SortedSet<ObjectInfo> returnVal = Sets.newTreeSet(Iterables.transform(list,
new Function<ObjectInfoImpl, ObjectInfo>() {
public ObjectInfo apply(ObjectInfoImpl from) {
new Function<ObjectInfoImpl, ObjectInfo>() {
public ObjectInfo apply(ObjectInfoImpl from) {
return from.toBuilder().container(container)
.uri(uriBuilder(request.getEndpoint()).clearQuery().appendPath(from.getName()).build())
.build();
}
}));
}
}));
boolean truncated = options.getMaxResults() == returnVal.size();
String marker = truncated ? returnVal.last().getName() : null;
return new PageSetImpl<ObjectInfo>(returnVal, marker);
@ -95,12 +92,13 @@ public class ParseObjectInfoListFromJsonResponse extends ParseJson<PageSet<Objec
@Override
public ParseObjectInfoListFromJsonResponse setContext(HttpRequest request) {
checkArgument(request instanceof GeneratedHttpRequest, "note this handler requires a GeneratedHttpRequest");
this.request = (GeneratedHttpRequest) request;
return setContainer(GeneratedHttpRequest.class.cast(request).getArgs().get(0).toString());
}
private ParseObjectInfoListFromJsonResponse setContainer(String container) {
this.container = container;
this.request = GeneratedHttpRequest.class.cast(request);
this.args = this.request.getInvocation().getArgs();
checkArgument(args.get(0) instanceof String, "arg[0] must be a container name");
this.container = args.get(0).toString();
checkArgument(args.get(1) instanceof ListContainerOptions[], "arg[1] must be an array of ListContainerOptions");
ListContainerOptions[] optionsList = (ListContainerOptions[]) args.get(1);
this.options = optionsList.length > 0 ? optionsList[0] : ListContainerOptions.NONE;
return this;
}
}

View File

@ -19,9 +19,6 @@
package org.jclouds.openstack.swift.domain.internal;
import static com.google.common.io.BaseEncoding.base16;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
import static org.testng.Assert.assertEquals;
import java.io.InputStream;
@ -29,20 +26,15 @@ import java.net.URI;
import java.util.Set;
import org.jclouds.date.internal.SimpleDateFormatDateService;
import org.jclouds.json.config.GsonModule;
import org.jclouds.json.config.GsonModule.DateAdapter;
import org.jclouds.json.config.GsonModule.Iso8601DateAdapter;
import org.jclouds.openstack.swift.domain.ObjectInfo;
import org.jclouds.openstack.swift.functions.ParseObjectInfoListFromJsonResponse;
import org.jclouds.openstack.swift.internal.BasePayloadTest;
import org.jclouds.openstack.swift.options.ListContainerOptions;
import org.jclouds.rest.internal.GeneratedHttpRequest;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Injector;
/**
* Tests behavior of {@code ParseObjectInfoListFromJsonResponse}
@ -50,35 +42,26 @@ import com.google.inject.Injector;
* @author Adrian Cole
*/
@Test(groups = "unit")
public class ParseObjectInfoListFromJsonResponseTest {
Injector i = Guice.createInjector(new AbstractModule() {
@Override
protected void configure() {
bind(DateAdapter.class).to(Iso8601DateAdapter.class);
}
}, new GsonModule());
public class ParseObjectInfoListFromJsonResponseTest extends BasePayloadTest {
public void testApplyInputStream() {
InputStream is = getClass().getResourceAsStream("/test_list_container.json");
Set<ObjectInfo> expects = ImmutableSet.<ObjectInfo> of(ObjectInfoImpl.builder().container("container").name(
"test_obj_1").uri(URI.create("http://localhost/foo/test_obj_1")).hash(
base16().lowerCase().decode("4281c348eaf83e70ddce0e07221c3d28")).bytes(14l)
.contentType("application/octet-stream").lastModified(
new SimpleDateFormatDateService().iso8601DateParse("2009-02-03T05:26:32.612Z")).build(),
ObjectInfoImpl.builder().container("container").name("test_obj_2").uri(
URI.create("http://localhost/foo/test_obj_2")).hash(
base16().lowerCase().decode("b039efe731ad111bc1b0ef221c3849d0")).bytes(64l).contentType(
"application/octet-stream").lastModified(
new SimpleDateFormatDateService().iso8601DateParse("2009-02-03T05:26:32.612Z")).build());
GeneratedHttpRequest request = createMock(GeneratedHttpRequest.class);
ListContainerOptions options = new ListContainerOptions();
expect(request.getEndpoint()).andReturn(URI.create("http://localhost/foo")).atLeastOnce();
expect(request.getArgs()).andReturn(
ImmutableList.<Object> of("container", new ListContainerOptions[] { options })).atLeastOnce();
replay(request);
Set<ObjectInfo> expects = ImmutableSet
.<ObjectInfo> of(
ObjectInfoImpl.builder().container("container").name("test_obj_1")
.uri(URI.create("http://localhost/key/test_obj_1"))
.hash(base16().lowerCase().decode("4281c348eaf83e70ddce0e07221c3d28")).bytes(14l)
.contentType("application/octet-stream")
.lastModified(new SimpleDateFormatDateService().iso8601DateParse("2009-02-03T05:26:32.612Z"))
.build(),
ObjectInfoImpl.builder().container("container").name("test_obj_2")
.uri(URI.create("http://localhost/key/test_obj_2"))
.hash(base16().lowerCase().decode("b039efe731ad111bc1b0ef221c3849d0")).bytes(64l)
.contentType("application/octet-stream")
.lastModified(new SimpleDateFormatDateService().iso8601DateParse("2009-02-03T05:26:32.612Z"))
.build());
GeneratedHttpRequest request = requestForArgs(ImmutableList.<Object> of("container",
new ListContainerOptions[] { new ListContainerOptions() }));
ParseObjectInfoListFromJsonResponse parser = i.getInstance(ParseObjectInfoListFromJsonResponse.class);
parser.setContext(request);
assertEquals(parser.apply(is).toString(), expects.toString());

View File

@ -26,15 +26,13 @@ import java.util.Map;
import org.jclouds.http.HttpResponse;
import org.jclouds.http.functions.ParseJson;
import org.jclouds.json.config.GsonModule;
import org.jclouds.openstack.swift.domain.ContainerMetadata;
import org.jclouds.openstack.swift.internal.BasePayloadTest;
import org.jclouds.util.Strings2;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Maps;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Key;
import com.google.inject.TypeLiteral;
@ -44,8 +42,7 @@ import com.google.inject.TypeLiteral;
* @author Adrian Cole
*/
@Test(groups = "unit")
public class ParseContainerListFromJsonResponseTest {
Injector i = Guice.createInjector(new GsonModule());
public class ParseContainerListFromJsonResponseTest extends BasePayloadTest {
@Test
public void testApplyInputStream() {

View File

@ -18,24 +18,15 @@
*/
package org.jclouds.openstack.swift.functions;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
import static org.testng.Assert.assertEquals;
import java.net.URI;
import org.jclouds.http.HttpResponse;
import org.jclouds.openstack.swift.domain.ContainerMetadata;
import org.jclouds.openstack.swift.functions.ParseContainerMetadataFromHeaders;
import org.jclouds.openstack.swift.internal.BasePayloadTest;
import org.jclouds.openstack.swift.reference.SwiftHeaders;
import org.jclouds.rest.internal.GeneratedHttpRequest;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableList;
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Injector;
/**
* Tests behavior of {@code ParseContainerMetadataFromHeaders}
@ -43,22 +34,12 @@ import com.google.inject.Injector;
* @author Everett Toews
*/
@Test(groups = "unit")
public class ParseContainerMetadataFromHeadersTest {
Injector i = Guice.createInjector(new AbstractModule() {
@Override
protected void configure() {
}
});
public class ParseContainerMetadataFromHeadersTest extends BasePayloadTest {
public void testParseContainerMetadataHeaders() {
ParseContainerMetadataFromHeaders parser = i.getInstance(ParseContainerMetadataFromHeaders.class);
GeneratedHttpRequest request = createMock(GeneratedHttpRequest.class);
expect(request.getArgs()).andReturn(ImmutableList.<Object> of("container", "key")).atLeastOnce();
expect(request.getEndpoint()).andReturn(URI.create("http://localhost/test")).atLeastOnce();
replay(request);
parser.setContext(request);
parser.setContext(requestForArgs(ImmutableList.<Object> of("container", "key")));
HttpResponse response = HttpResponse.builder().statusCode(204).message("No Content").payload("")
.addHeader(SwiftHeaders.CONTAINER_BYTES_USED, "42")

View File

@ -18,25 +18,14 @@
*/
package org.jclouds.openstack.swift.functions;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
import static org.testng.Assert.assertNotNull;
import java.net.URI;
import org.jclouds.Constants;
import org.jclouds.blobstore.reference.BlobStoreConstants;
import org.jclouds.http.HttpResponse;
import org.jclouds.openstack.swift.domain.MutableObjectInfoWithMetadata;
import org.jclouds.rest.internal.GeneratedHttpRequest;
import org.jclouds.openstack.swift.internal.BasePayloadTest;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableList;
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.name.Names;
/**
* Tests behavior of {@code ParseContainerListFromJsonResponse}
@ -44,26 +33,13 @@ import com.google.inject.name.Names;
* @author Adrian Cole
*/
@Test(groups = "unit")
public class ParseObjectInfoFromHeadersTest {
Injector i = Guice.createInjector(new AbstractModule() {
@Override
protected void configure() {
bindConstant().annotatedWith(Names.named(BlobStoreConstants.PROPERTY_USER_METADATA_PREFIX)).to("sdf");
bindConstant().annotatedWith(Names.named(Constants.PROPERTY_API_VERSION)).to("1");
}
});
public class ParseObjectInfoFromHeadersTest extends BasePayloadTest {
public void testEtagCaseIssue() {
ParseObjectInfoFromHeaders parser = i.getInstance(ParseObjectInfoFromHeaders.class);
GeneratedHttpRequest request = createMock(GeneratedHttpRequest.class);
expect(request.getArgs()).andReturn(ImmutableList.<Object> of("container", "key")).atLeastOnce();
parser.setContext(requestForArgs(ImmutableList.<Object> of("container", "key")));
expect(request.getEndpoint()).andReturn(URI.create("http://localhost/test")).atLeastOnce();
replay(request);
parser.setContext(request);
HttpResponse response = HttpResponse.builder().statusCode(200).message("ok").payload("")
.addHeader("Last-Modified", "Fri, 12 Jun 2007 13:40:18 GMT")
.addHeader("Content-Length", "0")

View File

@ -0,0 +1,57 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds 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.openstack.swift.internal;
import java.net.URI;
import java.util.List;
import org.jclouds.json.config.GsonModule;
import org.jclouds.json.config.GsonModule.DateAdapter;
import org.jclouds.json.config.GsonModule.Iso8601DateAdapter;
import org.jclouds.openstack.swift.SwiftApiMetadata;
import org.jclouds.reflect.Invocation;
import org.jclouds.rest.internal.GeneratedHttpRequest;
import org.nnsoft.guice.rocoto.Rocoto;
import org.nnsoft.guice.rocoto.configuration.ConfigurationModule;
import com.google.common.base.Throwables;
import com.google.common.reflect.Invokable;
import com.google.inject.Guice;
import com.google.inject.Injector;
public class BasePayloadTest {
protected Injector i = Guice.createInjector(Rocoto.expandVariables(new ConfigurationModule() {
protected void bindConfigurations() {
bindProperties(new SwiftApiMetadata().getDefaultProperties());
bind(DateAdapter.class).to(Iso8601DateAdapter.class);
}
}), new GsonModule());
protected GeneratedHttpRequest requestForArgs(List<Object> args) {
try {
Invocation invocation = Invocation.create(Invokable.from(String.class.getDeclaredMethod("toString")), args);
return GeneratedHttpRequest.builder().method("POST").endpoint(URI.create("http://localhost/key"))
.invocation(invocation).build();
} catch (SecurityException e) {
throw Throwables.propagate(e);
} catch (NoSuchMethodException e) {
throw Throwables.propagate(e);
}
}
}

View File

@ -20,7 +20,6 @@ package org.jclouds.vcloud.binders;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import static org.jclouds.vcloud.reference.VCloudConstants.PROPERTY_VCLOUD_XML_NAMESPACE;
import static org.jclouds.vcloud.reference.VCloudConstants.PROPERTY_VCLOUD_XML_SCHEMA;
@ -68,7 +67,6 @@ public class BindCaptureVAppParamsToXmlPayload implements MapBinder {
checkArgument(checkNotNull(request, "request") instanceof GeneratedHttpRequest,
"this binder is only valid for GeneratedHttpRequests!");
GeneratedHttpRequest gRequest = (GeneratedHttpRequest) request;
checkState(gRequest.getArgs() != null, "args should be initialized at this point");
String templateName = checkNotNull(postParams.remove("templateName"), "templateName").toString();
String vApp = checkNotNull(postParams.remove("vApp"), "vApp").toString();
@ -106,7 +104,7 @@ public class BindCaptureVAppParamsToXmlPayload implements MapBinder {
}
protected CaptureVAppOptions findOptionsInArgsOrNull(GeneratedHttpRequest gRequest) {
for (Object arg : gRequest.getArgs()) {
for (Object arg : gRequest.getInvocation().getArgs()) {
if (arg instanceof CaptureVAppOptions) {
return (CaptureVAppOptions) arg;
} else if (arg instanceof CaptureVAppOptions[]) {

View File

@ -20,7 +20,6 @@ package org.jclouds.vcloud.binders;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import static org.jclouds.vcloud.reference.VCloudConstants.PROPERTY_VCLOUD_XML_NAMESPACE;
import static org.jclouds.vcloud.reference.VCloudConstants.PROPERTY_VCLOUD_XML_SCHEMA;
@ -69,7 +68,6 @@ public class BindCatalogItemToXmlPayload implements MapBinder {
checkArgument(checkNotNull(request, "request") instanceof GeneratedHttpRequest,
"this binder is only valid for GeneratedHttpRequests!");
GeneratedHttpRequest gRequest = (GeneratedHttpRequest) request;
checkState(gRequest.getArgs() != null, "args should be initialized at this point");
String name = checkNotNull(postParams.get("name"), "name").toString();
URI entity = URI.create(checkNotNull(postParams.get("Entity"), "Entity").toString());
@ -107,7 +105,7 @@ public class BindCatalogItemToXmlPayload implements MapBinder {
}
protected CatalogItemOptions findOptionsInArgsOrNew(GeneratedHttpRequest gRequest) {
for (Object arg : gRequest.getArgs()) {
for (Object arg : gRequest.getInvocation().getArgs()) {
if (arg instanceof CatalogItemOptions) {
return CatalogItemOptions.class.cast(arg);
} else if (arg.getClass().isArray()) {

View File

@ -20,7 +20,6 @@ package org.jclouds.vcloud.binders;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import static org.jclouds.vcloud.reference.VCloudConstants.PROPERTY_VCLOUD_XML_NAMESPACE;
import static org.jclouds.vcloud.reference.VCloudConstants.PROPERTY_VCLOUD_XML_SCHEMA;
@ -69,7 +68,6 @@ public abstract class BindCloneParamsToXmlPayload<O extends CloneOptions> implem
checkArgument(checkNotNull(request, "request") instanceof GeneratedHttpRequest,
"this binder is only valid for GeneratedHttpRequests!");
GeneratedHttpRequest gRequest = (GeneratedHttpRequest) request;
checkState(gRequest.getArgs() != null, "args should be initialized at this point");
String name = checkNotNull(postParams.get("name"), "name").toString();
String source = checkNotNull(postParams.get("Source"), "Source").toString();
boolean isSourceDelete = Boolean.parseBoolean((String) postParams.get("IsSourceDelete"));
@ -110,7 +108,7 @@ public abstract class BindCloneParamsToXmlPayload<O extends CloneOptions> implem
@SuppressWarnings("unchecked")
protected O findOptionsInArgsOrNew(GeneratedHttpRequest gRequest) {
for (Object arg : gRequest.getArgs()) {
for (Object arg : gRequest.getInvocation().getArgs()) {
if (getOptionClass().isInstance(arg)) {
return (O) arg;
} else if (arg.getClass().isArray()) {

View File

@ -20,7 +20,6 @@ package org.jclouds.vcloud.binders;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import static com.google.common.collect.Iterables.transform;
import static org.jclouds.vcloud.reference.VCloudConstants.PROPERTY_VCLOUD_XML_NAMESPACE;
import static org.jclouds.vcloud.reference.VCloudConstants.PROPERTY_VCLOUD_XML_SCHEMA;
@ -92,7 +91,6 @@ public class BindInstantiateVAppTemplateParamsToXmlPayload implements MapBinder
checkArgument(checkNotNull(request, "request") instanceof GeneratedHttpRequest,
"this binder is only valid for GeneratedHttpRequests!");
GeneratedHttpRequest gRequest = (GeneratedHttpRequest) request;
checkState(gRequest.getArgs() != null, "args should be initialized at this point");
String name = checkNotNull(postParams.remove("name"), "name").toString();
URI template = URI.create(checkNotNull(postParams.remove("template"), "template").toString());
@ -203,7 +201,7 @@ public class BindInstantiateVAppTemplateParamsToXmlPayload implements MapBinder
}
protected InstantiateVAppTemplateOptions findOptionsInArgsOrNull(GeneratedHttpRequest gRequest) {
for (Object arg : gRequest.getArgs()) {
for (Object arg : gRequest.getInvocation().getArgs()) {
if (arg instanceof InstantiateVAppTemplateOptions) {
return (InstantiateVAppTemplateOptions) arg;
} else if (arg instanceof InstantiateVAppTemplateOptions[]) {

View File

@ -18,26 +18,18 @@
*/
package org.jclouds.vcloud.binders;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.verify;
import static org.testng.Assert.assertEquals;
import java.io.IOException;
import java.net.URI;
import java.util.Map;
import org.jclouds.rest.internal.GeneratedHttpRequest;
import org.jclouds.vcloud.VCloudApiMetadata;
import org.jclouds.vcloud.internal.BasePayloadTest;
import org.jclouds.vcloud.options.CatalogItemOptions;
import org.nnsoft.guice.rocoto.Rocoto;
import org.nnsoft.guice.rocoto.configuration.ConfigurationModule;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.inject.Guice;
import com.google.inject.Injector;
/**
* Tests behavior of {@code BindCatalogItemToXmlPayload}
@ -45,31 +37,19 @@ import com.google.inject.Injector;
* @author Adrian Cole
*/
@Test(groups = "unit")
public class BindCatalogItemToXmlPayloadTest {
Injector injector = Guice.createInjector(Rocoto.expandVariables(new ConfigurationModule() {
@Override
protected void bindConfigurations() {
bindProperties(new VCloudApiMetadata().getDefaultProperties());
}
}));
public class BindCatalogItemToXmlPayloadTest extends BasePayloadTest {
public void testDefault() throws IOException {
String expected = "<CatalogItem xmlns=\"http://www.vmware.com/vcloud/v1\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" name=\"myname\" xsi:schemaLocation=\"http://www.vmware.com/vcloud/v1 http://vcloud.safesecureweb.com/ns/vcloud.xsd\"><Description>mydescription</Description><Entity href=\"http://fooentity\"/><Property key=\"foo\">bar</Property></CatalogItem>";
GeneratedHttpRequest request = createMock(GeneratedHttpRequest.class);
expect(request.getEndpoint()).andReturn(URI.create("http://localhost/key")).anyTimes();
expect(request.getArgs()).andReturn(
ImmutableList.<Object> of(CatalogItemOptions.Builder.description("mydescription").properties(
ImmutableMap.of("foo", "bar")))).anyTimes();
request.setPayload(expected);
replay(request);
CatalogItemOptions options = CatalogItemOptions.Builder.description("mydescription").properties(
ImmutableMap.of("foo", "bar"));
GeneratedHttpRequest request = requestForArgs(ImmutableList.<Object> of(options));
BindCatalogItemToXmlPayload binder = injector.getInstance(BindCatalogItemToXmlPayload.class);
Map<String, Object> map = ImmutableMap.<String, Object>of("name", "myname", "Entity", "http://fooentity");
Map<String, Object> map = ImmutableMap.<String, Object> of("name", "myname", "Entity", "http://fooentity");
binder.bindToRequest(request, map);
verify(request);
assertEquals(binder.bindToRequest(request, map).getPayload().getRawContent(), expected);
}
}

View File

@ -20,21 +20,15 @@ package org.jclouds.vcloud.binders;
import static org.testng.Assert.assertEquals;
import java.util.Properties;
import org.jclouds.rest.internal.GeneratedHttpRequest;
import org.jclouds.util.Strings2;
import org.jclouds.vcloud.VCloudApiMetadata;
import org.jclouds.vcloud.internal.BasePayloadTest;
import org.jclouds.vcloud.options.CloneVAppOptions;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableMap.Builder;
import com.google.common.reflect.Invokable;
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.name.Names;
/**
* Tests behavior of {@code BindCloneVAppParamsToXmlPayload}
@ -42,26 +36,15 @@ import com.google.inject.name.Names;
* @author Adrian Cole
*/
@Test(groups = "unit")
public class BindCloneVAppParamsToXmlPayloadTest {
Injector injector = Guice.createInjector(new AbstractModule() {
@Override
protected void configure() {
Properties props = new VCloudApiMetadata().getDefaultProperties();
props.setProperty("jclouds.vcloud.xml.ns", "http://www.vmware.com/vcloud/v1");
props.setProperty("jclouds.vcloud.xml.schema", "http://vcloud.safesecureweb.com/ns/vcloud.xsd");
Names.bindProperties(binder(), props);
}
});
public class BindCloneVAppParamsToXmlPayloadTest extends BasePayloadTest {
public void testWithDescriptionDeployOn() throws Exception {
String expected = Strings2.toStringAndClose(getClass().getResourceAsStream("/copyVApp.xml"));
CloneVAppOptions options = new CloneVAppOptions().deploy().powerOn().description(
"The description of the new vApp");
GeneratedHttpRequest request = GeneratedHttpRequest.builder().method("POST").endpoint("http://localhost/key")
.declaring(String.class).invoker(Invokable.from(String.class.getDeclaredMethod("toString"))).arg(options).build();
GeneratedHttpRequest request = requestForArgs(ImmutableList.<Object> of(options));
BindCloneVAppParamsToXmlPayload binder = injector.getInstance(BindCloneVAppParamsToXmlPayload.class);
Builder<String, Object> map = ImmutableMap.builder();
@ -75,9 +58,7 @@ public class BindCloneVAppParamsToXmlPayloadTest {
CloneVAppOptions options = new CloneVAppOptions().deploy().powerOn().description(
"The description of the new vApp");
GeneratedHttpRequest request = GeneratedHttpRequest.builder().method("POST").endpoint("http://localhost/key")
.declaring(String.class).invoker(Invokable.from(String.class.getDeclaredMethod("toString"))).arg(options).build();
GeneratedHttpRequest request = requestForArgs(ImmutableList.<Object> of(options));
BindCloneVAppParamsToXmlPayload binder = injector.getInstance(BindCloneVAppParamsToXmlPayload.class);
@ -90,10 +71,7 @@ public class BindCloneVAppParamsToXmlPayloadTest {
public void testDefault() throws Exception {
String expected = Strings2.toStringAndClose(getClass().getResourceAsStream("/copyVApp-default.xml"));
GeneratedHttpRequest request = GeneratedHttpRequest.builder().method("POST").endpoint("http://localhost/key")
.declaring(String.class).invoker(Invokable.from(String.class.getDeclaredMethod("toString"))).build();
GeneratedHttpRequest request = requestForArgs(ImmutableList.<Object> of());
BindCloneVAppParamsToXmlPayload binder = injector.getInstance(BindCloneVAppParamsToXmlPayload.class);

View File

@ -18,28 +18,19 @@
*/
package org.jclouds.vcloud.binders;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.verify;
import static org.jclouds.util.Strings2.toStringAndClose;
import static org.testng.Assert.assertEquals;
import java.io.IOException;
import java.net.URI;
import java.util.Properties;
import org.jclouds.rest.internal.GeneratedHttpRequest;
import org.jclouds.util.Strings2;
import org.jclouds.vcloud.VCloudApiMetadata;
import org.jclouds.vcloud.internal.BasePayloadTest;
import org.jclouds.vcloud.options.CloneVAppTemplateOptions;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableMap.Builder;
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.name.Names;
/**
* Tests behavior of {@code BindCloneVAppTemplateParamsToXmlPayload}
@ -47,77 +38,54 @@ import com.google.inject.name.Names;
* @author Adrian Cole
*/
@Test(groups = "unit")
public class BindCloneVAppTemplateParamsToXmlPayloadTest {
Injector injector = Guice.createInjector(new AbstractModule() {
@Override
protected void configure() {
Properties props = new Properties();
props.setProperty("jclouds.vcloud.xml.ns", "http://www.vmware.com/vcloud/v1");
props.setProperty("jclouds.vcloud.xml.schema", "http://vcloud.safesecureweb.com/ns/vcloud.xsd");
Names.bindProperties(binder(), new VCloudApiMetadata().getDefaultProperties());
}
});
public class BindCloneVAppTemplateParamsToXmlPayloadTest extends BasePayloadTest {
public void testWithDescription() throws IOException {
String expected = Strings2.toStringAndClose(getClass().getResourceAsStream("/copyVAppTemplate.xml"));
String expected = toStringAndClose(getClass().getResourceAsStream("/copyVAppTemplate.xml"));
CloneVAppTemplateOptions options = new CloneVAppTemplateOptions()
.description("The description of the new vAppTemplate");
GeneratedHttpRequest request = createMock(GeneratedHttpRequest.class);
expect(request.getEndpoint()).andReturn(URI.create("http://localhost/key")).anyTimes();
expect(request.getArgs()).andReturn(ImmutableList.<Object> of(options)).atLeastOnce();
request.setPayload(expected);
replay(request);
.description("The description of the new vAppTemplate");
GeneratedHttpRequest request = requestForArgs(ImmutableList.<Object> of(options));
BindCloneVAppTemplateParamsToXmlPayload binder = injector
.getInstance(BindCloneVAppTemplateParamsToXmlPayload.class);
.getInstance(BindCloneVAppTemplateParamsToXmlPayload.class);
Builder<String, Object> map = ImmutableMap.builder();
map.put("name", "new-linux-server");
map.put("Source", "https://vcenterprise.bluelock.com/api/v1.0/vAppTemplate/201");
binder.bindToRequest(request, map.build());
verify(request);
assertEquals(binder.bindToRequest(request, map.build()).getPayload().getRawContent(), expected);
}
public void testWithDescriptionSourceDelete() throws IOException {
String expected = Strings2.toStringAndClose(getClass().getResourceAsStream("/moveVAppTemplate.xml"));
String expected = toStringAndClose(getClass().getResourceAsStream("/moveVAppTemplate.xml"));
CloneVAppTemplateOptions options = new CloneVAppTemplateOptions()
.description("The description of the new vAppTemplate");
GeneratedHttpRequest request = createMock(GeneratedHttpRequest.class);
expect(request.getEndpoint()).andReturn(URI.create("http://localhost/key")).anyTimes();
expect(request.getArgs()).andReturn(ImmutableList.<Object> of(options)).atLeastOnce();
request.setPayload(expected);
replay(request);
.description("The description of the new vAppTemplate");
GeneratedHttpRequest request = requestForArgs(ImmutableList.<Object> of(options));
BindCloneVAppTemplateParamsToXmlPayload binder = injector
.getInstance(BindCloneVAppTemplateParamsToXmlPayload.class);
.getInstance(BindCloneVAppTemplateParamsToXmlPayload.class);
Builder<String, Object> map = ImmutableMap.builder();
map.put("name", "new-linux-server");
map.put("Source", "https://vcenterprise.bluelock.com/api/v1.0/vAppTemplate/201");
map.put("IsSourceDelete", "true");
binder.bindToRequest(request, map.build());
verify(request);
assertEquals(binder.bindToRequest(request, map.build()).getPayload().getRawContent(), expected);
}
public void testDefault() throws IOException {
String expected = Strings2.toStringAndClose(getClass().getResourceAsStream("/copyVAppTemplate-default.xml"));
String expected = toStringAndClose(getClass().getResourceAsStream("/copyVAppTemplate-default.xml"));
GeneratedHttpRequest request = createMock(GeneratedHttpRequest.class);
expect(request.getEndpoint()).andReturn(URI.create("http://localhost/key")).anyTimes();
expect(request.getArgs()).andReturn(ImmutableList.<Object> of()).atLeastOnce();
request.setPayload(expected);
replay(request);
GeneratedHttpRequest request = requestForArgs(ImmutableList.<Object> of());
BindCloneVAppTemplateParamsToXmlPayload binder = injector
.getInstance(BindCloneVAppTemplateParamsToXmlPayload.class);
.getInstance(BindCloneVAppTemplateParamsToXmlPayload.class);
Builder<String, Object> map = ImmutableMap.builder();
map.put("name", "my-vapptemplate");
map.put("Source", "https://vcenterprise.bluelock.com/api/v1.0/vAppTemplate/4181");
binder.bindToRequest(request, map.build());
verify(request);
assertEquals(binder.bindToRequest(request, map.build()).getPayload().getRawContent(), expected);
}
}

View File

@ -18,24 +18,17 @@
*/
package org.jclouds.vcloud.binders;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.verify;
import static org.testng.Assert.assertEquals;
import java.io.IOException;
import java.net.URI;
import java.util.Map;
import org.jclouds.rest.internal.GeneratedHttpRequest;
import org.jclouds.vcloud.VCloudApiMetadata;
import org.nnsoft.guice.rocoto.Rocoto;
import org.nnsoft.guice.rocoto.configuration.ConfigurationModule;
import org.jclouds.vcloud.internal.BasePayloadTest;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Maps;
import com.google.inject.Guice;
import com.google.inject.Injector;
/**
* Tests behavior of {@code BindDeployVAppParamsToXmlPayload}
@ -43,44 +36,28 @@ import com.google.inject.Injector;
* @author Adrian Cole
*/
@Test(groups = "unit")
public class BindDeployVAppParamsToXmlPayloadTest {
Injector injector = Guice.createInjector(Rocoto.expandVariables(new ConfigurationModule() {
@Override
protected void bindConfigurations() {
bindProperties(new VCloudApiMetadata().getDefaultProperties());
}
}));
public class BindDeployVAppParamsToXmlPayloadTest extends BasePayloadTest {
public void testPowerOnTrue() throws IOException {
String expected = "<DeployVAppParams xmlns=\"http://www.vmware.com/vcloud/v1\" powerOn=\"true\"/>";
GeneratedHttpRequest request = createMock(GeneratedHttpRequest.class);
expect(request.getEndpoint()).andReturn(URI.create("http://localhost/key")).anyTimes();
request.setPayload(expected);
replay(request);
GeneratedHttpRequest request = requestForArgs(ImmutableList.<Object> of());
BindDeployVAppParamsToXmlPayload binder = injector.getInstance(BindDeployVAppParamsToXmlPayload.class);
Map<String, Object> map = Maps.newHashMap();
map.put("powerOn", "true");
binder.bindToRequest(request, map);
verify(request);
assertEquals(binder.bindToRequest(request, map).getPayload().getRawContent(), expected);
}
public void testDefault() throws IOException {
String expected = "<DeployVAppParams xmlns=\"http://www.vmware.com/vcloud/v1\"/>";
GeneratedHttpRequest request = createMock(GeneratedHttpRequest.class);
expect(request.getEndpoint()).andReturn(URI.create("http://localhost/key")).anyTimes();
request.setPayload(expected);
replay(request);
GeneratedHttpRequest request = requestForArgs(ImmutableList.<Object> of());
BindDeployVAppParamsToXmlPayload binder = injector.getInstance(BindDeployVAppParamsToXmlPayload.class);
Map<String, Object> map = Maps.newHashMap();
binder.bindToRequest(request, map);
verify(request);
assertEquals(binder.bindToRequest(request, map).getPayload().getRawContent(), expected);
}
}

View File

@ -19,11 +19,10 @@
package org.jclouds.vcloud.binders;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.verify;
import static org.jclouds.vcloud.options.InstantiateVAppTemplateOptions.Builder.addNetworkConfig;
import static org.jclouds.vcloud.reference.VCloudConstants.PROPERTY_VCLOUD_DEFAULT_FENCEMODE;
import static org.testng.Assert.assertEquals;
import java.io.IOException;
import java.net.URI;
@ -41,6 +40,7 @@ import org.jclouds.vcloud.domain.internal.ReferenceTypeImpl;
import org.jclouds.vcloud.domain.network.FenceMode;
import org.jclouds.vcloud.domain.network.NetworkConfig;
import org.jclouds.vcloud.endpoints.Network;
import org.jclouds.vcloud.internal.BasePayloadTest;
import org.jclouds.vcloud.options.InstantiateVAppTemplateOptions;
import org.nnsoft.guice.rocoto.Rocoto;
import org.nnsoft.guice.rocoto.configuration.ConfigurationModule;
@ -66,7 +66,7 @@ import com.google.inject.Provides;
* @author Adrian Cole
*/
@Test(groups = "unit")
public class BindInstantiateVAppTemplateParamsToXmlPayloadTest {
public class BindInstantiateVAppTemplateParamsToXmlPayloadTest extends BasePayloadTest {
Injector createInjector(final URI vAppTemplate, final VAppTemplate value) {
return Guice.createInjector(Rocoto.expandVariables(new ConfigurationModule() {
@ -109,15 +109,10 @@ public class BindInstantiateVAppTemplateParamsToXmlPayloadTest {
public void testDefault() throws IOException {
URI templateUri = URI.create("https://vcenterprise.bluelock.com/api/v1.0/vAppTemplate/3");
VAppTemplate template = createMock(VAppTemplate.class);
replay(template);
String expected = Strings2.toStringAndClose(getClass().getResourceAsStream("/instantiationparams.xml"));
GeneratedHttpRequest request = createMock(GeneratedHttpRequest.class);
expect(request.getEndpoint()).andReturn(URI.create("http://localhost/key")).anyTimes();
expect(request.getArgs()).andReturn(ImmutableList.<Object> of(new InstantiateVAppTemplateOptions()))
.atLeastOnce();
request.setPayload(expected);
replay(request, template);
GeneratedHttpRequest request = requestForArgs(ImmutableList.<Object> of(new InstantiateVAppTemplateOptions()));
BindInstantiateVAppTemplateParamsToXmlPayload binder = createInjector(templateUri, template).getInstance(
BindInstantiateVAppTemplateParamsToXmlPayload.class);
@ -125,24 +120,17 @@ public class BindInstantiateVAppTemplateParamsToXmlPayloadTest {
Map<String, Object> map = Maps.newHashMap();
map.put("name", "my-vapp");
map.put("template", templateUri.toASCIIString());
binder.bindToRequest(request, map);
verify(request, template);
assertEquals(binder.bindToRequest(request, map).getPayload().getRawContent(), expected);
}
public void testDescription() throws IOException {
URI templateUri = URI.create("https://vcenterprise.bluelock.com/api/v1.0/vAppTemplate/3");
VAppTemplate template = createMock(VAppTemplate.class);
replay(template);
String expected = Strings2.toStringAndClose(getClass()
.getResourceAsStream("/instantiationparams-description.xml"));
GeneratedHttpRequest request = createMock(GeneratedHttpRequest.class);
expect(request.getEndpoint()).andReturn(URI.create("http://localhost/key")).anyTimes();
expect(request.getArgs()).andReturn(
ImmutableList.<Object> of(new InstantiateVAppTemplateOptions().description("my foo"))).atLeastOnce();
request.setPayload(expected);
replay(request, template);
GeneratedHttpRequest request = requestForArgs(ImmutableList.<Object> of(new InstantiateVAppTemplateOptions().description("my foo")));
BindInstantiateVAppTemplateParamsToXmlPayload binder = createInjector(templateUri, template).getInstance(
BindInstantiateVAppTemplateParamsToXmlPayload.class);
@ -150,22 +138,16 @@ public class BindInstantiateVAppTemplateParamsToXmlPayloadTest {
Map<String, Object> map = Maps.newHashMap();
map.put("name", "my-vapp");
map.put("template", templateUri.toASCIIString());
binder.bindToRequest(request, map);
verify(request, template);
assertEquals(binder.bindToRequest(request, map).getPayload().getRawContent(), expected);
}
public void testWhenTemplateDoesntExist() throws IOException {
URI templateUri = URI.create("https://vcenterprise.bluelock.com/api/v1.0/vAppTemplate/3");
VAppTemplate template = createMock(VAppTemplate.class);
replay(template);
String expected = Strings2.toStringAndClose(getClass().getResourceAsStream("/instantiationparams.xml"));
GeneratedHttpRequest request = createMock(GeneratedHttpRequest.class);
expect(request.getEndpoint()).andReturn(URI.create("http://localhost/key")).anyTimes();
expect(request.getArgs()).andReturn(ImmutableList.<Object> of()).atLeastOnce();
request.setPayload(expected);
replay(request, template);
GeneratedHttpRequest request = requestForArgs(ImmutableList.<Object> of());
BindInstantiateVAppTemplateParamsToXmlPayload binder = createInjector(templateUri, template).getInstance(
BindInstantiateVAppTemplateParamsToXmlPayload.class);
@ -173,52 +155,19 @@ public class BindInstantiateVAppTemplateParamsToXmlPayloadTest {
Map<String, Object> map = Maps.newHashMap();
map.put("name", "my-vapp");
map.put("template", templateUri.toASCIIString());
binder.bindToRequest(request, map);
verify(request, template);
}
// TODO!!! figure out how to get this to work
@Test(enabled = false)
public void testWithProcessorMemoryDisk() throws IOException {
URI templateUri = URI.create("https://vcenterprise.bluelock.com/api/v1.0/vAppTemplate/3");
VAppTemplate template = null;
InstantiateVAppTemplateOptions options = new InstantiateVAppTemplateOptions();
String expected = Strings2.toStringAndClose(getClass().getResourceAsStream("/instantiationparams.xml"));
GeneratedHttpRequest request = createMock(GeneratedHttpRequest.class);
expect(request.getEndpoint()).andReturn(URI.create("http://localhost/key")).anyTimes();
expect(request.getArgs()).andReturn(ImmutableList.<Object> of(options)).atLeastOnce();
request.setPayload(expected);
replay(request);
BindInstantiateVAppTemplateParamsToXmlPayload binder = createInjector(templateUri, template).getInstance(
BindInstantiateVAppTemplateParamsToXmlPayload.class);
Map<String, Object> map = Maps.newHashMap();
map.put("name", "my-vapp");
map.put("template", "https://vcenterprise.bluelock.com/api/v1.0/vAppTemplate/3");
binder.bindToRequest(request, map);
verify(request);
assertEquals(binder.bindToRequest(request, map).getPayload().getRawContent(), expected);
}
public void testWithNetworkNameFenceMode() throws IOException {
URI templateUri = URI.create("https://vcenterprise.bluelock.com/api/v1.0/vAppTemplate/3");
VAppTemplate template = createMock(VAppTemplate.class);
replay(template);
InstantiateVAppTemplateOptions options = addNetworkConfig(new NetworkConfig("aloha", URI
.create("https://vcenterprise.bluelock.com/api/v1.0/network/1991"), FenceMode.NAT_ROUTED));
String expected = Strings2.toStringAndClose(getClass().getResourceAsStream("/instantiationparams-network.xml"));
GeneratedHttpRequest request = createMock(GeneratedHttpRequest.class);
expect(request.getEndpoint()).andReturn(URI.create("http://localhost/key")).anyTimes();
expect(request.getArgs()).andReturn(ImmutableList.<Object> of(options)).atLeastOnce();
request.setPayload(expected);
replay(request, template);
GeneratedHttpRequest request = requestForArgs(ImmutableList.<Object> of(options));
BindInstantiateVAppTemplateParamsToXmlPayload binder = createInjector(templateUri, template).getInstance(
BindInstantiateVAppTemplateParamsToXmlPayload.class);
@ -227,7 +176,6 @@ public class BindInstantiateVAppTemplateParamsToXmlPayloadTest {
map.put("name", "my-vapp");
map.put("template", "https://vcenterprise.bluelock.com/api/v1.0/vAppTemplate/3");
binder.bindToRequest(request, map);
verify(request, template);
assertEquals(binder.bindToRequest(request, map).getPayload().getRawContent(), expected);
}
}

View File

@ -24,17 +24,13 @@ import java.io.IOException;
import java.net.URI;
import org.jclouds.http.HttpRequest;
import org.jclouds.vcloud.VCloudApiMetadata;
import org.jclouds.vcloud.domain.NetworkConnection;
import org.jclouds.vcloud.domain.NetworkConnectionSection;
import org.jclouds.vcloud.domain.network.IpAddressAllocationMode;
import org.nnsoft.guice.rocoto.Rocoto;
import org.nnsoft.guice.rocoto.configuration.ConfigurationModule;
import org.jclouds.vcloud.internal.BasePayloadTest;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableSet;
import com.google.inject.Guice;
import com.google.inject.Injector;
/**
* Tests behavior of {@code BindNetworkConnectionSectionToXmlPayload}
@ -42,14 +38,7 @@ import com.google.inject.Injector;
* @author Adrian Cole
*/
@Test(groups = "unit", testName = "BindNetworkConnectionSectionToXmlPayloadTest")
public class BindNetworkConnectionSectionToXmlPayloadTest {
Injector injector = Guice.createInjector(Rocoto.expandVariables(new ConfigurationModule() {
@Override
protected void bindConfigurations() {
bindProperties(new VCloudApiMetadata().getDefaultProperties());
}
}));
public class BindNetworkConnectionSectionToXmlPayloadTest extends BasePayloadTest {
public void testWithIpAllocationModeNONE() throws IOException {

View File

@ -18,24 +18,17 @@
*/
package org.jclouds.vcloud.binders;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.verify;
import static org.testng.Assert.assertEquals;
import java.io.IOException;
import java.net.URI;
import java.util.Map;
import org.jclouds.rest.internal.GeneratedHttpRequest;
import org.jclouds.vcloud.VCloudApiMetadata;
import org.nnsoft.guice.rocoto.Rocoto;
import org.nnsoft.guice.rocoto.configuration.ConfigurationModule;
import org.jclouds.vcloud.internal.BasePayloadTest;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Maps;
import com.google.inject.Guice;
import com.google.inject.Injector;
/**
* Tests behavior of {@code BindUndeployVAppParamsToXmlPayload}
@ -43,44 +36,28 @@ import com.google.inject.Injector;
* @author Adrian Cole
*/
@Test(groups = "unit")
public class BindUndeployVAppParamsToXmlPayloadTest {
Injector injector = Guice.createInjector(Rocoto.expandVariables(new ConfigurationModule() {
@Override
protected void bindConfigurations() {
bindProperties(new VCloudApiMetadata().getDefaultProperties());
}
}));
public class BindUndeployVAppParamsToXmlPayloadTest extends BasePayloadTest {
public void testSaveStateTrue() throws IOException {
String expected = "<UndeployVAppParams xmlns=\"http://www.vmware.com/vcloud/v1\" saveState=\"true\"/>";
GeneratedHttpRequest request = createMock(GeneratedHttpRequest.class);
expect(request.getEndpoint()).andReturn(URI.create("http://localhost/key")).anyTimes();
request.setPayload(expected);
replay(request);
GeneratedHttpRequest request = requestForArgs(ImmutableList.<Object> of());
BindUndeployVAppParamsToXmlPayload binder = injector.getInstance(BindUndeployVAppParamsToXmlPayload.class);
Map<String, Object> map = Maps.newHashMap();
map.put("saveState", "true");
binder.bindToRequest(request, map);
verify(request);
assertEquals(binder.bindToRequest(request, map).getPayload().getRawContent(), expected);
}
public void testDefault() throws IOException {
String expected = "<UndeployVAppParams xmlns=\"http://www.vmware.com/vcloud/v1\"/>";
GeneratedHttpRequest request = createMock(GeneratedHttpRequest.class);
expect(request.getEndpoint()).andReturn(URI.create("http://localhost/key")).anyTimes();
request.setPayload(expected);
replay(request);
GeneratedHttpRequest request = requestForArgs(ImmutableList.<Object> of());
BindUndeployVAppParamsToXmlPayload binder = injector.getInstance(BindUndeployVAppParamsToXmlPayload.class);
Map<String, Object> map = Maps.newHashMap();
binder.bindToRequest(request, map);
verify(request);
assertEquals(binder.bindToRequest(request, map).getPayload().getRawContent(), expected);
}
}

View File

@ -0,0 +1,54 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds 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.vcloud.internal;
import java.net.URI;
import java.util.List;
import org.jclouds.reflect.Invocation;
import org.jclouds.rest.internal.GeneratedHttpRequest;
import org.jclouds.vcloud.VCloudApiMetadata;
import org.nnsoft.guice.rocoto.Rocoto;
import org.nnsoft.guice.rocoto.configuration.ConfigurationModule;
import com.google.common.base.Throwables;
import com.google.common.reflect.Invokable;
import com.google.inject.Guice;
import com.google.inject.Injector;
public class BasePayloadTest {
protected Injector injector = Guice.createInjector(Rocoto.expandVariables(new ConfigurationModule() {
protected void bindConfigurations() {
bindProperties(new VCloudApiMetadata().getDefaultProperties());
}
}));
protected GeneratedHttpRequest requestForArgs(List<Object> args) {
try {
Invocation invocation = Invocation.create(Invokable.from(String.class.getDeclaredMethod("toString")), args);
return GeneratedHttpRequest.builder().method("POST").endpoint(URI.create("http://localhost/key"))
.invocation(invocation).build();
} catch (SecurityException e) {
throw Throwables.propagate(e);
} catch (NoSuchMethodException e) {
throw Throwables.propagate(e);
}
}
}

View File

@ -20,6 +20,7 @@ package org.jclouds.blobstore.util;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@ -60,12 +61,13 @@ public class BlobStoreUtils {
public static String getNameFor(GeneratedHttpRequest request) {
checkNotNull(request, "request");
List<Object> args = request.getInvocation().getArgs();
// assume first params are container and key
if (request.getArgs().size() >= 2 && request.getArgs().get(0) instanceof String
&& request.getArgs().get(1) instanceof String) {
return request.getArgs().get(1).toString();
} else if (request.getArgs().size() >= 1 && request.getArgs().get(0) instanceof String) {
Matcher matcher = keyFromContainer.matcher(request.getArgs().get(0).toString());
if (args.size() >= 2 && args.get(0) instanceof String
&& args.get(1) instanceof String) {
return args.get(1).toString();
} else if (args.size() >= 1 && args.get(0) instanceof String) {
Matcher matcher = keyFromContainer.matcher(args.get(0).toString());
if (matcher.find())
return matcher.group(1);
}

View File

@ -27,16 +27,20 @@ import static org.jclouds.blobstore.util.BlobStoreUtils.getNameFor;
import static org.testng.Assert.assertEquals;
import java.net.URI;
import java.util.List;
import org.jclouds.blobstore.AsyncBlobStore;
import org.jclouds.blobstore.domain.Blob;
import org.jclouds.blobstore.domain.MutableBlobMetadata;
import org.jclouds.reflect.Invocation;
import org.jclouds.rest.Providers;
import org.jclouds.rest.internal.GeneratedHttpRequest;
import org.testng.annotations.Test;
import com.google.common.base.Throwables;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.google.common.reflect.Invokable;
/**
* Tests behavior of {@code BlobStoreUtils}
@ -121,30 +125,28 @@ public class BlobStoreUtilsTest {
}
public void testGetKeyForAzureS3AndRackspace() {
GeneratedHttpRequest request = createMock(GeneratedHttpRequest.class);
expect(request.getEndpoint()).andReturn(
URI.create("https://jclouds.blob.core.windows.net/adriancole-blobstore0/five"));
expect(request.getArgs()).andReturn(ImmutableList.<Object> of("adriancole-blobstore0", "five")).atLeastOnce();
replay(request);
GeneratedHttpRequest request = requestForEndpointAndArgs(
"https://jclouds.blob.core.windows.net/adriancole-blobstore0/five",
ImmutableList.<Object> of("adriancole-blobstore0", "five"));
assertEquals(getNameFor(request), "five");
}
public void testGetKeyForAtmos() {
GeneratedHttpRequest request = createMock(GeneratedHttpRequest.class);
expect(request.getEndpoint())
.andReturn(
URI.create("https://storage4.clouddrive.com/v1/MossoCloudFS_dc1f419c-5059-4c87-a389-3f2e33a77b22/adriancole-blobstore0/four"));
expect(request.getArgs()).andReturn(ImmutableList.<Object> of("adriancole-blobstore0/four")).atLeastOnce();
replay(request);
GeneratedHttpRequest request = requestForEndpointAndArgs(
"https://storage4.clouddrive.com/v1/MossoCloudFS_dc1f419c-5059-4c87-a389-3f2e33a77b22/adriancole-blobstore0/four",
ImmutableList.<Object> of("adriancole-blobstore0/four"));
assertEquals(getNameFor(request), "four");
}
GeneratedHttpRequest requestForEndpointAndArgs(String endpoint, List<Object> args) {
try {
Invocation invocation = Invocation.create(Invokable.from(String.class.getDeclaredMethod("toString")), args);
return GeneratedHttpRequest.builder().method("POST").endpoint(URI.create(endpoint)).invocation(invocation)
.build();
} catch (SecurityException e) {
throw Throwables.propagate(e);
} catch (NoSuchMethodException e) {
throw Throwables.propagate(e);
}
}
}

View File

@ -213,7 +213,7 @@ public class AWSUtils {
}
public static String findRegionInArgsOrNull(GeneratedHttpRequest gRequest) {
for (Object arg : gRequest.getArgs()) {
for (Object arg : gRequest.getInvocation().getArgs()) {
if (arg instanceof String) {
String regionName = (String) arg;
// TODO regions may not be amazon regions!

View File

@ -68,7 +68,6 @@ public class BindCloneVAppParamsToXmlPayload implements MapBinder {
checkArgument(checkNotNull(request, "request") instanceof GeneratedHttpRequest,
"this binder is only valid for GeneratedHttpRequests!");
GeneratedHttpRequest gRequest = (GeneratedHttpRequest) request;
checkState(gRequest.getArgs() != null, "args should be initialized at this point");
String newName = checkNotNull(postParams.remove("newName"), "newName").toString();
String vApp = checkNotNull(postParams.remove("vApp"), "vApp").toString();
@ -108,7 +107,7 @@ public class BindCloneVAppParamsToXmlPayload implements MapBinder {
}
protected CloneVAppOptions findOptionsInArgsOrNull(GeneratedHttpRequest gRequest) {
for (Object arg : gRequest.getArgs()) {
for (Object arg : gRequest.getInvocation().getArgs()) {
if (arg instanceof CloneVAppOptions) {
return (CloneVAppOptions) arg;
} else if (arg instanceof CloneVAppOptions[]) {

View File

@ -87,7 +87,6 @@ public class BindInstantiateVAppTemplateParamsToXmlPayload implements MapBinder
checkArgument(checkNotNull(request, "request") instanceof GeneratedHttpRequest,
"this binder is only valid for GeneratedHttpRequests!");
GeneratedHttpRequest gRequest = (GeneratedHttpRequest) request;
checkState(gRequest.getArgs() != null, "args should be initialized at this point");
String name = checkNotNull(postParams.remove("name"), "name").toString();
String template = checkNotNull(postParams.remove("template"), "template").toString();
@ -174,7 +173,7 @@ public class BindInstantiateVAppTemplateParamsToXmlPayload implements MapBinder
protected InstantiateVAppTemplateOptions findOptionsInArgsOrNull(GeneratedHttpRequest gRequest) {
InstantiateVAppTemplateOptions options = null;
for (Object arg : gRequest.getArgs()) {
for (Object arg : gRequest.getInvocation().getArgs()) {
if (arg instanceof InstantiateVAppTemplateOptions) {
options = (InstantiateVAppTemplateOptions) arg;
} else if (arg instanceof InstantiateVAppTemplateOptions[]) {

View File

@ -82,8 +82,6 @@ public class BindVAppConfigurationToXmlPayload implements MapBinder, Function<Ob
checkArgument(checkNotNull(request, "request") instanceof GeneratedHttpRequest,
"this binder is only valid for GeneratedHttpRequests!");
GeneratedHttpRequest gRequest = (GeneratedHttpRequest) request;
checkState(gRequest.getArgs() != null, "args should be initialized at this point");
VApp vApp = checkNotNull(findVAppInArgsOrNull(gRequest), "vApp");
checkArgument(vApp.getStatus() == Status.OFF, "vApp must be off!");
VAppConfiguration configuration = checkNotNull(findConfigInArgsOrNull(gRequest), "config");
@ -182,7 +180,7 @@ public class BindVAppConfigurationToXmlPayload implements MapBinder, Function<Ob
}
protected VApp findVAppInArgsOrNull(GeneratedHttpRequest gRequest) {
for (Object arg : gRequest.getArgs()) {
for (Object arg : gRequest.getInvocation().getArgs()) {
if (arg instanceof VApp) {
return (VApp) arg;
} else if (arg instanceof VApp[]) {
@ -194,7 +192,7 @@ public class BindVAppConfigurationToXmlPayload implements MapBinder, Function<Ob
}
protected VAppConfiguration findConfigInArgsOrNull(GeneratedHttpRequest gRequest) {
for (Object arg : gRequest.getArgs()) {
for (Object arg : gRequest.getInvocation().getArgs()) {
if (arg instanceof VAppConfiguration) {
return (VAppConfiguration) arg;
} else if (arg instanceof VAppConfiguration[]) {

View File

@ -48,7 +48,7 @@ public class KeyPairByNameHandler extends ParseSax.HandlerForGeneratedRequestWit
@Override
public KeyPair getResult() {
final String name = getRequest().getArgs().get(1).toString();
final String name = getRequest().getInvocation().getArgs().get(1).toString();
try {
return Iterables.find(handler.getResult(), new Predicate<KeyPair>() {
@ -59,7 +59,8 @@ public class KeyPairByNameHandler extends ParseSax.HandlerForGeneratedRequestWit
});
} catch (NoSuchElementException e) {
logger.debug("keypair %s/%s not found in %s", getRequest().getArgs().get(0), name, handler.getResult());
logger.debug("keypair %s/%s not found in %s", getRequest().getInvocation().getArgs().get(0), name,
handler.getResult());
return null;
}
}

View File

@ -51,7 +51,7 @@ public class BindAddNodeServiceToXmlPayloadTest {
@Override
protected void configure() {
bindConstant().annotatedWith(Names.named(PROPERTY_TERREMARK_EXTENSION_NS)).to(
"urn:tmrk:vCloudExpressExtensions-1.6");
"urn:tmrk:vCloudExpressExtensions-1.6");
}
@Singleton
@ -64,11 +64,9 @@ public class BindAddNodeServiceToXmlPayloadTest {
});
public void testApplyInputStream() throws IOException {
String expected = Strings2.toStringAndClose(getClass().getResourceAsStream(
"/CreateNodeService-test.xml"));
String expected = Strings2.toStringAndClose(getClass().getResourceAsStream("/CreateNodeService-test.xml"));
HttpRequest request = HttpRequest.builder().method("GET").endpoint("http://test").build();
BindAddNodeServiceToXmlPayload binder = injector
.getInstance(BindAddNodeServiceToXmlPayload.class);
BindAddNodeServiceToXmlPayload binder = injector.getInstance(BindAddNodeServiceToXmlPayload.class);
Map<String, Object> map = Maps.newHashMap();
map.put("name", "Node for Jim");
@ -76,8 +74,6 @@ public class BindAddNodeServiceToXmlPayloadTest {
map.put("port", "80");
map.put("enabled", "false");
map.put("description", "Some test node");
binder.bindToRequest(request, map);
assertEquals(request.getPayload().getRawContent(), expected);
assertEquals(binder.bindToRequest(request, map).getPayload().getRawContent(), expected);
}
}

View File

@ -24,13 +24,14 @@ import java.util.Map;
import java.util.Properties;
import org.jclouds.rest.internal.GeneratedHttpRequest;
import org.jclouds.trmk.vcloud_0_8.internal.BasePayloadTest;
import org.jclouds.trmk.vcloud_0_8.internal.TerremarkVCloudApiMetadata;
import org.jclouds.trmk.vcloud_0_8.options.CloneVAppOptions;
import org.jclouds.util.Strings2;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Maps;
import com.google.common.reflect.Invokable;
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Injector;
@ -42,7 +43,7 @@ import com.google.inject.name.Names;
* @author Adrian Cole
*/
@Test(groups = "unit")
public class BindCloneVAppParamsToXmlPayloadTest {
public class BindCloneVAppParamsToXmlPayloadTest extends BasePayloadTest {
Injector injector = Guice.createInjector(new AbstractModule() {
@Override
@ -53,15 +54,13 @@ public class BindCloneVAppParamsToXmlPayloadTest {
Names.bindProperties(binder(), props);
}
});
public void testWithDescriptionDeployOn() throws Exception {
String expected = Strings2.toStringAndClose(getClass().getResourceAsStream("/cloneVApp.xml"));
CloneVAppOptions options = new CloneVAppOptions().deploy().powerOn().withDescription(
"The description of the new vApp");
GeneratedHttpRequest request = GeneratedHttpRequest.builder().method("POST").endpoint("http://localhost/key")
.declaring(String.class).invoker(Invokable.from(String.class.getDeclaredMethod("toString"))).arg(options).build();
GeneratedHttpRequest request = requestForArgs(ImmutableList.<Object> of(options));
BindCloneVAppParamsToXmlPayload binder = injector.getInstance(BindCloneVAppParamsToXmlPayload.class);
@ -74,8 +73,7 @@ public class BindCloneVAppParamsToXmlPayloadTest {
public void testDefault() throws Exception {
String expected = Strings2.toStringAndClose(getClass().getResourceAsStream("/cloneVApp-default.xml"));
GeneratedHttpRequest request = GeneratedHttpRequest.builder().method("POST").endpoint("http://localhost/key")
.declaring(String.class).invoker(Invokable.from(String.class.getDeclaredMethod("toString"))).build();
GeneratedHttpRequest request = requestForArgs(ImmutableList.<Object> of());
BindCloneVAppParamsToXmlPayload binder = injector.getInstance(BindCloneVAppParamsToXmlPayload.class);

View File

@ -18,9 +18,7 @@
*/
package org.jclouds.trmk.vcloud_0_8.binders;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
import static org.testng.Assert.assertEquals;
import java.io.IOException;
import java.net.URI;
@ -32,6 +30,7 @@ import org.jclouds.rest.internal.GeneratedHttpRequest;
import org.jclouds.trmk.vcloud_0_8.domain.ReferenceType;
import org.jclouds.trmk.vcloud_0_8.domain.internal.ReferenceTypeImpl;
import org.jclouds.trmk.vcloud_0_8.endpoints.Network;
import org.jclouds.trmk.vcloud_0_8.internal.BasePayloadTest;
import org.jclouds.trmk.vcloud_0_8.internal.TerremarkVCloudApiMetadata;
import org.jclouds.trmk.vcloud_0_8.options.InstantiateVAppTemplateOptions;
import org.jclouds.trmk.vcloud_0_8.options.InstantiateVAppTemplateOptions.NetworkConfig;
@ -42,11 +41,8 @@ import org.testng.annotations.Test;
import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Maps;
import com.google.common.collect.Multimap;
import com.google.common.collect.Multimaps;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Provides;
@ -57,7 +53,7 @@ import com.google.inject.Provides;
* @author Adrian Cole
*/
@Test(groups = "unit")
public class BindInstantiateVAppTemplateParamsToXmlPayloadTest {
public class BindInstantiateVAppTemplateParamsToXmlPayloadTest extends BasePayloadTest {
Injector injector = Guice.createInjector(Rocoto.expandVariables(new ConfigurationModule() {
@Override
@ -69,7 +65,7 @@ public class BindInstantiateVAppTemplateParamsToXmlPayloadTest {
@Provides
@Singleton
Supplier<ReferenceType> provideNetwork() {
return Suppliers.<ReferenceType>ofInstance(new ReferenceTypeImpl(null, null, URI
return Suppliers.<ReferenceType> ofInstance(new ReferenceTypeImpl(null, null, URI
.create("https://vcloud.safesecureweb.com/network/1990")));
}
}));
@ -78,25 +74,18 @@ public class BindInstantiateVAppTemplateParamsToXmlPayloadTest {
String expected = Strings2.toStringAndClose(getClass().getResourceAsStream(
"/InstantiateVAppTemplateParams-options-test.xml"));
Multimap<String, String> headers = Multimaps.synchronizedMultimap(HashMultimap.<String, String> create());
GeneratedHttpRequest request = createMock(GeneratedHttpRequest.class);
expect(request.getEndpoint()).andReturn(URI.create("http://localhost/key")).anyTimes();
expect(request.getArgs()).andReturn(
ImmutableList.<Object> of(InstantiateVAppTemplateOptions.Builder.processorCount(2).memory(512)
.inGroup("group").withPassword("password").inRow("row")
.addNetworkConfig(new NetworkConfig(URI.create("http://network"))))).atLeastOnce();
expect(request.getFirstHeaderOrNull("Content-Type")).andReturn("application/unknown").atLeastOnce();
expect(request.getHeaders()).andReturn(headers).atLeastOnce();
request.setPayload(expected);
replay(request);
BindInstantiateVAppTemplateParamsToXmlPayload binder = injector
GeneratedHttpRequest request = requestForArgs(ImmutableList.<Object> of(InstantiateVAppTemplateOptions.Builder
.processorCount(2).memory(512).inGroup("group").withPassword("password").inRow("row")
.addNetworkConfig(new NetworkConfig(URI.create("http://network")))));
BindInstantiateVAppTemplateParamsToXmlPayload binder = injector
.getInstance(BindInstantiateVAppTemplateParamsToXmlPayload.class);
Map<String, Object> map = Maps.newHashMap();
map.put("name", "name");
map.put("template", "https://vcloud/vAppTemplate/3");
binder.bindToRequest(request, map);
assertEquals(binder.bindToRequest(request, map).getPayload().getRawContent(), expected);
}
}

View File

@ -18,11 +18,8 @@
*/
package org.jclouds.trmk.vcloud_0_8.binders;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.verify;
import static org.jclouds.trmk.vcloud_0_8.domain.VAppConfiguration.Builder.changeNameTo;
import static org.testng.Assert.assertEquals;
import java.io.IOException;
import java.net.URI;
@ -35,6 +32,7 @@ import org.jclouds.rest.internal.GeneratedHttpRequest;
import org.jclouds.trmk.vcloud_0_8.domain.Status;
import org.jclouds.trmk.vcloud_0_8.domain.VAppConfiguration;
import org.jclouds.trmk.vcloud_0_8.domain.internal.VAppImpl;
import org.jclouds.trmk.vcloud_0_8.internal.BasePayloadTest;
import org.jclouds.trmk.vcloud_0_8.internal.TerremarkVCloudApiMetadata;
import org.jclouds.util.Strings2;
import org.nnsoft.guice.rocoto.Rocoto;
@ -54,7 +52,7 @@ import com.google.inject.Injector;
* @author Adrian Cole
*/
@Test(groups = "unit")
public class BindVAppConfigurationToXmlPayloadTest {
public class BindVAppConfigurationToXmlPayloadTest extends BasePayloadTest {
Injector injector = Guice.createInjector(Rocoto.expandVariables(new ConfigurationModule() {
@Override
@ -80,17 +78,11 @@ public class BindVAppConfigurationToXmlPayloadTest {
VAppConfiguration config = new VAppConfiguration().changeNameTo("roberto");
GeneratedHttpRequest request = createMock(GeneratedHttpRequest.class);
expect(request.getEndpoint()).andReturn(URI.create("http://localhost/key")).anyTimes();
expect(request.getArgs()).andReturn(ImmutableList.<Object> of(vApp, config)).atLeastOnce();
request.setPayload(expected);
replay(request);
GeneratedHttpRequest request = requestForArgs(ImmutableList.<Object> of(vApp, config));
BindVAppConfigurationToXmlPayload binder = injector.getInstance(BindVAppConfigurationToXmlPayload.class);
Map<String, Object> map = Maps.newHashMap();
binder.bindToRequest(request, map);
verify(request);
assertEquals(binder.bindToRequest(request, map).getPayload().getRawContent(), expected);
}
public void testRemoveDisk() throws IOException {
@ -115,18 +107,13 @@ public class BindVAppConfigurationToXmlPayloadTest {
.replace("eduardo", "MyAppServer6");
VAppConfiguration config = new VAppConfiguration().deleteDiskWithAddressOnParent(1);
GeneratedHttpRequest request = createMock(GeneratedHttpRequest.class);
expect(request.getEndpoint()).andReturn(URI.create("http://localhost/key")).anyTimes();
expect(request.getArgs()).andReturn(ImmutableList.<Object> of(vApp, config)).atLeastOnce();
request.setPayload(expected);
replay(request);
GeneratedHttpRequest request = requestForArgs(ImmutableList.<Object> of(vApp, config));
BindVAppConfigurationToXmlPayload binder = injector.getInstance(BindVAppConfigurationToXmlPayload.class);
Map<String, Object> map = Maps.newHashMap();
binder.bindToRequest(request, map);
verify(request);
assertEquals(binder.bindToRequest(request, map).getPayload().getRawContent(), expected);
}
public void testChangeAll() throws IOException {
@ -145,17 +132,12 @@ public class BindVAppConfigurationToXmlPayloadTest {
VAppConfiguration config = changeNameTo("eduardo").changeMemoryTo(1536).changeProcessorCountTo(1).addDisk(
25 * 1048576).addDisk(25 * 1048576);
GeneratedHttpRequest request = createMock(GeneratedHttpRequest.class);
expect(request.getEndpoint()).andReturn(URI.create("http://localhost/key")).anyTimes();
expect(request.getArgs()).andReturn(ImmutableList.<Object> of(vApp, config)).atLeastOnce();
request.setPayload(expected);
replay(request);
GeneratedHttpRequest request = requestForArgs(ImmutableList.<Object> of(vApp, config));
BindVAppConfigurationToXmlPayload binder = injector.getInstance(BindVAppConfigurationToXmlPayload.class);
Map<String, Object> map = Maps.newHashMap();
binder.bindToRequest(request, map);
verify(request);
assertEquals(binder.bindToRequest(request, map).getPayload().getRawContent(), expected);
}
public void testChangeCPUCountTo4() throws IOException {
@ -172,17 +154,12 @@ public class BindVAppConfigurationToXmlPayloadTest {
VAppConfiguration config = new VAppConfiguration().changeProcessorCountTo(4);
GeneratedHttpRequest request = createMock(GeneratedHttpRequest.class);
expect(request.getEndpoint()).andReturn(URI.create("http://localhost/key")).anyTimes();
expect(request.getArgs()).andReturn(ImmutableList.<Object> of(vApp, config)).atLeastOnce();
request.setPayload(expected);
replay(request);
GeneratedHttpRequest request = requestForArgs(ImmutableList.<Object> of(vApp, config));
BindVAppConfigurationToXmlPayload binder = injector.getInstance(BindVAppConfigurationToXmlPayload.class);
Map<String, Object> map = Maps.newHashMap();
binder.bindToRequest(request, map);
verify(request);
assertEquals(binder.bindToRequest(request, map).getPayload().getRawContent(), expected);
}
public void testChangeMemoryTo1536() throws IOException {
@ -201,16 +178,11 @@ public class BindVAppConfigurationToXmlPayloadTest {
VAppConfiguration config = new VAppConfiguration().changeMemoryTo(1536);
GeneratedHttpRequest request = createMock(GeneratedHttpRequest.class);
expect(request.getEndpoint()).andReturn(URI.create("http://localhost/key")).anyTimes();
expect(request.getArgs()).andReturn(ImmutableList.<Object> of(vApp, config)).atLeastOnce();
request.setPayload(expected);
replay(request);
GeneratedHttpRequest request = requestForArgs(ImmutableList.<Object> of(vApp, config));
BindVAppConfigurationToXmlPayload binder = injector.getInstance(BindVAppConfigurationToXmlPayload.class);
Map<String, Object> map = Maps.newHashMap();
binder.bindToRequest(request, map);
verify(request);
assertEquals(binder.bindToRequest(request, map).getPayload().getRawContent(), expected);
}
}

View File

@ -0,0 +1,43 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds 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.trmk.vcloud_0_8.internal;
import java.net.URI;
import java.util.List;
import org.jclouds.reflect.Invocation;
import org.jclouds.rest.internal.GeneratedHttpRequest;
import com.google.common.base.Throwables;
import com.google.common.reflect.Invokable;
public class BasePayloadTest {
protected GeneratedHttpRequest requestForArgs(List<Object> args) {
try {
Invocation invocation = Invocation.create(Invokable.from(String.class.getDeclaredMethod("toString")), args);
return GeneratedHttpRequest.builder().method("POST").endpoint(URI.create("http://localhost/key"))
.invocation(invocation).build();
} catch (SecurityException e) {
throw Throwables.propagate(e);
} catch (NoSuchMethodException e) {
throw Throwables.propagate(e);
}
}
}

View File

@ -18,17 +18,14 @@
*/
package org.jclouds.trmk.vcloud_0_8.xml;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNull;
import java.io.InputStream;
import java.net.URI;
import java.net.UnknownHostException;
import org.jclouds.http.functions.BaseHandlerTest;
import org.jclouds.rest.internal.GeneratedHttpRequest;
import org.jclouds.trmk.vcloud_0_8.domain.KeyPair;
import org.testng.annotations.Test;
@ -59,15 +56,11 @@ public class KeyPairByNameHandlerTest extends BaseHandlerTest {
KeyPair result = factory.create(
addOrgAndNameToHandler(injector.getInstance(KeyPairByNameHandler.class), "org", "monster")).parse(is);
assertEquals(result, null);
assertNull(result);
}
private static KeyPairByNameHandler addOrgAndNameToHandler(KeyPairByNameHandler handler, String org, String name) {
GeneratedHttpRequest request = createMock(GeneratedHttpRequest.class);
expect(request.getArgs()).andReturn(ImmutableList.<Object> of(org, name)).anyTimes();
replay(request);
handler.setContext(request);
private KeyPairByNameHandler addOrgAndNameToHandler(KeyPairByNameHandler handler, String org, String name) {
handler.setContext(requestForArgs(ImmutableList.<Object> of(org, name)));
return handler;
}
}

View File

@ -24,34 +24,33 @@ import static com.google.common.base.Preconditions.checkState;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import javax.annotation.Resource;
import javax.inject.Inject;
import javax.inject.Named;
import org.jclouds.internal.ClassInvokerArgs;
import org.jclouds.internal.ClassInvokerArgsAndReturnVal;
import org.jclouds.internal.ForwardInvocationToInterface;
import org.jclouds.logging.Logger;
import org.jclouds.reflect.AbstractInvocationHandler;
import org.jclouds.reflect.FunctionalReflection;
import org.jclouds.reflect.Invocation;
import org.jclouds.reflect.Invocation.Result;
import org.jclouds.reflect.InvocationSuccess;
import org.jclouds.rest.annotations.Delegate;
import org.jclouds.rest.internal.AsyncRestClientProxy;
import org.jclouds.util.Optionals2;
import org.jclouds.util.Throwables2;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Function;
import com.google.common.base.Optional;
import com.google.common.base.Throwables;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.reflect.Invokable;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.inject.ProvisionException;
import com.google.inject.assistedinject.Assisted;
/**
@ -59,137 +58,181 @@ import com.google.inject.assistedinject.Assisted;
*
* @author Adrian Cole
*/
public final class SyncProxy extends AbstractInvocationHandler {
public final class SyncProxy implements Function<Invocation, Result> {
public static interface Factory {
/**
* @param declaring
* type of the interface where all methods match those of {@code async} except the return values are
* type of the interface where all invokeds match those of {@code async} except the return values are
* dereferenced
* @param async
* object whose interface matched {@code declaring} except all methods return {@link ListenableFuture}
* object whose interface matched {@code declaring} except all invokeds return {@link ListenableFuture}
* @return blocking invocation handler
*/
SyncProxy create(Class<?> declaring, Object async);
}
/**
* CreateClientForCaller is parameterized, so clients it creates aren't singletons. For example,
* CreateClientForCaller satisfies a call like this:
* {@code context.getProviderSpecificContext().getApi().getOrgClientForName(name)}
*
* @author Adrian Cole
*/
public static class CreateClientForCaller implements Function<ForwardInvocationToInterface, Object> {
private final SyncProxy.Factory factory;
private final AsyncRestClientProxy.Caller.Factory asyncFactory;
@Inject
private CreateClientForCaller(SyncProxy.Factory factory, AsyncRestClientProxy.Caller.Factory asyncFactory) {
this.factory = factory;
this.asyncFactory = asyncFactory;
}
@Override
public Object apply(ForwardInvocationToInterface from) {
Object asyncClient = FunctionalReflection.newProxy(from.getInterfaceType(),
asyncFactory.caller(from.getInvocation(), from.getInterfaceType()));
checkState(asyncClient != null, "configuration error, sync client for " + from + " not found");
Class<?> type = Optionals2.unwrapIfOptional(from.getInvocation().getInvokable().getReturnType());
return FunctionalReflection.newProxy(type, factory.create(type, asyncClient));
}
}
@Resource
private Logger logger = Logger.NULL;
private final Function<ClassInvokerArgsAndReturnVal, Optional<Object>> optionalConverter;
private final Function<InvocationSuccess, Optional<Object>> optionalConverter;
private final Object delegate;
private final Class<?> declaring;
private final Map<Invokable<?, ?>, Invokable<Object, ListenableFuture<?>>> methodMap;
private final Map<Invokable<?, ?>, Invokable<Object, ListenableFuture<?>>> invokedMap;
private final Map<Invokable<?, ?>, Invokable<Object, ?>> syncMethodMap;
private final Map<Invokable<?, ?>, Optional<Long>> timeoutMap;
private final LoadingCache<ClassInvokerArgs, Object> delegateMap;
private final Function<ForwardInvocationToInterface, Object> createClientForCaller;
private final Map<Class<?>, Class<?>> sync2Async;
private static final Set<Method> objectMethods = ImmutableSet.copyOf(Object.class.getMethods());
@SuppressWarnings("unchecked")
@Inject
@VisibleForTesting
SyncProxy(Function<ClassInvokerArgsAndReturnVal, Optional<Object>> optionalConverter,
@Named("sync") LoadingCache<ClassInvokerArgs, Object> delegateMap, Map<Class<?>, Class<?>> sync2Async,
SyncProxy(Function<InvocationSuccess, Optional<Object>> optionalConverter,
Function<ForwardInvocationToInterface, Object> createClientForCaller, Map<Class<?>, Class<?>> sync2Async,
@Named("TIMEOUTS") Map<String, Long> timeouts, @Assisted Class<?> declaring, @Assisted Object async)
throws SecurityException, NoSuchMethodException {
this.optionalConverter = optionalConverter;
this.delegateMap = delegateMap;
this.createClientForCaller = createClientForCaller;
this.delegate = async;
this.declaring = declaring;
this.sync2Async = ImmutableMap.copyOf(sync2Async);
ImmutableMap.Builder<Invokable<?, ?>, Invokable<Object, ListenableFuture<?>>> methodMapBuilder = ImmutableMap.builder();
ImmutableMap.Builder<Invokable<?, ?>, Invokable<Object, ListenableFuture<?>>> invokedMapBuilder = ImmutableMap
.builder();
ImmutableMap.Builder<Invokable<?, ?>, Invokable<Object, ?>> syncMethodMapBuilder = ImmutableMap.builder();
for (Method method : declaring.getMethods()) {
if (!objectMethods.contains(method)) {
Method delegatedMethod = delegate.getClass().getMethod(method.getName(), method.getParameterTypes());
if (!Arrays.equals(delegatedMethod.getExceptionTypes(), method.getExceptionTypes()))
for (Method invoked : declaring.getMethods()) {
if (!objectMethods.contains(invoked)) {
Method delegatedMethod = delegate.getClass().getMethod(invoked.getName(), invoked.getParameterTypes());
if (!Arrays.equals(delegatedMethod.getExceptionTypes(), invoked.getExceptionTypes()))
throw new IllegalArgumentException(String.format(
"method %s has different typed exceptions than delegated method %s", method, delegatedMethod));
"invoked %s has different typed exceptions than delegated invoked %s", invoked, delegatedMethod));
if (delegatedMethod.getReturnType().isAssignableFrom(ListenableFuture.class)) {
methodMapBuilder.put(Invokable.from(method), Invokable.class.cast(Invokable.from(delegatedMethod)));
invokedMapBuilder.put(Invokable.from(invoked), Invokable.class.cast(Invokable.from(delegatedMethod)));
} else {
syncMethodMapBuilder.put(Invokable.from(method), Invokable.class.cast(Invokable.from(delegatedMethod)));
syncMethodMapBuilder.put(Invokable.from(invoked), Invokable.class.cast(Invokable.from(delegatedMethod)));
}
}
}
methodMap = methodMapBuilder.build();
invokedMap = invokedMapBuilder.build();
syncMethodMap = syncMethodMapBuilder.build();
ImmutableMap.Builder<Invokable<?, ?>, Optional<Long>> timeoutMapBuilder = ImmutableMap.builder();
for (Invokable<?, ?> method : methodMap.keySet()) {
timeoutMapBuilder.put(method, timeoutInNanos(method, timeouts));
for (Invokable<?, ?> invoked : invokedMap.keySet()) {
timeoutMapBuilder.put(invoked, timeoutInNanos(invoked, timeouts));
}
timeoutMap = timeoutMapBuilder.build();
}
public Class<?> getDeclaring() {
return declaring;
}
@Override
protected Object handleInvocation(Object proxy, Invokable<?, ?> method, List<Object> args) throws Throwable {
if (method.isAnnotationPresent(Delegate.class)) {
Class<?> syncClass = Optionals2.returnTypeOrTypeOfOptional(method);
// get the return type of the asynchronous class associated with this client
// ex. FloatingIPClient is associated with FloatingIPAsyncClient
Class<?> asyncClass = sync2Async.get(syncClass);
checkState(asyncClass != null, "please configure corresponding async class for " + syncClass
+ " in your RestClientModule");
// pass any parameters necessary to get a relevant instance of that async class
// ex. getClientForRegion("north") might return an instance whose endpoint is
// different that "south"
ClassInvokerArgs cma = ClassInvokerArgs.builder().clazz(asyncClass).invoker(method).args(args).build();
Object returnVal = delegateMap.get(cma);
if (Optionals2.isReturnTypeOptional(method)){
ClassInvokerArgsAndReturnVal cmar = ClassInvokerArgsAndReturnVal.builder().fromClassInvokerArgs(cma)
.returnVal(returnVal).build();
return optionalConverter.apply(cmar);
}
return returnVal;
} else if (syncMethodMap.containsKey(method)) {
try {
return syncMethodMap.get(method).invoke(delegate, args.toArray());
} catch (InvocationTargetException e) {
throw Throwables.propagate(e.getCause());
}
} else {
try {
Optional<Long> timeoutNanos = timeoutMap.get(method);
Invokable<Object, ListenableFuture<?>> asyncMethod = methodMap.get(method);
String name = asyncMethod.getDeclaringClass().getSimpleName() + "." + asyncMethod.getName();
ListenableFuture<?> future = asyncMethod.invoke(delegate, args.toArray());
if (timeoutNanos.isPresent()) {
logger.debug(">> blocking on %s for %s", name, timeoutNanos);
return future.get(timeoutNanos.get(), TimeUnit.NANOSECONDS);
}
logger.debug(">> blocking on %s", name);
return future.get();
} catch (ProvisionException e) {
throw Throwables2.returnFirstExceptionIfInListOrThrowStandardExceptionOrCause(method.getExceptionTypes(), e);
} catch (ExecutionException e) {
throw Throwables2.returnFirstExceptionIfInListOrThrowStandardExceptionOrCause(method.getExceptionTypes(), e);
} catch (Exception e) {
throw Throwables2.returnFirstExceptionIfInListOrThrowStandardExceptionOrCause(method.getExceptionTypes(), e);
public Result apply(Invocation invocation) {
if (invocation.getInvokable().isAnnotationPresent(Delegate.class))
return forwardToDelegate(invocation);
if (syncMethodMap.containsKey(invocation.getInvokable()))
return invokeOnDelegate(invocation);
return invokeFutureAndBlock(invocation);
}
private Result forwardToDelegate(Invocation invocation) {
Class<?> returnType = Optionals2.unwrapIfOptional(invocation.getInvokable().getReturnType());
// get the return type of the asynchronous class associated with this client
// ex. FloatingIPClient is associated with FloatingIPAsyncClient
Class<?> asyncClass = sync2Async.get(returnType);
checkState(asyncClass != null, "please configure corresponding async class for %s in your RestClientModule",
returnType);
// pass any parameters necessary to get a relevant instance of that async class
// ex. getClientForRegion("north") might return an instance whose endpoint is
// different that "south"
ForwardInvocationToInterface cma = ForwardInvocationToInterface.create(invocation, asyncClass);
Object result = createClientForCaller.apply(cma);
if (Optionals2.isReturnTypeOptional(invocation.getInvokable())) {
result = optionalConverter.apply(InvocationSuccess.create(invocation, result));
}
return Result.success(result);
}
private Result invokeFutureAndBlock(Invocation invocation) {
try {
Invokable<Object, ListenableFuture<?>> asyncMethod = invokedMap.get(invocation.getInvokable());
ListenableFuture<?> future = asyncMethod.invoke(delegate, invocation.getArgs().toArray());
Optional<Long> timeoutNanos = timeoutMap.get(invocation.getInvokable());
return block(future, timeoutNanos);
} catch (InvocationTargetException e) {
return Result.fail(e);
} catch (IllegalAccessException e) {
return Result.fail(e);
}
}
private Result block(ListenableFuture<?> future, Optional<Long> timeoutNanos) {
try {
if (timeoutNanos.isPresent()) {
logger.debug(">> blocking on %s for %s", future, timeoutNanos);
return Result.success(future.get(timeoutNanos.get(), TimeUnit.NANOSECONDS));
} else {
logger.debug(">> blocking on %s", future);
return Result.success(future.get());
}
} catch (ExecutionException e) {
return Result.fail(e.getCause());
} catch (InterruptedException e) {
return Result.fail(e); // TODO: should we kill the future?
} catch (TimeoutException e) {
return Result.fail(e);
}
}
private Result invokeOnDelegate(Invocation invocation) {
Invokable<Object, ?> toInvoke = syncMethodMap.get(invocation.getInvokable());
try {
return Result.success(toInvoke.invoke(delegate, invocation.getArgs().toArray()));
} catch (InvocationTargetException e) {
return Result.fail(e);
} catch (IllegalAccessException e) {
return Result.fail(e);
}
}
// override timeout by values configured in properties(in ms)
private Optional<Long> timeoutInNanos(Invokable<?, ?> method, Map<String, Long> timeouts) {
private Optional<Long> timeoutInNanos(Invokable<?, ?> invoked, Map<String, Long> timeouts) {
String className = declaring.getSimpleName();
Optional<Long> timeoutMillis = fromNullable(timeouts.get(className + "." + method.getName()))
.or(fromNullable(timeouts.get(className)))
.or(fromNullable(timeouts.get("default")));
Optional<Long> timeoutMillis = fromNullable(timeouts.get(className + "." + invoked.getName())).or(
fromNullable(timeouts.get(className))).or(fromNullable(timeouts.get("default")));
if (timeoutMillis.isPresent())
return Optional.of(TimeUnit.MILLISECONDS.toNanos(timeoutMillis.get()));
return Optional.absent();
}
@Override
public String toString() {
return "blocking invocation handler for: " + delegate.getClass().getSimpleName();
return String.format("%s->%s", declaring.getClass().getSimpleName(), delegate.getClass().getSimpleName());
}
}

View File

@ -23,6 +23,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
import org.jclouds.rest.internal.GeneratedHttpRequest;
import com.google.common.base.Objects;
import com.google.common.reflect.Invokable;
/**
* Command whose endpoint is an http service.
@ -131,12 +132,13 @@ public class HttpCommand {
@Override
public String toString() {
if (request instanceof GeneratedHttpRequest)
return String.format("[method=%s.%s, request=%s]", GeneratedHttpRequest.class.cast(request).getDeclaring()
.getSimpleName(), GeneratedHttpRequest.class.cast(request).getInvoker().getName(), request
.getRequestLine());
else
return "[request=" + request.getRequestLine() + "]";
if (request instanceof GeneratedHttpRequest) {
GeneratedHttpRequest gRequest = GeneratedHttpRequest.class.cast(request);
return String.format("[method=%s.%s, request=%s]",
gRequest.getInvocation().getInterfaceType().getSimpleName(), gRequest.getInvocation().getInvokable()
.getName(), gRequest.getRequestLine());
}
return "[request=" + request.getRequestLine() + "]";
}
}

View File

@ -212,7 +212,7 @@ public class ParseSax<T> implements Function<HttpResponse, T>, InvocationContext
@Override
public HandlerForGeneratedRequestWithResult<T> setContext(HttpRequest request) {
checkArgument(request instanceof GeneratedHttpRequest, "note this handler requires a GeneratedHttpRequest");
checkArgument(checkNotNull(request, "request") instanceof GeneratedHttpRequest, "note this handler requires a GeneratedHttpRequest");
super.setContext(request);
return this;
}

View File

@ -1,149 +0,0 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds 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.internal;
import static com.google.common.base.Objects.equal;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.List;
import com.google.common.base.Objects;
import com.google.common.base.Objects.ToStringHelper;
import com.google.common.collect.ImmutableList;
import com.google.common.reflect.Invokable;
/**
*
* @author Adrian Cole
*/
public class ClassInvokerArgs {
public static Builder<?> builder() {
return new ConcreteBuilder();
}
public Builder<?> toBuilder() {
return builder().fromClassInvokerArgs(this);
}
private static class ConcreteBuilder extends Builder<ConcreteBuilder> {
}
public abstract static class Builder<B extends Builder<B>> {
private Class<?> clazz;
private Invokable<?, ?> invoker;
private List<Object> args = ImmutableList.of();
@SuppressWarnings("unchecked")
protected B self() {
return (B) this;
}
/**
* @see ClassInvokerArgs#getClazz()
*/
public B clazz(Class<?> clazz) {
this.clazz = clazz;
return self();
}
/**
* @see ClassInvokerArgs#getInvoker()
*/
public B invoker(Invokable<?, ?> invoker) {
this.invoker = invoker;
return self();
}
/**
* @see ClassInvokerArgs#getArgs()
*/
public B args(List<Object> args) {
this.args = args;
return self();
}
public ClassInvokerArgs build() {
return new ClassInvokerArgs(this);
}
public B fromClassInvokerArgs(ClassInvokerArgs in) {
return clazz(in.getClazz()).invoker(in.getInvoker()).args(in.getArgs());
}
}
private final Class<?> clazz;
private final Invokable<?, ?> invoker;
private final List<Object> args;
public ClassInvokerArgs(Builder<?> builder) {
this(builder.clazz, builder.invoker, builder.args);
}
/**
* @param args as these represent parameters, can contain nulls
*/
public ClassInvokerArgs(Class<?> clazz, Invokable<?, ?> invoker, List<Object> args) {
this.clazz = checkNotNull(clazz, "clazz");
this.invoker = checkNotNull(invoker, "invoker");
this.args = checkNotNull(args, "args");
}
/**
* not necessarily the declaring class of the invoker.
*/
public Class<?> getClazz() {
return clazz;
}
public Invokable<?, ?> getInvoker() {
return invoker;
}
/**
* @param args as these represent parameters, can contain nulls
*/
public List<Object> getArgs() {
return args;
}
@Override
public boolean equals(Object o) {
if (this == o)
return true;
if (o == null || getClass() != o.getClass())
return false;
ClassInvokerArgs that = ClassInvokerArgs.class.cast(o);
return equal(this.clazz, that.clazz) && equal(this.invoker, that.invoker) && equal(this.args, that.args);
}
@Override
public int hashCode() {
return Objects.hashCode(clazz, invoker, args);
}
@Override
public String toString() {
return string().toString();
}
protected ToStringHelper string() {
return Objects.toStringHelper("").omitNullValues().add("clazz", clazz).add("invoker", invoker)
.add("args", args.size() != 0 ? args : null);
}
}

View File

@ -1,101 +0,0 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds 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.internal;
import static com.google.common.base.Objects.equal;
import java.util.List;
import com.google.common.base.Objects;
import com.google.common.base.Objects.ToStringHelper;
import com.google.common.reflect.Invokable;
/**
*
* @author Adrian Cole
*/
public final class ClassInvokerArgsAndReturnVal extends ClassInvokerArgs {
public static Builder builder() {
return new Builder();
}
public Builder toBuilder() {
return builder().fromClassInvokerArgsAndReturnVal(this);
}
public final static class Builder extends ClassInvokerArgs.Builder<Builder> {
private Object returnVal;
/**
* @see ClassInvokerArgsAndReturnVal#getReturnVal()
*/
public Builder returnVal(Object returnVal) {
this.returnVal = returnVal;
return this;
}
@Override
public ClassInvokerArgsAndReturnVal build() {
return new ClassInvokerArgsAndReturnVal(this);
}
public Builder fromClassInvokerArgsAndReturnVal(ClassInvokerArgsAndReturnVal in) {
return fromClassInvokerArgs(in).returnVal(in.getReturnVal());
}
}
private final Object returnVal;
private ClassInvokerArgsAndReturnVal(Class<?> clazz, Invokable<?, ?> invoker, List<Object> args, Object returnVal) {
super(clazz, invoker, args);
this.returnVal = returnVal;
}
private ClassInvokerArgsAndReturnVal(Builder builder) {
super(builder);
this.returnVal = builder.returnVal;
}
public Object getReturnVal() {
return returnVal;
}
@Override
public boolean equals(Object o) {
if (this == o)
return true;
if (o == null || getClass() != o.getClass())
return false;
ClassInvokerArgsAndReturnVal that = ClassInvokerArgsAndReturnVal.class.cast(o);
return super.equals(that) && equal(this.returnVal, that.returnVal);
}
@Override
public int hashCode() {
return Objects.hashCode(super.hashCode(), returnVal);
}
@Override
public ToStringHelper string() {
return super.string().add("returnVal", returnVal);
}
}

View File

@ -0,0 +1,84 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds 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.internal;
import static com.google.common.base.Objects.equal;
import static com.google.common.base.Preconditions.checkNotNull;
import org.jclouds.reflect.Invocation;
import com.google.common.annotations.Beta;
import com.google.common.base.Objects;
import com.google.common.base.Objects.ToStringHelper;
/**
* internal type to {@link SyncProxy} which is likely to be removed
*
* @author Adrian Cole
*/
@Beta
public final class ForwardInvocationToInterface {
/**
* @param interfaceType
* {@link #getInterfaceType()}
*/
public static ForwardInvocationToInterface create(Invocation invocation, Class<?> interfaceType) {
return new ForwardInvocationToInterface(invocation, interfaceType);
}
private final Invocation invocation;
private final Class<?> interfaceType;
private ForwardInvocationToInterface(Invocation invocation, Class<?> interfaceType) {
this.invocation = checkNotNull(invocation, "invocation");
this.interfaceType = checkNotNull(interfaceType, "interfaceType");
}
public Invocation getInvocation() {
return invocation;
}
public Class<?> getInterfaceType() {
return interfaceType;
}
@Override
public boolean equals(Object o) {
if (this == o)
return true;
if (o == null || getClass() != o.getClass())
return false;
ForwardInvocationToInterface that = ForwardInvocationToInterface.class.cast(o);
return equal(this.invocation, that.invocation) && equal(this.interfaceType, that.interfaceType);
}
@Override
public int hashCode() {
return Objects.hashCode(invocation, interfaceType);
}
@Override
public String toString() {
return string().toString();
}
protected ToStringHelper string() {
return Objects.toStringHelper("").omitNullValues().add("invocation", invocation).add("interfaceType", interfaceType);
}
}

View File

@ -32,7 +32,6 @@ import javax.inject.Singleton;
import org.jclouds.collect.Memoized;
import org.jclouds.domain.Location;
import org.jclouds.internal.ClassInvokerArgsAndReturnVal;
import org.jclouds.location.Iso3166;
import org.jclouds.location.Provider;
import org.jclouds.location.Region;
@ -49,6 +48,7 @@ import org.jclouds.location.suppliers.RegionIdToZoneIdsSupplier;
import org.jclouds.location.suppliers.RegionIdsSupplier;
import org.jclouds.location.suppliers.ZoneIdToURISupplier;
import org.jclouds.location.suppliers.ZoneIdsSupplier;
import org.jclouds.reflect.InvocationSuccess;
import org.jclouds.rest.AuthorizationException;
import org.jclouds.rest.functions.ImplicitOptionalConverter;
import org.jclouds.rest.suppliers.MemoizedRetryOnTimeOutButNotOnAuthorizationExceptionSupplier;
@ -73,7 +73,7 @@ public class LocationModule extends AbstractModule {
@Override
protected void configure() {
bind(new TypeLiteral<Function<ClassInvokerArgsAndReturnVal, Optional<Object>>>(){}).to(ImplicitOptionalConverter.class);
bind(new TypeLiteral<Function<InvocationSuccess, Optional<Object>>>(){}).to(ImplicitOptionalConverter.class);
}
@Provides

View File

@ -1,58 +0,0 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds 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.reflect;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import com.google.common.annotations.Beta;
import com.google.common.base.Predicates;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.google.common.reflect.Invokable;
/**
* Like {@link com.google.common.reflect.AbstractInvocationHandler}, except you process {@link Invokable} and
* {@link List} as opposed to {@link Method} and arg arrays.
*
* @author Adrian Cole
* @since 1.6
*/
@Beta
public abstract class AbstractInvocationHandler extends com.google.common.reflect.AbstractInvocationHandler {
/**
* @param args
* note that this can contain nulls, as method arguments can be null.
* @see com.google.common.reflect.AbstractInvocationHandler#invoke(Object, Method, Object[])
*/
protected abstract Object handleInvocation(Object proxy, Invokable<?, ?> method, List<Object> args) throws Throwable;
@Override
protected Object handleInvocation(Object proxy, Method method, Object[] argv) throws Throwable {
List<Object> args = Arrays.asList(argv);
if (Iterables.all(args, Predicates.notNull()))
args = ImmutableList.copyOf(args);
else
args = Collections.unmodifiableList(args);
return handleInvocation(proxy, Invokable.from(method), args);
}
}

View File

@ -26,12 +26,12 @@ import java.util.List;
import javax.inject.Inject;
import org.jclouds.predicates.Validator;
import org.jclouds.reflect.Invocation;
import org.jclouds.rest.annotations.ParamValidators;
import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.reflect.Invokable;
import com.google.common.reflect.Parameter;
import com.google.inject.Injector;
@ -70,14 +70,13 @@ public class InputParamValidator {
* @throws IllegalStateException
* if validation failed
*/
public void validateMethodParametersOrThrow(Invokable<?, ?> method, List<Object> args) {
public void validateMethodParametersOrThrow(Invocation invocation) {
try {
performMethodValidation(checkNotNull(method, "method"), args);
performParameterValidation(method.getParameters(), args);
performMethodValidation(checkNotNull(invocation, "invocation"));
performParameterValidation(invocation);
} catch (IllegalArgumentException e) {
throw new IllegalArgumentException(String.format("Validation on '%s#%s' didn't pass for arguments: "
+ "%s. %n Reason: %s.", method.getDeclaringClass().getName(), method.getName(), args,
e.getMessage()));
throw new IllegalArgumentException(String.format("Validation on '%s' didn't pass:%n Reason: %s.", invocation,
e.getMessage()), e);
}
}
@ -90,14 +89,14 @@ public class InputParamValidator {
* @param args
* method's parameters
*/
private void performMethodValidation(Invokable<?, ?> method, List<Object> args) {
ParamValidators paramValidatorsAnnotation = method.getAnnotation(ParamValidators.class);
private void performMethodValidation(Invocation invocation) {
ParamValidators paramValidatorsAnnotation = invocation.getInvokable().getAnnotation(ParamValidators.class);
if (paramValidatorsAnnotation == null)
return; // by contract
List<Validator<?>> methodValidators = getValidatorsFromAnnotation(paramValidatorsAnnotation);
runPredicatesAgainstArgs(methodValidators, args);
runPredicatesAgainstArgs(methodValidators, invocation.getArgs());
}
/**
@ -109,8 +108,8 @@ public class InputParamValidator {
* @param args
* arguments that correspond to the array of annotations
*/
private void performParameterValidation(List<Parameter> parameters, List<Object> args) {
for (Parameter param : filter(parameters, new Predicate<Parameter>() {
private void performParameterValidation(Invocation invocation) {
for (Parameter param : filter(invocation.getInvokable().getParameters(), new Predicate<Parameter>() {
public boolean apply(Parameter in) {
return in.isAnnotationPresent(ParamValidators.class);
}
@ -119,7 +118,8 @@ public class InputParamValidator {
if (annotation == null)
continue;
List<Validator<?>> parameterValidators = getValidatorsFromAnnotation(annotation);
runPredicatesAgainstArg(parameterValidators, args.get(param.hashCode()));// TODO position guava issue 1243
// TODO position guava issue 1243
runPredicatesAgainstArg(parameterValidators, invocation.getArgs().get(param.hashCode()));
}
}
@ -130,7 +130,7 @@ public class InputParamValidator {
}
return validators;
}
@SuppressWarnings("unchecked")
private void runPredicatesAgainstArg(List<Validator<?>> predicates, Object arg) {
for (@SuppressWarnings("rawtypes")

View File

@ -32,21 +32,24 @@ import org.jclouds.rest.MapBinder;
import org.jclouds.rest.annotations.Payload;
import org.jclouds.rest.internal.GeneratedHttpRequest;
import com.google.common.reflect.Invokable;
/**
*
* @author Adrian Cole
*/
@Singleton
public class BindMapToStringPayload implements MapBinder {
@SuppressWarnings("unchecked")
@Override
public <R extends HttpRequest> R bindToRequest(R request, Map<String, Object> postParams) {
checkNotNull(postParams, "postParams");
GeneratedHttpRequest r = GeneratedHttpRequest.class.cast(checkNotNull(request, "request"));
checkArgument(r.getInvoker().isAnnotationPresent(Payload.class),
"method %s must have @Payload annotation to use this binder", r.getInvoker());
String payload = r.getInvoker().getAnnotation(Payload.class).value();
Invokable<?, ?> invoked = r.getInvocation().getInvokable();
checkArgument(invoked.isAnnotationPresent(Payload.class),
"method %s must have @Payload annotation to use this binder", invoked);
String payload = invoked.getAnnotation(Payload.class).value();
if (postParams.size() > 0) {
payload = urlDecode(expand(payload, postParams));
}

View File

@ -18,13 +18,11 @@
*/
package org.jclouds.rest.config;
import static com.google.common.reflect.Reflection.newProxy;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.jclouds.reflect.FunctionalReflection;
import org.jclouds.rest.internal.AsyncRestClientProxy;
import org.jclouds.rest.internal.AsyncRestClientProxy.Factory;
import com.google.inject.Provider;
import com.google.inject.TypeLiteral;
@ -36,11 +34,11 @@ import com.google.inject.TypeLiteral;
@Singleton
public class AsyncClientProvider<A> implements Provider<A> {
private final Class<? super A> asyncClientType;
private final Factory factory;
private final AsyncRestClientProxy proxy;
@Inject
private AsyncClientProvider(AsyncRestClientProxy.Factory factory, TypeLiteral<A> asyncClientType) {
this.factory = factory;
private AsyncClientProvider(AsyncRestClientProxy proxy, TypeLiteral<A> asyncClientType) {
this.proxy = proxy;
this.asyncClientType = asyncClientType.getRawType();
}
@ -48,7 +46,7 @@ public class AsyncClientProvider<A> implements Provider<A> {
@Override
@Singleton
public A get() {
return (A) newProxy(asyncClientType, factory.declaring(asyncClientType));
return (A) FunctionalReflection.newProxy(asyncClientType, proxy);
}
}

View File

@ -18,12 +18,11 @@
*/
package org.jclouds.rest.config;
import static com.google.common.reflect.Reflection.newProxy;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.jclouds.concurrent.internal.SyncProxy;
import org.jclouds.reflect.FunctionalReflection;
import com.google.inject.Provider;
@ -50,6 +49,6 @@ public class ClientProvider<S, A> implements Provider<S> {
@Override
@Singleton
public S get() {
return newProxy(syncClientType, factory.create(syncClientType, asyncClient));
return FunctionalReflection.newProxy(syncClientType, factory.create(syncClientType, asyncClient));
}
}

View File

@ -29,10 +29,11 @@ import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.concurrent.internal.SyncProxy;
import org.jclouds.concurrent.internal.SyncProxy.CreateClientForCaller;
import org.jclouds.functions.IdentityFunction;
import org.jclouds.http.functions.config.SaxParserModule;
import org.jclouds.internal.ClassInvokerArgs;
import org.jclouds.internal.FilterStringsBoundToInjectorByName;
import org.jclouds.internal.ForwardInvocationToInterface;
import org.jclouds.json.config.GsonModule;
import org.jclouds.location.config.LocationModule;
import org.jclouds.rest.AuthorizationException;
@ -40,8 +41,6 @@ import org.jclouds.rest.HttpAsyncClient;
import org.jclouds.rest.HttpClient;
import org.jclouds.rest.binders.BindToJsonPayloadWrappedWith;
import org.jclouds.rest.internal.AsyncRestClientProxy;
import org.jclouds.rest.internal.CreateAsyncClientForCaller;
import org.jclouds.rest.internal.CreateClientForCaller;
import org.jclouds.rest.internal.RestAnnotationProcessor;
import org.jclouds.util.Maps2;
import org.jclouds.util.Predicates2;
@ -49,8 +48,6 @@ import org.jclouds.util.Predicates2;
import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.base.Supplier;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
import com.google.common.util.concurrent.Atomics;
@ -84,8 +81,8 @@ public class RestModule extends AbstractModule {
install(new SaxParserModule());
install(new GsonModule());
install(new FactoryModuleBuilder().build(BindToJsonPayloadWrappedWith.Factory.class));
install(new FactoryModuleBuilder().build(RestAnnotationProcessor.Factory.class));
install(new FactoryModuleBuilder().build(AsyncRestClientProxy.Factory.class));
install(new FactoryModuleBuilder().build(RestAnnotationProcessor.Caller.Factory.class));
install(new FactoryModuleBuilder().build(AsyncRestClientProxy.Caller.Factory.class));
bind(IdentityFunction.class).toInstance(IdentityFunction.INSTANCE);
install(new FactoryModuleBuilder().build(SyncProxy.Factory.class));
bindClientAndAsyncClient(binder(), HttpClient.class, HttpAsyncClient.class);
@ -94,6 +91,10 @@ public class RestModule extends AbstractModule {
}).toInstance(authException);
bind(new TypeLiteral<Function<Predicate<String>, Map<String, String>>>() {
}).to(FilterStringsBoundToInjectorByName.class);
bind(new TypeLiteral<Function<Predicate<String>, Map<String, String>>>() {
}).to(FilterStringsBoundToInjectorByName.class);
bind(new TypeLiteral<Function<ForwardInvocationToInterface, Object>>() {
}).to(CreateClientForCaller.class);
installLocations();
}
@ -120,19 +121,4 @@ public class RestModule extends AbstractModule {
});
}
@Provides
@Singleton
@Named("async")
LoadingCache<ClassInvokerArgs, Object> provideAsyncDelegateMap(CreateAsyncClientForCaller createAsyncClientForCaller) {
return CacheBuilder.newBuilder().build(createAsyncClientForCaller);
}
@Provides
@Singleton
@Named("sync")
LoadingCache<ClassInvokerArgs, Object> provideSyncDelegateMap(CreateClientForCaller createClientForCaller) {
return CacheBuilder.newBuilder().build(createClientForCaller);
}
}

View File

@ -18,7 +18,7 @@
*/
package org.jclouds.rest.functions;
import org.jclouds.internal.ClassInvokerArgsAndReturnVal;
import org.jclouds.reflect.InvocationSuccess;
import com.google.common.annotations.Beta;
import com.google.common.base.Optional;
@ -31,8 +31,8 @@ import com.google.common.base.Optional;
public class AlwaysPresentImplicitOptionalConverter implements ImplicitOptionalConverter {
@Override
public Optional<Object> apply(ClassInvokerArgsAndReturnVal input) {
return Optional.of(input.getReturnVal());
public Optional<Object> apply(InvocationSuccess input) {
return input.getResult();
}
}

View File

@ -18,7 +18,9 @@
*/
package org.jclouds.rest.functions;
import org.jclouds.internal.ClassInvokerArgsAndReturnVal;
import org.jclouds.reflect.InvocationSuccess;
import org.jclouds.rest.annotations.ApiVersion;
import org.jclouds.rest.annotations.SinceApiVersion;
import org.jclouds.rest.config.RestClientModule;
import com.google.common.annotations.Beta;
@ -39,19 +41,19 @@ import com.google.inject.ImplementedBy;
* }
* </pre>
*
* The input object of type {@link ClassInvokerArgsAndReturnVal} will include the
* The input object of type {@link InvocationSuccess} will include the
* following.
* <ol>
* <li>the class declaring the method that returns optional:
* {@link ClassInvokerArgsAndReturnVal#getClazz}; in the example above,
* {@link InvocationSuccess#getClazz}; in the example above,
* {@code MyCloud}</li>
* <li>the method returning the optional:
* {@link ClassInvokerArgsAndReturnVal#getMethod}; in the example above,
* {@link InvocationSuccess#getMethod}; in the example above,
* {@code getKeyPairExtensionForRegion}</li>
* <li>the args passed to that method at runtime:
* {@link ClassInvokerArgsAndReturnVal#getArgs}; for example {@code North}</li>
* {@link InvocationSuccess#getArgs}; for example {@code North}</li>
* <li>the rest client to be enclosed in the optional, should you choose to
* return it: {@link ClassInvokerArgsAndReturnVal#getReturnVal}; in the example
* return it: {@link InvocationSuccess#getReturnVal}; in the example
* above, an implementation of {@code KeyPairClient}</li>
* </ol>
*
@ -80,6 +82,6 @@ import com.google.inject.ImplementedBy;
*/
@Beta
@ImplementedBy(PresentWhenApiVersionLexicographicallyAtOrAfterSinceApiVersion.class)
public interface ImplicitOptionalConverter extends Function<ClassInvokerArgsAndReturnVal, Optional<Object>> {
public interface ImplicitOptionalConverter extends Function<InvocationSuccess, Optional<Object>> {
}

View File

@ -19,11 +19,12 @@
package org.jclouds.rest.functions;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.util.Optionals2.unwrapIfOptional;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.jclouds.internal.ClassInvokerArgsAndReturnVal;
import org.jclouds.reflect.InvocationSuccess;
import org.jclouds.rest.annotations.ApiVersion;
import org.jclouds.rest.annotations.SinceApiVersion;
@ -43,7 +44,7 @@ import com.google.common.cache.LoadingCache;
public class PresentWhenApiVersionLexicographicallyAtOrAfterSinceApiVersion implements ImplicitOptionalConverter {
@VisibleForTesting
static final class Loader extends CacheLoader<ClassInvokerArgsAndReturnVal, Optional<Object>> {
static final class Loader extends CacheLoader<InvocationSuccess, Optional<Object>> {
private final String apiVersion;
@Inject
@ -52,22 +53,22 @@ public class PresentWhenApiVersionLexicographicallyAtOrAfterSinceApiVersion impl
}
@Override
public Optional<Object> load(ClassInvokerArgsAndReturnVal input) {
Optional<SinceApiVersion> sinceApiVersion = Optional.fromNullable(input.getClazz().getAnnotation(
SinceApiVersion.class));
public Optional<Object> load(InvocationSuccess input) {
Class<?> target = unwrapIfOptional(input.getInvocation().getInvokable().getReturnType());
Optional<SinceApiVersion> sinceApiVersion = Optional.fromNullable(target.getAnnotation(SinceApiVersion.class));
if (sinceApiVersion.isPresent()) {
String since = sinceApiVersion.get().value();
if (since.compareTo(apiVersion) <= 0)
return Optional.of(input.getReturnVal());
return input.getResult();
return Optional.absent();
} else {
// No SinceApiVersion annotation, so return present
return Optional.of(input.getReturnVal());
return input.getResult();
}
}
}
private final LoadingCache<ClassInvokerArgsAndReturnVal, Optional<Object>> lookupCache;
private final LoadingCache<InvocationSuccess, Optional<Object>> lookupCache;
@Inject
protected PresentWhenApiVersionLexicographicallyAtOrAfterSinceApiVersion(@ApiVersion String apiVersion) {
@ -76,7 +77,7 @@ public class PresentWhenApiVersionLexicographicallyAtOrAfterSinceApiVersion impl
}
@Override
public Optional<Object> apply(ClassInvokerArgsAndReturnVal input) {
public Optional<Object> apply(InvocationSuccess input) {
return lookupCache.getUnchecked(input);
}

View File

@ -19,6 +19,9 @@
package org.jclouds.rest.internal;
import static com.google.common.base.Functions.compose;
import static com.google.common.base.Objects.equal;
import static com.google.common.base.Predicates.in;
import static com.google.common.base.Predicates.not;
import static com.google.common.base.Throwables.propagate;
import static com.google.common.collect.Iterables.any;
import static com.google.common.collect.Iterables.find;
@ -31,7 +34,7 @@ import static javax.ws.rs.core.MediaType.APPLICATION_XML;
import static org.jclouds.concurrent.Futures.makeListenable;
import static org.jclouds.http.HttpUtils.tryFindHttpMethod;
import static org.jclouds.util.Optionals2.isReturnTypeOptional;
import static org.jclouds.util.Optionals2.returnTypeOrTypeOfOptional;
import static org.jclouds.util.Optionals2.unwrapIfOptional;
import static org.jclouds.util.Throwables2.getFirstThrowableOfType;
import java.io.InputStream;
@ -41,7 +44,6 @@ import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.WildcardType;
import java.net.URI;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
@ -73,11 +75,12 @@ import org.jclouds.http.functions.ReturnInputStream;
import org.jclouds.http.functions.ReturnStringIf2xx;
import org.jclouds.http.functions.ReturnTrueIf2xx;
import org.jclouds.http.functions.UnwrapOnlyJsonValue;
import org.jclouds.internal.ClassInvokerArgs;
import org.jclouds.internal.ClassInvokerArgsAndReturnVal;
import org.jclouds.json.internal.GsonWrapper;
import org.jclouds.logging.Logger;
import org.jclouds.reflect.AbstractInvocationHandler;
import org.jclouds.reflect.FunctionalReflection;
import org.jclouds.reflect.Invocation;
import org.jclouds.reflect.Invocation.Result;
import org.jclouds.reflect.InvocationSuccess;
import org.jclouds.rest.AuthorizationException;
import org.jclouds.rest.InvocationContext;
import org.jclouds.rest.annotations.Delegate;
@ -95,7 +98,6 @@ import com.google.common.base.Function;
import com.google.common.base.Objects;
import com.google.common.base.Optional;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.base.Supplier;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
@ -103,7 +105,6 @@ import com.google.common.cache.LoadingCache;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Maps;
import com.google.common.reflect.Invokable;
import com.google.common.reflect.Parameter;
import com.google.common.reflect.TypeToken;
@ -123,49 +124,36 @@ import com.google.inject.assistedinject.Assisted;
* <p/>
* Particularly, this code delegates calls to other things.
* <ol>
* <li>if the method has a {@link Provides} annotation, it responds via a {@link Injector} lookup</li>
* <li>if the method has a {@link Delegate} annotation, it responds with an instance of interface set in returnVal,
* <li>if the invoked has a {@link Provides} annotation, it responds via a {@link Injector} lookup</li>
* <li>if the invoked has a {@link Delegate} annotation, it responds with an instance of interface set in returnVal,
* adding the current JAXrs annotations to whatever are on that class.</li>
* <ul>
* <li>ex. if the method with {@link Delegate} has a {@code Path} annotation, and the returnval interface also has
* <li>ex. if the invoked with {@link Delegate} has a {@code Path} annotation, and the returnval interface also has
* {@code Path}, these values are combined.</li>
* </ul>
* <li>if {@link RestAnnotationProcessor#delegationMap} contains a mapping for this, and the returnVal is properly
* assigned as a {@link ListenableFuture}, it responds with an http implementation.</li>
* <li>otherwise a RuntimeException is thrown with a message including:
* {@code method is intended solely to set constants}</li>
* {@code invoked is intended solely to set constants}</li>
* </ol>
*
* @author Adrian Cole
*/
@Singleton
public abstract class AsyncRestClientProxy extends AbstractInvocationHandler {
public static interface Factory {
Declaring declaring(Class<?> declaring);
Caller caller(ClassInvokerArgs caller);
}
public final static class Declaring extends AsyncRestClientProxy {
@Inject
private Declaring(Injector injector, Function<ClassInvokerArgsAndReturnVal, Optional<Object>> optionalConverter,
HttpCommandExecutorService http, @Named(Constants.PROPERTY_USER_THREADS) ExecutorService userThreads,
@Named("async") LoadingCache<ClassInvokerArgs, Object> delegateMap, RestAnnotationProcessor.Factory rap,
ParseSax.Factory parserFactory, @Assisted Class<?> declaring) {
super(injector, optionalConverter, http, userThreads, delegateMap, rap.declaring(declaring), parserFactory,
declaring);
}
}
public class AsyncRestClientProxy implements Function<Invocation, Result> {
public final static class Caller extends AsyncRestClientProxy {
public static interface Factory {
Caller caller(Invocation caller, Class<?> interfaceType);
}
@Inject
private Caller(Injector injector, Function<ClassInvokerArgsAndReturnVal, Optional<Object>> optionalConverter,
private Caller(Injector injector, Function<InvocationSuccess, Optional<Object>> optionalConverter,
HttpCommandExecutorService http, @Named(Constants.PROPERTY_USER_THREADS) ExecutorService userThreads,
@Named("async") LoadingCache<ClassInvokerArgs, Object> delegateMap, RestAnnotationProcessor.Factory rap,
ParseSax.Factory parserFactory, @Assisted ClassInvokerArgs caller) {
super(injector, optionalConverter, http, userThreads, delegateMap, rap.caller(caller), parserFactory, caller
.getClazz());
Caller.Factory factory, RestAnnotationProcessor.Caller.Factory rap, ParseSax.Factory parserFactory,
@Assisted Invocation caller) {
super(injector, optionalConverter, http, userThreads, factory, rap.caller(caller), parserFactory);
}
}
@ -175,18 +163,16 @@ public abstract class AsyncRestClientProxy extends AbstractInvocationHandler {
private final Injector injector;
private final HttpCommandExecutorService http;
private final ExecutorService userThreads;
private final Function<ClassInvokerArgsAndReturnVal, Optional<Object>> optionalConverter;
private final LoadingCache<ClassInvokerArgs, Object> delegateMap;
private final Function<InvocationSuccess, Optional<Object>> optionalConverter;
private final Caller.Factory factory;
private final RestAnnotationProcessor annotationProcessor;
private final ParseSax.Factory parserFactory;
private final Class<?> declaring;
private static final LoadingCache<Class<?>, Set<Integer>> delegationMapCache = CacheBuilder.newBuilder().build(
new CacheLoader<Class<?>, Set<Integer>>() {
public Set<Integer> load(Class<?> declaring) throws ExecutionException {
FluentIterable<Invokable<?, ?>> methodsToProcess = FluentIterable
.from(ImmutableSet.copyOf(declaring.getMethods()))
.filter(Predicates.not(Predicates.in(ImmutableSet.copyOf(Object.class.getMethods()))))
private static final LoadingCache<Class<?>, Set<InterfaceNameAndParameters>> delegationMapCache = CacheBuilder
.newBuilder().build(new CacheLoader<Class<?>, Set<InterfaceNameAndParameters>>() {
public Set<InterfaceNameAndParameters> load(final Class<?> interfaceType) throws ExecutionException {
return FluentIterable.from(ImmutableSet.copyOf(interfaceType.getMethods()))
.filter(not(in(ImmutableSet.copyOf(Object.class.getMethods()))))
.transform(new Function<Method, Invokable<?, ?>>() {
public Invokable<?, ?> apply(Method in) {
return Invokable.from(in);
@ -194,7 +180,7 @@ public abstract class AsyncRestClientProxy extends AbstractInvocationHandler {
}).filter(new Predicate<Invokable<?, ?>>() {
public boolean apply(Invokable<?, ?> in) {
return in.isAnnotationPresent(Path.class) || tryFindHttpMethod(in).isPresent()
|| any(in.getParameters(), new Predicate<Parameter>(){
|| any(in.getParameters(), new Predicate<Parameter>() {
public boolean apply(Parameter in) {
return in.getType().getRawType().isAssignableFrom(HttpRequest.class);
}
@ -204,86 +190,97 @@ public abstract class AsyncRestClientProxy extends AbstractInvocationHandler {
public boolean apply(Invokable<?, ?> in) {
return in.getReturnType().getRawType().isAssignableFrom(ListenableFuture.class);
}
});
return Maps.uniqueIndex(methodsToProcess, HashSignatureExceptReturnVal.INSTANCE).keySet();
}).transform(new Function<Invokable<?, ?>, InterfaceNameAndParameters>() {
public InterfaceNameAndParameters apply(Invokable<?, ?> in) {
return new InterfaceNameAndParameters(interfaceType, in.getName(), in.getParameters());
}
}).toSet();
}
});
private static enum HashSignatureExceptReturnVal implements Function<Invokable<?, ?>, Integer> {
INSTANCE;
public Integer apply(Invokable<?, ?> in) {
int parametersTypeHashCode = hashParameterTypes(in);
return Objects.hashCode(in.getDeclaringClass(), in.getName(), parametersTypeHashCode);
private static final class InterfaceNameAndParameters {
private final Class<?> interfaceType;
private final String name;
private final int parametersTypeHashCode;
private InterfaceNameAndParameters(Class<?> interfaceType, String name, ImmutableList<Parameter> parameters) {
this.interfaceType = interfaceType;
this.name = name;
int parametersTypeHashCode = 0;
for (Parameter param : parameters)
parametersTypeHashCode += param.getType().hashCode();
this.parametersTypeHashCode = parametersTypeHashCode;
}
public int hashCode() {
return Objects.hashCode(interfaceType, name, parametersTypeHashCode);
}
@Override
public boolean equals(Object o) {
if (this == o)
return true;
if (o == null || getClass() != o.getClass())
return false;
InterfaceNameAndParameters that = InterfaceNameAndParameters.class.cast(o);
return equal(this.interfaceType, that.interfaceType) && equal(this.name, that.name)
&& equal(this.parametersTypeHashCode, that.parametersTypeHashCode);
}
}
private static int hashParameterTypes(Invokable<?, ?> in) {
int parametersTypeHashCode = 0;
for (Parameter param : in.getParameters())
parametersTypeHashCode += param.getType().hashCode();
return parametersTypeHashCode;
}
private AsyncRestClientProxy(Injector injector,
Function<ClassInvokerArgsAndReturnVal, Optional<Object>> optionalConverter, HttpCommandExecutorService http,
ExecutorService userThreads, LoadingCache<ClassInvokerArgs, Object> delegateMap,
RestAnnotationProcessor annotationProcessor, ParseSax.Factory parserFactory, Class<?> declaring) {
@Inject
private AsyncRestClientProxy(Injector injector, Function<InvocationSuccess, Optional<Object>> optionalConverter,
HttpCommandExecutorService http, @Named(Constants.PROPERTY_USER_THREADS) ExecutorService userThreads,
Caller.Factory factory, RestAnnotationProcessor annotationProcessor, ParseSax.Factory parserFactory) {
this.injector = injector;
this.optionalConverter = optionalConverter;
this.http = http;
this.userThreads = userThreads;
this.delegateMap = delegateMap;
this.factory = factory;
this.annotationProcessor = annotationProcessor;
this.parserFactory = parserFactory;
this.declaring = declaring;
}
private static final Predicate<Annotation> isQualifierPresent = new Predicate<Annotation>() {
@Override
public boolean apply(Annotation input) {
return input.annotationType().isAnnotationPresent(Qualifier.class);
}
};
@Override
protected Object handleInvocation(Object proxy, Invokable<?, ?> method, List<Object> args) throws Throwable {
if (method.isAnnotationPresent(Provides.class)) {
return lookupValueFromGuice(method);
} else if (method.isAnnotationPresent(Delegate.class)) {
return propagateContextToDelegate(method, args);
} else if (isAsyncOrDelegate(method)) {
return createListenableFutureForHttpRequestMappedToMethodAndArgs(method, args);
public Result apply(Invocation invocation) {
if (invocation.getInvokable().isAnnotationPresent(Provides.class)) {
return Result.success(lookupValueFromGuice(invocation.getInvokable()));
} else if (invocation.getInvokable().isAnnotationPresent(Delegate.class)) {
return Result.success(propagateContextToDelegate(invocation));
} else if (isAsyncOrDelegate(invocation)) {
return Result.success(createListenableFutureForHttpRequestMappedToMethodAndArgs(invocation));
} else {
throw new RuntimeException(String.format("Method is not annotated as either http or provider method: %s",
method));
return Result.fail(new IllegalStateException(String.format(
"Method is not annotated as either http or provider invoked: %s", invocation.getInvokable())));
}
}
private boolean isAsyncOrDelegate(Invokable<?, ?> method) {
return delegationMapCache.getUnchecked(declaring).contains(HashSignatureExceptReturnVal.INSTANCE.apply(method));
private boolean isAsyncOrDelegate(Invocation invocation) {
return delegationMapCache.getUnchecked(invocation.getInterfaceType()).contains(
new InterfaceNameAndParameters(invocation.getInterfaceType(), invocation.getInvokable().getName(),
invocation.getInvokable().getParameters()));
}
private Object propagateContextToDelegate(Invokable<?, ?> method, List<Object> args) throws ExecutionException {
Class<?> asyncClass = returnTypeOrTypeOfOptional(method);
ClassInvokerArgs cma = ClassInvokerArgs.builder().clazz(asyncClass).invoker(method).args(args).build();
Object returnVal = delegateMap.get(cma);
if (isReturnTypeOptional(method)) {
ClassInvokerArgsAndReturnVal cmar = ClassInvokerArgsAndReturnVal.builder().fromClassInvokerArgs(cma)
.returnVal(returnVal).build();
return optionalConverter.apply(cmar);
private Object propagateContextToDelegate(Invocation invocation) {
Class<?> returnType = unwrapIfOptional(invocation.getInvokable().getReturnType());
Object result = FunctionalReflection.newProxy(returnType, factory.caller(invocation, returnType));
if (isReturnTypeOptional(invocation.getInvokable())) {
return optionalConverter.apply(InvocationSuccess.create(invocation, result));
}
return returnVal;
return result;
}
private Object lookupValueFromGuice(Invokable<?, ?> method) {
private Object lookupValueFromGuice(Invokable<?, ?> invoked) {
try {
Type genericReturnType = method.getReturnType().getType();
Type genericReturnType = invoked.getReturnType().getType();
try {
Annotation qualifier = find(ImmutableList.copyOf(method.getAnnotations()), isQualifierPresent);
Annotation qualifier = find(ImmutableList.copyOf(invoked.getAnnotations()), isQualifierPresent);
return getInstanceOfTypeWithQualifier(genericReturnType, qualifier);
} catch (ProvisionException e) {
throw propagate(e.getCause());
@ -336,19 +333,20 @@ public abstract class AsyncRestClientProxy extends AbstractInvocationHandler {
@SuppressWarnings("unchecked")
@VisibleForTesting
static Function<HttpResponse, ?> createResponseParser(ParseSax.Factory parserFactory, Injector injector,
Invokable<?, ?> method, HttpRequest request) {
Invocation invocation, HttpRequest request) {
Function<HttpResponse, ?> transformer;
Class<? extends HandlerWithResult<?>> handler = getSaxResponseParserClassOrNull(method);
Class<? extends HandlerWithResult<?>> handler = getSaxResponseParserClassOrNull(invocation.getInvokable());
if (handler != null) {
transformer = parserFactory.create(injector.getInstance(handler));
} else {
transformer = getTransformerForMethod(method, injector);
transformer = getTransformerForMethod(invocation, injector);
}
if (transformer instanceof InvocationContext<?>) {
((InvocationContext<?>) transformer).setContext(request);
}
if (method.isAnnotationPresent(Transform.class)) {
Function<?, ?> wrappingTransformer = injector.getInstance(method.getAnnotation(Transform.class).value());
if (invocation.getInvokable().isAnnotationPresent(Transform.class)) {
Function<?, ?> wrappingTransformer = injector.getInstance(invocation.getInvokable()
.getAnnotation(Transform.class).value());
if (wrappingTransformer instanceof InvocationContext<?>) {
((InvocationContext<?>) wrappingTransformer).setContext(request);
}
@ -357,8 +355,8 @@ public abstract class AsyncRestClientProxy extends AbstractInvocationHandler {
return transformer;
}
private static Class<? extends HandlerWithResult<?>> getSaxResponseParserClassOrNull(Invokable<?, ?> method) {
XMLResponseParser annotation = method.getAnnotation(XMLResponseParser.class);
private static Class<? extends HandlerWithResult<?>> getSaxResponseParserClassOrNull(Invokable<?, ?> invoked) {
XMLResponseParser annotation = invoked.getAnnotation(XMLResponseParser.class);
if (annotation != null) {
return annotation.value();
}
@ -368,40 +366,40 @@ public abstract class AsyncRestClientProxy extends AbstractInvocationHandler {
// TODO: refactor this out of here
@VisibleForTesting
@SuppressWarnings({ "rawtypes", "unchecked" })
public static Function<HttpResponse, ?> getTransformerForMethod(Invokable<?, ?> method, Injector injector) {
public static Function<HttpResponse, ?> getTransformerForMethod(Invocation invocation, Injector injector) {
Invokable<?, ?> invoked = invocation.getInvokable();
Function<HttpResponse, ?> transformer;
if (method.isAnnotationPresent(SelectJson.class)) {
Type returnVal = getReturnTypeFor(method.getReturnType());
if (method.isAnnotationPresent(OnlyElement.class))
if (invoked.isAnnotationPresent(SelectJson.class)) {
Type returnVal = getReturnTypeFor(invoked.getReturnType());
if (invoked.isAnnotationPresent(OnlyElement.class))
returnVal = newParameterizedType(Set.class, returnVal);
transformer = new ParseFirstJsonValueNamed(injector.getInstance(GsonWrapper.class),
TypeLiteral.get(returnVal), method.getAnnotation(SelectJson.class).value());
if (method.isAnnotationPresent(OnlyElement.class))
TypeLiteral.get(returnVal), invoked.getAnnotation(SelectJson.class).value());
if (invoked.isAnnotationPresent(OnlyElement.class))
transformer = compose(new OnlyElementOrNull(), transformer);
} else {
transformer = injector.getInstance(getParserOrThrowException(method));
transformer = injector.getInstance(getParserOrThrowException(invocation));
}
return transformer;
}
private ListenableFuture<?> createListenableFutureForHttpRequestMappedToMethodAndArgs(Invokable<?, ?> invoker,
List<Object> args) {
String name = invoker.getDeclaringClass().getSimpleName() + "." + invoker.getName();
private ListenableFuture<?> createListenableFutureForHttpRequestMappedToMethodAndArgs(Invocation invocation) {
String name = invocation.getInterfaceType().getSimpleName() + "." + invocation.getInvokable().getName();
logger.trace(">> converting %s", name);
FutureFallback<?> fallback = fallbacks.getUnchecked(invoker);
FutureFallback<?> fallback = fallbacks.getUnchecked(invocation.getInvokable());
// in case there is an exception creating the request, we should at least pass in args
if (fallback instanceof InvocationContext) {
InvocationContext.class.cast(fallback).setContext((HttpRequest) null);
}
ListenableFuture<?> result;
try {
GeneratedHttpRequest request = annotationProcessor.createRequest(invoker, args);
GeneratedHttpRequest request = annotationProcessor.apply(invocation);
if (fallback instanceof InvocationContext) {
InvocationContext.class.cast(fallback).setContext(request);
}
logger.trace("<< converted %s to %s", name, request.getRequestLine());
Function<HttpResponse, ?> transformer = createResponseParser(parserFactory, injector, invoker, request);
Function<HttpResponse, ?> transformer = createResponseParser(parserFactory, injector, invocation, request);
logger.trace("<< response from %s is parsed by %s", name, transformer.getClass().getSimpleName());
logger.debug(">> invoking %s", name);
@ -422,7 +420,7 @@ public abstract class AsyncRestClientProxy extends AbstractInvocationHandler {
@Override
public String toString() {
return "Client Proxy for :" + declaring.getName();
return String.format("async->http");
}
private final LoadingCache<Invokable<?, ?>, FutureFallback<?>> fallbacks = CacheBuilder.newBuilder().build(
@ -460,57 +458,57 @@ public abstract class AsyncRestClientProxy extends AbstractInvocationHandler {
@SuppressWarnings("unchecked")
@VisibleForTesting
static Key<? extends Function<HttpResponse, ?>> getParserOrThrowException(Invokable<?, ?> method) {
ResponseParser annotation = method.getAnnotation(ResponseParser.class);
static Key<? extends Function<HttpResponse, ?>> getParserOrThrowException(Invocation invocation) {
Invokable<?, ?> invoked = invocation.getInvokable();
ResponseParser annotation = invoked.getAnnotation(ResponseParser.class);
if (annotation == null) {
if (method.getReturnType().equals(void.class) || method.getReturnType().equals(futureVoidLiteral)) {
if (invoked.getReturnType().equals(void.class) || invoked.getReturnType().equals(futureVoidLiteral)) {
return Key.get(ReleasePayloadAndReturn.class);
} else if (method.getReturnType().equals(boolean.class) || method.getReturnType().equals(Boolean.class)
|| method.getReturnType().equals(futureBooleanLiteral)) {
} else if (invoked.getReturnType().equals(boolean.class) || invoked.getReturnType().equals(Boolean.class)
|| invoked.getReturnType().equals(futureBooleanLiteral)) {
return Key.get(ReturnTrueIf2xx.class);
} else if (method.getReturnType().equals(InputStream.class)
|| method.getReturnType().equals(futureInputStreamLiteral)) {
} else if (invoked.getReturnType().equals(InputStream.class)
|| invoked.getReturnType().equals(futureInputStreamLiteral)) {
return Key.get(ReturnInputStream.class);
} else if (method.getReturnType().equals(HttpResponse.class)
|| method.getReturnType().equals(futureHttpResponseLiteral)) {
} else if (invoked.getReturnType().equals(HttpResponse.class)
|| invoked.getReturnType().equals(futureHttpResponseLiteral)) {
return Key.get(Class.class.cast(IdentityFunction.class));
} else if (RestAnnotationProcessor.getAcceptHeaders(method).contains(APPLICATION_JSON)) {
return getJsonParserKeyForMethod(method);
} else if (RestAnnotationProcessor.getAcceptHeaders(method).contains(APPLICATION_XML)
|| method.isAnnotationPresent(JAXBResponseParser.class)) {
return getJAXBParserKeyForMethod(method);
} else if (method.getReturnType().equals(String.class) || method.getReturnType().equals(futureStringLiteral)) {
} else if (RestAnnotationProcessor.getAcceptHeaders(invocation).contains(APPLICATION_JSON)) {
return getJsonParserKeyForMethod(invoked);
} else if (RestAnnotationProcessor.getAcceptHeaders(invocation).contains(APPLICATION_XML)
|| invoked.isAnnotationPresent(JAXBResponseParser.class)) {
return getJAXBParserKeyForMethod(invoked);
} else if (invoked.getReturnType().equals(String.class) || invoked.getReturnType().equals(futureStringLiteral)) {
return Key.get(ReturnStringIf2xx.class);
} else if (method.getReturnType().equals(URI.class) || method.getReturnType().equals(futureURILiteral)) {
} else if (invoked.getReturnType().equals(URI.class) || invoked.getReturnType().equals(futureURILiteral)) {
return Key.get(ParseURIFromListOrLocationHeaderIf20x.class);
} else {
throw new IllegalStateException("You must specify a ResponseParser annotation on: " + method.toString());
throw new IllegalStateException("You must specify a ResponseParser annotation on: " + invoked.toString());
}
}
return Key.get(annotation.value());
}
@SuppressWarnings("unchecked")
private static Key<? extends Function<HttpResponse, ?>> getJAXBParserKeyForMethod(Invokable<?, ?> method) {
private static Key<? extends Function<HttpResponse, ?>> getJAXBParserKeyForMethod(Invokable<?, ?> invoked) {
Optional<Type> configuredReturnVal = Optional.absent();
if (method.isAnnotationPresent(JAXBResponseParser.class)) {
Type configuredClass = method.getAnnotation(JAXBResponseParser.class).value();
if (invoked.isAnnotationPresent(JAXBResponseParser.class)) {
Type configuredClass = invoked.getAnnotation(JAXBResponseParser.class).value();
configuredReturnVal = configuredClass.equals(NullType.class) ? Optional.<Type> absent() : Optional
.<Type> of(configuredClass);
}
Type returnVal = configuredReturnVal.or(getReturnTypeFor(method.getReturnType()));
Type returnVal = configuredReturnVal.or(getReturnTypeFor(invoked.getReturnType()));
Type parserType = newParameterizedType(ParseXMLWithJAXB.class, returnVal);
return (Key<? extends Function<HttpResponse, ?>>) Key.get(parserType);
}
@SuppressWarnings({ "unchecked" })
private static Key<? extends Function<HttpResponse, ?>> getJsonParserKeyForMethod(Invokable<?, ?> method) {
private static Key<? extends Function<HttpResponse, ?>> getJsonParserKeyForMethod(Invokable<?, ?> invoked) {
ParameterizedType parserType;
if (method.isAnnotationPresent(Unwrap.class)) {
parserType = newParameterizedType(UnwrapOnlyJsonValue.class, getReturnTypeFor(method.getReturnType()));
if (invoked.isAnnotationPresent(Unwrap.class)) {
parserType = newParameterizedType(UnwrapOnlyJsonValue.class, getReturnTypeFor(invoked.getReturnType()));
} else {
parserType = newParameterizedType(ParseJson.class, getReturnTypeFor(method.getReturnType()));
parserType = newParameterizedType(ParseJson.class, getReturnTypeFor(invoked.getReturnType()));
}
return (Key<? extends Function<HttpResponse, ?>>) Key.get(parserType);
}
@ -527,4 +525,5 @@ public abstract class AsyncRestClientProxy extends AbstractInvocationHandler {
}
return returnVal;
}
}

View File

@ -1,41 +0,0 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds 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.reflect.Reflection.newProxy;
import org.jclouds.internal.ClassInvokerArgs;
import org.jclouds.rest.internal.AsyncRestClientProxy.Factory;
import com.google.common.cache.CacheLoader;
import com.google.inject.Inject;
public final class CreateAsyncClientForCaller extends CacheLoader<ClassInvokerArgs, Object> {
private final Factory factory;
@Inject
private CreateAsyncClientForCaller(AsyncRestClientProxy.Factory factory) {
this.factory = factory;
}
@Override
public Object load(ClassInvokerArgs from) {
return newProxy(from.getClazz(), factory.caller(from));
}
}

View File

@ -1,64 +0,0 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds 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.checkState;
import static com.google.common.reflect.Reflection.newProxy;
import java.util.Map;
import javax.inject.Inject;
import javax.inject.Named;
import org.jclouds.concurrent.internal.SyncProxy;
import org.jclouds.internal.ClassInvokerArgs;
import org.jclouds.util.Optionals2;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
/**
* CreateClientForCaller is parameterized, so clients it creates aren't singletons. For example, CreateClientForCaller
* satisfies a call like this: {@code context.getProviderSpecificContext().getApi().getOrgClientForName(name)}
*
* @author Adrian Cole
*/
public class CreateClientForCaller extends CacheLoader<ClassInvokerArgs, Object> {
private final SyncProxy.Factory factory;
private final LoadingCache<ClassInvokerArgs, Object> asyncMap;
private final Map<Class<?>, Class<?>> sync2Async;
@Inject
private CreateClientForCaller(SyncProxy.Factory factory,
@Named("async") LoadingCache<ClassInvokerArgs, Object> asyncMap, Map<Class<?>, Class<?>> sync2Async) {
this.factory = factory;
this.asyncMap = asyncMap;
this.sync2Async = sync2Async;
}
@Override
public Object load(ClassInvokerArgs from) {
Class<?> syncClass = Optionals2.returnTypeOrTypeOfOptional(from.getInvoker());
Class<?> asyncClass = sync2Async.get(syncClass);
checkState(asyncClass != null, "configuration error, sync class " + syncClass + " not mapped to an async class");
Object asyncClient = asyncMap.getUnchecked(from);
checkState(asyncClient != null, "configuration error, sync client for " + from + " not found");
return newProxy(syncClass, factory.create(syncClass, asyncClient));
}
}

View File

@ -21,28 +21,22 @@ package org.jclouds.rest.internal;
import static com.google.common.base.Preconditions.checkNotNull;
import java.net.URI;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpRequestFilter;
import org.jclouds.internal.ClassInvokerArgs;
import org.jclouds.io.Payload;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.reflect.Invocation;
import com.google.common.base.Optional;
import com.google.common.collect.Lists;
import com.google.common.collect.Multimap;
import com.google.common.reflect.Invokable;
/**
* Represents a request generated from annotations
*
* @author Adrian Cole
*/
// TODO: get rid of all the mock tests so that this can be made final
public class GeneratedHttpRequest extends HttpRequest {
public final class GeneratedHttpRequest extends HttpRequest {
public static Builder builder() {
return new Builder();
}
@ -51,70 +45,34 @@ public class GeneratedHttpRequest extends HttpRequest {
return new Builder().fromGeneratedHttpRequest(this);
}
public static class Builder extends HttpRequest.Builder<Builder> {
protected Class<?> declaring;
protected Invokable<?, ?> invoker;
// args can be null, so cannot use immutable list
protected List<Object> args = Lists.newArrayList();
protected Optional<ClassInvokerArgs> caller = Optional.absent();
/**
* @see GeneratedHttpRequest#getDeclaring()
*/
public Builder declaring(Class<?> declaring) {
this.declaring = checkNotNull(declaring, "declaring");
return this;
}
public final static class Builder extends HttpRequest.Builder<Builder> {
protected Invocation invocation;
protected Optional<Invocation> caller = Optional.absent();
/**
* @see GeneratedHttpRequest#getInvoker()
* @see GeneratedHttpRequest#getInvocation()
*/
public Builder invoker(Invokable<?, ?> invoker) {
this.invoker = checkNotNull(invoker, "invoker");
public Builder invocation(Invocation invocation) {
this.invocation = checkNotNull(invocation, "invocation");
return this;
}
/**
* @see GeneratedHttpRequest#getArgs()
*/
public Builder args(Iterable<Object> args) {
this.args = Lists.newArrayList(checkNotNull(args, "args"));
return this;
}
/**
* @see GeneratedHttpRequest#getArgs()
*/
public Builder args(@Nullable Object[] args) {
return args(Arrays.asList(args != null ? args : new Object[] {}));
}
/**
* @see GeneratedHttpRequest#getArgs()
*/
public Builder arg(@Nullable Object arg) {
this.args.add(arg);
return this;
}
/**
* @see GeneratedHttpRequest#getCaller()
*/
public Builder caller(@Nullable ClassInvokerArgs caller) {
public Builder caller(@Nullable Invocation caller) {
this.caller = Optional.fromNullable(caller);
return this;
}
public GeneratedHttpRequest build() {
return new GeneratedHttpRequest(method, endpoint, headers.build(), payload, declaring, invoker, args,
filters.build(), caller);
return new GeneratedHttpRequest(method, endpoint, headers.build(), payload, invocation, filters.build(),
caller);
}
public Builder fromGeneratedHttpRequest(GeneratedHttpRequest in) {
return super.fromHttpRequest(in)
.declaring(in.getDeclaring())
.invoker(in.invoker)
.args(in.getArgs())
.invocation(in.invocation)
.caller(in.getCaller().orNull());
}
@ -124,35 +82,25 @@ public class GeneratedHttpRequest extends HttpRequest {
}
}
private final Class<?> declaring;
private final Invokable<?, ?> invoker;
private final List<Object> args;
private final Optional<ClassInvokerArgs> caller;
private final Invocation invocation;
private final Optional<Invocation> caller;
protected GeneratedHttpRequest(String method, URI endpoint, Multimap<String, String> headers,
@Nullable Payload payload, Class<?> declaring, Invokable<?, ?> invoker,
List<Object> args, Iterable<HttpRequestFilter> filters, Optional<ClassInvokerArgs> caller) {
@Nullable Payload payload, Invocation invocation, Iterable<HttpRequestFilter> filters,
Optional<Invocation> caller) {
super(method, endpoint, headers, payload, filters);
this.declaring = checkNotNull(declaring, "declaring");
this.invoker = checkNotNull(invoker, "invoker");
// TODO make immutable. ImmutableList.of() doesn't accept nulls
this.args = Collections.unmodifiableList(checkNotNull(args, "args"));
this.invocation = checkNotNull(invocation, "invocation");
this.caller = checkNotNull(caller, "caller");
}
public Class<?> getDeclaring() {
return declaring;
/**
* what was interpreted to create this request
*/
public Invocation getInvocation() {
return invocation;
}
public Invokable<?,?> getInvoker() {
return invoker;
}
public List<Object> getArgs() {
return args;
}
public Optional<ClassInvokerArgs> getCaller() {
public Optional<Invocation> getCaller() {
return caller;
}
}

View File

@ -17,6 +17,7 @@
* under the License.
*/
package org.jclouds.rest.internal;
import static com.google.common.base.Functions.toStringFunction;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
@ -67,7 +68,6 @@ import org.jclouds.http.HttpRequestFilter;
import org.jclouds.http.HttpUtils;
import org.jclouds.http.Uris.UriBuilder;
import org.jclouds.http.options.HttpRequestOptions;
import org.jclouds.internal.ClassInvokerArgs;
import org.jclouds.io.ContentMetadataCodec;
import org.jclouds.io.Payload;
import org.jclouds.io.PayloadEnclosing;
@ -77,6 +77,7 @@ import org.jclouds.io.payloads.Part;
import org.jclouds.io.payloads.Part.PartOptions;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.logging.Logger;
import org.jclouds.reflect.Invocation;
import org.jclouds.rest.Binder;
import org.jclouds.rest.InputParamValidator;
import org.jclouds.rest.annotations.ApiVersion;
@ -127,34 +128,25 @@ import com.google.inject.TypeLiteral;
import com.google.inject.assistedinject.Assisted;
/**
* Creates http methods based on annotations on a class or interface.
*
* Creates http invocation.getInvoked()s based on annotations on a class or interface.
*
* @author Adrian Cole
*/
public abstract class RestAnnotationProcessor {
public static interface Factory {
Declaring declaring(Class<?> declaring);
Caller caller(ClassInvokerArgs caller);
}
public static final class Declaring extends RestAnnotationProcessor {
@Inject
private Declaring(Injector injector, @ApiVersion String apiVersion, @BuildVersion String buildVersion,
HttpUtils utils, ContentMetadataCodec contentMetadataCodec, InputParamValidator inputParamValidator,
@Assisted Class<?> declaring) {
super(injector, apiVersion, buildVersion, utils, contentMetadataCodec, inputParamValidator, declaring);
}
}
public class RestAnnotationProcessor implements Function<Invocation, GeneratedHttpRequest> {
public static final class Caller extends RestAnnotationProcessor {
private final ClassInvokerArgs caller;
public static interface Factory {
Caller caller(Invocation caller);
}
private final Invocation caller;
@Inject
private Caller(Injector injector, @ApiVersion String apiVersion, @BuildVersion String buildVersion,
HttpUtils utils, ContentMetadataCodec contentMetadataCodec, InputParamValidator inputParamValidator,
@Assisted ClassInvokerArgs caller) {
super(injector, apiVersion, buildVersion, utils, contentMetadataCodec, inputParamValidator, caller.getClazz());
@Assisted Invocation caller) {
super(injector, apiVersion, buildVersion, utils, contentMetadataCodec, inputParamValidator);
this.caller = caller;
}
@ -164,29 +156,22 @@ public abstract class RestAnnotationProcessor {
}
@Override
protected Optional<URI> findEndpoint(Invokable<?,?> method, List<Object> args) {
Optional<URI> endpoint = getEndpointFor(caller.getInvoker(), caller.getArgs());
protected Optional<URI> findEndpoint(Invocation invocation) {
Optional<URI> endpoint = getEndpointFor(caller);
if (endpoint.isPresent())
logger.trace("using endpoint %s from caller %s for %s", endpoint, caller, cma(method, args));
logger.trace("using endpoint %s from caller %s for %s", endpoint, caller, invocation);
else
endpoint = super.findEndpoint(method, args);
endpoint = super.findEndpoint(invocation);
return endpoint;
}
@Override
protected Multimap<String, Object> addPathAndGetTokens(Class<?> clazz, Invokable<?,?> method, List<Object> args,
UriBuilder uriBuilder) {
Class<?> callerClass = caller.getInvoker().getDeclaringClass();
return ImmutableMultimap.<String, Object> builder()
.putAll(super.addPathAndGetTokens(callerClass, caller.getInvoker(), caller.getArgs(), uriBuilder))
.putAll(super.addPathAndGetTokens(clazz, method, args, uriBuilder)).build();
protected Multimap<String, Object> addPathAndGetTokens(Invocation invocation, UriBuilder uriBuilder) {
return ImmutableMultimap.<String, Object> builder().putAll(super.addPathAndGetTokens(caller, uriBuilder))
.putAll(super.addPathAndGetTokens(invocation, uriBuilder)).build();
}
}
protected ClassInvokerArgs cma(Invokable<?,?> method, List<Object> args) {
return logger.isTraceEnabled() ? new ClassInvokerArgs(method.getDeclaringClass(), method, args) : null;
}
@Resource
protected Logger logger = Logger.NULL;
@ -197,75 +182,79 @@ public abstract class RestAnnotationProcessor {
}
};
private final Class<?> declaring;
private final Injector injector;
private final HttpUtils utils;
private final ContentMetadataCodec contentMetadataCodec;
private final String apiVersion;
private final String buildVersion;
private final InputParamValidator inputParamValidator;
private RestAnnotationProcessor(Injector injector, String apiVersion, String buildVersion,
HttpUtils utils, ContentMetadataCodec contentMetadataCodec,
InputParamValidator inputParamValidator, Class<?> declaring) {
@Inject
private RestAnnotationProcessor(Injector injector, @ApiVersion String apiVersion, @BuildVersion String buildVersion,
HttpUtils utils, ContentMetadataCodec contentMetadataCodec, InputParamValidator inputParamValidator) {
this.injector = injector;
this.utils = utils;
this.contentMetadataCodec = contentMetadataCodec;
this.apiVersion = apiVersion;
this.buildVersion = buildVersion;
this.inputParamValidator = inputParamValidator;
this.declaring = declaring;
}
public GeneratedHttpRequest createRequest(Invokable<?, ?> invoker, List<Object> args) {
checkNotNull(invoker, "invoker");
checkNotNull(args, "args");
inputParamValidator.validateMethodParametersOrThrow(invoker, args);
/**
* Note this is dangerous as it cannot pass the inheriting class! Using this when subclassing interfaces may result
* in lost data.
*/
@Deprecated
public GeneratedHttpRequest createRequest(Invokable<?, ?> invokable, List<Object> args) {
return apply(Invocation.create(invokable, args));
}
@Override
public GeneratedHttpRequest apply(Invocation invocation) {
checkNotNull(invocation, "invocation");
inputParamValidator.validateMethodParametersOrThrow(invocation);
Optional<URI> endpoint = Optional.absent();
HttpRequest r = findOrNull(args, HttpRequest.class);
HttpRequest r = findOrNull(invocation.getArgs(), HttpRequest.class);
if (r != null) {
endpoint = Optional.fromNullable(r.getEndpoint());
if (endpoint.isPresent())
logger.trace("using endpoint %s from args for %s", endpoint, cma(invoker, args));
logger.trace("using endpoint %s from invocation.getArgs() for %s", endpoint, invocation);
} else {
endpoint = findEndpoint(invoker, args);
endpoint = findEndpoint(invocation);
}
if (!endpoint.isPresent())
throw new NoSuchElementException(format("no endpoint found for %s", cma(invoker, args)));
throw new NoSuchElementException(format("no endpoint found for %s", invocation));
GeneratedHttpRequest.Builder requestBuilder = requestBuilder();
if (r != null) {
requestBuilder.fromHttpRequest(r);
} else {
requestBuilder.method(tryFindHttpMethod(invoker).get());
requestBuilder.method(tryFindHttpMethod(invocation.getInvokable()).get());
}
requestBuilder.declaring(declaring)
.invoker(invoker)
.args(args)
.filters(getFiltersIfAnnotated(invoker));
requestBuilder.invocation(invocation).filters(getFiltersIfAnnotated(invocation));
Multimap<String, Object> tokenValues = LinkedHashMultimap.create();
tokenValues.put(Constants.PROPERTY_API_VERSION, apiVersion);
tokenValues.put(Constants.PROPERTY_BUILD_VERSION, buildVersion);
UriBuilder uriBuilder = uriBuilder(endpoint.get().toString()); // URI template in rfc6570 form
overridePathEncoding(uriBuilder, invoker);
tokenValues.putAll(addPathAndGetTokens(declaring, invoker, args, uriBuilder));
Multimap<String, Object> formParams = addFormParams(tokenValues, invoker, args);
Multimap<String, Object> queryParams = addQueryParams(tokenValues, invoker, args);
Multimap<String, String> headers = buildHeaders(tokenValues, invoker, args);
overridePathEncoding(uriBuilder, invocation);
tokenValues.putAll(addPathAndGetTokens(invocation, uriBuilder));
Multimap<String, Object> formParams = addFormParams(tokenValues, invocation);
Multimap<String, Object> queryParams = addQueryParams(tokenValues, invocation);
Multimap<String, String> headers = buildHeaders(tokenValues, invocation);
if (r != null)
headers.putAll(r.getHeaders());
if (shouldAddHostHeader(invoker)) {
if (shouldAddHostHeader(invocation)) {
StringBuilder hostHeader = new StringBuilder(endpoint.get().getHost());
if (endpoint.get().getPort() != -1)
hostHeader.append(":").append(endpoint.get().getPort());
@ -273,7 +262,7 @@ public abstract class RestAnnotationProcessor {
}
Payload payload = null;
for(HttpRequestOptions options : findOptionsIn(invoker, args)) {
for (HttpRequestOptions options : findOptionsIn(invocation)) {
injector.injectMembers(options);// TODO test case
for (Entry<String, String> header : options.buildRequestHeaders().entries()) {
headers.put(header.getKey(), replaceTokens(header.getValue(), tokenValues));
@ -293,7 +282,7 @@ public abstract class RestAnnotationProcessor {
if (stringPayload != null)
payload = Payloads.newStringPayload(stringPayload);
}
if (queryParams.size() > 0) {
uriBuilder.query(queryParams);
}
@ -301,16 +290,16 @@ public abstract class RestAnnotationProcessor {
requestBuilder.headers(filterOutContentHeaders(headers));
requestBuilder.endpoint(uriBuilder.build(convertUnsafe(tokenValues)));
if (payload == null) {
PayloadEnclosing payloadEnclosing = findOrNull(args, PayloadEnclosing.class);
payload = (payloadEnclosing != null) ? payloadEnclosing.getPayload() : findOrNull(args, Payload.class);
PayloadEnclosing payloadEnclosing = findOrNull(invocation.getArgs(), PayloadEnclosing.class);
payload = (payloadEnclosing != null) ? payloadEnclosing.getPayload() : findOrNull(invocation.getArgs(),
Payload.class);
}
List<? extends Part> parts = getParts(invoker, args, ImmutableMultimap.<String, Object> builder()
.putAll(tokenValues)
.putAll(formParams).build());
List<? extends Part> parts = getParts(invocation, ImmutableMultimap.<String, Object> builder()
.putAll(tokenValues).putAll(formParams).build());
if (parts.size() > 0) {
if (formParams.size() > 0) {
parts = newLinkedList(concat(transform(formParams.entries(), ENTRY_TO_PART), parts));
@ -328,11 +317,11 @@ public abstract class RestAnnotationProcessor {
}
GeneratedHttpRequest request = requestBuilder.build();
org.jclouds.rest.MapBinder mapBinder = getMapPayloadBinderOrNull(invoker, args);
org.jclouds.rest.MapBinder mapBinder = getMapPayloadBinderOrNull(invocation);
if (mapBinder != null) {
Map<String, Object> mapParams = buildPayloadParams(invoker, args);
if (invoker.isAnnotationPresent(PayloadParams.class)) {
PayloadParams params = invoker.getAnnotation(PayloadParams.class);
Map<String, Object> mapParams = buildPayloadParams(invocation);
if (invocation.getInvokable().isAnnotationPresent(PayloadParams.class)) {
PayloadParams params = invocation.getInvokable().getAnnotation(PayloadParams.class);
addMapPayload(mapParams, params, headers);
}
request = mapBinder.bindToRequest(request, mapParams);
@ -347,10 +336,10 @@ public abstract class RestAnnotationProcessor {
return request;
}
private <T> T findOrNull(Iterable<Object> args, Class<T> clazz) {
private static <T> T findOrNull(Iterable<Object> args, Class<T> clazz) {
return clazz.cast(tryFind(args, instanceOf(clazz)).orNull());
}
private static <K, V> Map<K, V> convertUnsafe(Multimap<K, V> in) {
LinkedHashMap<K, V> out = Maps.newLinkedHashMap();
for (Entry<K, V> entry : in.entries()) {
@ -358,17 +347,18 @@ public abstract class RestAnnotationProcessor {
}
return ImmutableMap.copyOf(out);
}
protected org.jclouds.rest.internal.GeneratedHttpRequest.Builder requestBuilder() {
return GeneratedHttpRequest.builder();
}
private void overridePathEncoding(UriBuilder uriBuilder, Invokable<?, ?> method) {
if (declaring.isAnnotationPresent(SkipEncoding.class)) {
uriBuilder.skipPathEncoding(Chars.asList(declaring.getAnnotation(SkipEncoding.class).value()));
private void overridePathEncoding(UriBuilder uriBuilder, Invocation invocation) {
if (invocation.getInterfaceType().isAnnotationPresent(SkipEncoding.class)) {
uriBuilder.skipPathEncoding(Chars.asList(invocation.getInterfaceType().getAnnotation(SkipEncoding.class)
.value()));
}
if (method.isAnnotationPresent(SkipEncoding.class)) {
uriBuilder.skipPathEncoding(Chars.asList(method.getAnnotation(SkipEncoding.class).value()));
if (invocation.getInvokable().isAnnotationPresent(SkipEncoding.class)) {
uriBuilder.skipPathEncoding(Chars.asList(invocation.getInvokable().getAnnotation(SkipEncoding.class).value()));
}
}
@ -382,64 +372,60 @@ public abstract class RestAnnotationProcessor {
return o.toString();
}
}
protected Optional<URI> findEndpoint(Invokable<?,?> method, List<Object> args) {
ClassInvokerArgs cma = cma(method, args);
Optional<URI> endpoint = getEndpointFor(method, args);
protected Optional<URI> findEndpoint(Invocation invocation) {
Optional<URI> endpoint = getEndpointFor(invocation);
if (endpoint.isPresent())
logger.trace("using endpoint %s for %s", endpoint, cma);
logger.trace("using endpoint %s for %s", endpoint, invocation);
if (!endpoint.isPresent()) {
logger.trace("looking up default endpoint for %s", cma);
logger.trace("looking up default endpoint for %s", invocation);
endpoint = Optional.fromNullable(injector.getInstance(
Key.get(uriSupplierLiteral, org.jclouds.location.Provider.class)).get());
if (endpoint.isPresent())
logger.trace("using default endpoint %s for %s", endpoint, cma);
logger.trace("using default endpoint %s for %s", endpoint, invocation);
}
return endpoint;
}
protected Multimap<String, Object> addPathAndGetTokens(Class<?> clazz, Invokable<?, ?> method, List<Object> args,
UriBuilder uriBuilder) {
if (clazz.isAnnotationPresent(Path.class))
uriBuilder.appendPath(clazz.getAnnotation(Path.class).value());
if (method.isAnnotationPresent(Path.class))
uriBuilder.appendPath(method.getAnnotation(Path.class).value());
return getPathParamKeyValues(method, args);
protected Multimap<String, Object> addPathAndGetTokens(Invocation invocation, UriBuilder uriBuilder) {
if (invocation.getInterfaceType().isAnnotationPresent(Path.class))
uriBuilder.appendPath(invocation.getInterfaceType().getAnnotation(Path.class).value());
if (invocation.getInvokable().isAnnotationPresent(Path.class))
uriBuilder.appendPath(invocation.getInvokable().getAnnotation(Path.class).value());
return getPathParamKeyValues(invocation);
}
private Multimap<String, Object> addFormParams(Multimap<String, ?> tokenValues, Invokable<?, ?> method,
List<Object> args) {
private Multimap<String, Object> addFormParams(Multimap<String, ?> tokenValues, Invocation invocation) {
Multimap<String, Object> formMap = LinkedListMultimap.create();
if (declaring.isAnnotationPresent(FormParams.class)) {
FormParams form = declaring.getAnnotation(FormParams.class);
if (invocation.getInterfaceType().isAnnotationPresent(FormParams.class)) {
FormParams form = invocation.getInterfaceType().getAnnotation(FormParams.class);
addForm(formMap, form, tokenValues);
}
if (method.isAnnotationPresent(FormParams.class)) {
FormParams form = method.getAnnotation(FormParams.class);
if (invocation.getInvokable().isAnnotationPresent(FormParams.class)) {
FormParams form = invocation.getInvokable().getAnnotation(FormParams.class);
addForm(formMap, form, tokenValues);
}
for (Entry<String, Object> form : getFormParamKeyValues(method, args).entries()) {
for (Entry<String, Object> form : getFormParamKeyValues(invocation).entries()) {
formMap.put(form.getKey(), replaceTokens(form.getValue().toString(), tokenValues));
}
return formMap;
}
private Multimap<String, Object> addQueryParams(Multimap<String, ?> tokenValues, Invokable<?, ?> method,
List<Object> args) {
private Multimap<String, Object> addQueryParams(Multimap<String, ?> tokenValues, Invocation invocation) {
Multimap<String, Object> queryMap = LinkedListMultimap.create();
if (declaring.isAnnotationPresent(QueryParams.class)) {
QueryParams query = declaring.getAnnotation(QueryParams.class);
if (invocation.getInterfaceType().isAnnotationPresent(QueryParams.class)) {
QueryParams query = invocation.getInterfaceType().getAnnotation(QueryParams.class);
addQuery(queryMap, query, tokenValues);
}
if (method.isAnnotationPresent(QueryParams.class)) {
QueryParams query = method.getAnnotation(QueryParams.class);
if (invocation.getInvokable().isAnnotationPresent(QueryParams.class)) {
QueryParams query = invocation.getInvokable().getAnnotation(QueryParams.class);
addQuery(queryMap, query, tokenValues);
}
for (Entry<String, Object> query : getQueryParamKeyValues(method, args).entries()) {
for (Entry<String, Object> query : getQueryParamKeyValues(invocation).entries()) {
queryMap.put(query.getKey(), replaceTokens(query.getValue().toString(), tokenValues));
}
return queryMap;
@ -478,47 +464,53 @@ public abstract class RestAnnotationProcessor {
}
}
private List<HttpRequestFilter> getFiltersIfAnnotated(Invokable<?,?> method) {
private List<HttpRequestFilter> getFiltersIfAnnotated(Invocation invocation) {
List<HttpRequestFilter> filters = newArrayList();
if (declaring.isAnnotationPresent(RequestFilters.class)) {
for (Class<? extends HttpRequestFilter> clazz : declaring.getAnnotation(RequestFilters.class).value()) {
if (invocation.getInterfaceType().isAnnotationPresent(RequestFilters.class)) {
for (Class<? extends HttpRequestFilter> clazz : invocation.getInterfaceType()
.getAnnotation(RequestFilters.class).value()) {
HttpRequestFilter instance = injector.getInstance(clazz);
filters.add(instance);
logger.trace("adding filter %s from annotation on %s", instance, declaring.getName());
logger.trace("adding filter %s from annotation on %s", instance, invocation.getInterfaceType().getName());
}
}
if (method.isAnnotationPresent(RequestFilters.class)) {
if (method.isAnnotationPresent(OverrideRequestFilters.class))
if (invocation.getInvokable().isAnnotationPresent(RequestFilters.class)) {
if (invocation.getInvokable().isAnnotationPresent(OverrideRequestFilters.class))
filters.clear();
for (Class<? extends HttpRequestFilter> clazz : method.getAnnotation(RequestFilters.class).value()) {
for (Class<? extends HttpRequestFilter> clazz : invocation.getInvokable().getAnnotation(RequestFilters.class)
.value()) {
HttpRequestFilter instance = injector.getInstance(clazz);
filters.add(instance);
logger.trace("adding filter %s from annotation on %s", instance, method.getName());
logger.trace("adding filter %s from annotation on %s", instance, invocation.getInvokable().getName());
}
}
return filters;
}
@VisibleForTesting
static URI getEndpointInParametersOrNull(Invokable<?,?> method, List<Object> args, Injector injector) {
Collection<Parameter> endpointParams = parametersWithAnnotation(method, EndpointParam.class);
static URI getEndpointInParametersOrNull(Invocation invocation, Injector injector) {
Collection<Parameter> endpointParams = parametersWithAnnotation(invocation.getInvokable(), EndpointParam.class);
if (endpointParams.isEmpty())
return null;
checkState(endpointParams.size() == 1, "method %s has too many EndpointParam annotations", method);
checkState(endpointParams.size() == 1, "invocation.getInvoked() %s has too many EndpointParam annotations",
invocation.getInvokable());
Parameter endpointParam = get(endpointParams, 0);
Function<Object, URI> parser = injector.getInstance(endpointParam.getAnnotation(EndpointParam.class).parser());
int position = endpointParam.hashCode();// guava issue 1243
try {
URI returnVal = parser.apply(args.get(position));
checkArgument(returnVal != null, format("endpoint for [%s] not configured for %s", position, method));
URI returnVal = parser.apply(invocation.getArgs().get(position));
checkArgument(returnVal != null,
format("endpoint for [%s] not configured for %s", position, invocation.getInvokable()));
return returnVal;
} catch (NullPointerException e) {
throw new IllegalArgumentException(format("argument at index %d on method %s was null", position, method), e);
throw new IllegalArgumentException(format("argument at index %d on invocation.getInvoked() %s was null",
position, invocation.getInvokable()), e);
}
}
private static Collection<Parameter> parametersWithAnnotation(Invokable<?, ?> method, final Class<? extends Annotation> annotationType) {
return filter(method.getParameters(), new Predicate<Parameter>() {
private static Collection<Parameter> parametersWithAnnotation(Invokable<?, ?> invokable,
final Class<? extends Annotation> annotationType) {
return filter(invokable.getParameters(), new Predicate<Parameter>() {
public boolean apply(Parameter in) {
return in.isAnnotationPresent(annotationType);
}
@ -528,16 +520,16 @@ public abstract class RestAnnotationProcessor {
private static final TypeLiteral<Supplier<URI>> uriSupplierLiteral = new TypeLiteral<Supplier<URI>>() {
};
protected Optional<URI> getEndpointFor(Invokable<?,?> method, List<Object> args) {
URI endpoint = getEndpointInParametersOrNull(method, args, injector);
protected Optional<URI> getEndpointFor(Invocation invocation) {
URI endpoint = getEndpointInParametersOrNull(invocation, injector);
if (endpoint == null) {
Endpoint annotation;
if (method.isAnnotationPresent(Endpoint.class)) {
annotation = method.getAnnotation(Endpoint.class);
} else if (method.getDeclaringClass().isAnnotationPresent(Endpoint.class)) {
annotation = method.getDeclaringClass().getAnnotation(Endpoint.class);
if (invocation.getInvokable().isAnnotationPresent(Endpoint.class)) {
annotation = invocation.getInvokable().getAnnotation(Endpoint.class);
} else if (invocation.getInterfaceType().isAnnotationPresent(Endpoint.class)) {
annotation = invocation.getInterfaceType().getAnnotation(Endpoint.class);
} else {
logger.trace("no annotations on class or method: %s", method);
logger.trace("no annotations on class or invocation.getInvoked(): %s", invocation.getInvokable());
return Optional.absent();
}
endpoint = injector.getInstance(Key.get(uriSupplierLiteral, annotation.value())).get();
@ -557,9 +549,9 @@ public abstract class RestAnnotationProcessor {
return withHost.resolve(original);
}
private org.jclouds.rest.MapBinder getMapPayloadBinderOrNull(Invokable<?,?> method, List<Object> args) {
if (args != null) {
for (Object arg : args) {
private org.jclouds.rest.MapBinder getMapPayloadBinderOrNull(Invocation invocation) {
if (invocation.getArgs() != null) {
for (Object arg : invocation.getArgs()) {
if (arg instanceof Object[]) {
Object[] postBinders = (Object[]) arg;
if (postBinders.length == 0) {
@ -571,8 +563,9 @@ public abstract class RestAnnotationProcessor {
}
} else {
if (postBinders[0] instanceof org.jclouds.rest.MapBinder) {
throw new IllegalArgumentException("we currently do not support multiple varargs postBinders in: "
+ method.getName());
throw new IllegalArgumentException(
"we currently do not support multiple varinvocation.getArgs() postBinders in: "
+ invocation.getInvokable().getName());
}
}
} else if (arg instanceof org.jclouds.rest.MapBinder) {
@ -582,25 +575,28 @@ public abstract class RestAnnotationProcessor {
}
}
}
if (method.isAnnotationPresent(MapBinder.class)) {
return injector.getInstance(method.getAnnotation(MapBinder.class).value());
} else if (method.isAnnotationPresent(org.jclouds.rest.annotations.Payload.class)) {
if (invocation.getInvokable().isAnnotationPresent(MapBinder.class)) {
return injector.getInstance(invocation.getInvokable().getAnnotation(MapBinder.class).value());
} else if (invocation.getInvokable().isAnnotationPresent(org.jclouds.rest.annotations.Payload.class)) {
return injector.getInstance(BindMapToStringPayload.class);
} else if (method.isAnnotationPresent(WrapWith.class)) {
} else if (invocation.getInvokable().isAnnotationPresent(WrapWith.class)) {
return injector.getInstance(BindToJsonPayloadWrappedWith.Factory.class).create(
method.getAnnotation(WrapWith.class).value());
invocation.getInvokable().getAnnotation(WrapWith.class).value());
}
return null;
}
private boolean shouldAddHostHeader(Invokable<?, ?> method) {
return (declaring.isAnnotationPresent(VirtualHost.class) || method.isAnnotationPresent(VirtualHost.class));
private boolean shouldAddHostHeader(Invocation invocation) {
return (invocation.getInterfaceType().isAnnotationPresent(VirtualHost.class) || invocation.getInvokable()
.isAnnotationPresent(VirtualHost.class));
}
private GeneratedHttpRequest decorateRequest(GeneratedHttpRequest request) throws NegativeArraySizeException {
Set<Parameter> binderOrWrapWith = ImmutableSet.copyOf(concat(parametersWithAnnotation(request.getInvoker(), BinderParam.class),
parametersWithAnnotation(request.getInvoker(), WrapWith.class)));
private GeneratedHttpRequest decorateRequest(GeneratedHttpRequest request) throws NegativeArraySizeException {
Invocation invocation = request.getInvocation();
List<Object> args = request.getInvocation().getArgs();
Set<Parameter> binderOrWrapWith = ImmutableSet.copyOf(concat(
parametersWithAnnotation(invocation.getInvokable(), BinderParam.class),
parametersWithAnnotation(invocation.getInvokable(), WrapWith.class)));
OUTER: for (Parameter entry : binderOrWrapWith) {
int position = entry.hashCode();
boolean shouldBreak = false;
@ -610,18 +606,19 @@ public abstract class RestAnnotationProcessor {
else
binder = injector.getInstance(BindToJsonPayloadWrappedWith.Factory.class).create(
entry.getAnnotation(WrapWith.class).value());
Object arg = request.getArgs().size() >= position + 1 ? request.getArgs().get(position) : null;
if (request.getArgs().size() >= position + 1 && arg != null) {
Object arg = args.size() >= position + 1 ? args.get(position) : null;
if (args.size() >= position + 1 && arg != null) {
Class<?> parameterType = entry.getType().getRawType();
Class<? extends Object> argType = arg.getClass();
if (!argType.isArray() && parameterType.isArray()) { // TODO && varargs guava issue 1244
int arrayLength = request.getArgs().size() - request.getInvoker().getParameters().size() + 1;
if (!argType.isArray() && parameterType.isArray()) { // TODO && varinvocation.getArgs() guava issue 1244
int arrayLength = args.size() - invocation.getInvokable().getParameters().size() + 1;
if (arrayLength == 0)
break OUTER;
arg = (Object[]) Array.newInstance(arg.getClass(), arrayLength);
System.arraycopy(request.getArgs().toArray(), position, arg, 0, arrayLength);
System.arraycopy(args.toArray(), position, arg, 0, arrayLength);
shouldBreak = true;
} else if (argType.isArray() && parameterType.isArray()) { // TODO && varargs guava issue 1244
} else if (argType.isArray() && parameterType.isArray()) { // TODO && varinvocation.getArgs() guava issue
// 1244
} else {
if (arg.getClass().isArray()) {
Object[] payloadArray = (Object[]) arg;
@ -634,24 +631,24 @@ public abstract class RestAnnotationProcessor {
if (shouldBreak)
break OUTER;
} else {
if (position + 1 == request.getInvoker().getParameters().size() && entry.getType().isArray())
continue OUTER; // TODO should only skip on null when varargs: guava issue 1244
if (position + 1 == invocation.getInvokable().getParameters().size() && entry.getType().isArray())
continue OUTER; // TODO should only skip on null when varinvocation.getArgs(): guava issue 1244
if (entry.isAnnotationPresent(Nullable.class)) {
continue OUTER;
}
checkNotNull(arg, request.getInvoker().getName() + " parameter " + (position + 1));
checkNotNull(arg, invocation.getInvokable().getName() + " parameter " + (position + 1));
}
}
return request;
}
private static final LoadingCache<Invokable<?, ?>, Set<Integer>> methodToIndexesOfOptions = CacheBuilder.newBuilder().build(
new CacheLoader<Invokable<?, ?>, Set<Integer>>() {
private static final LoadingCache<Invokable<?, ?>, Set<Integer>> invokableToIndexesOfOptions = CacheBuilder
.newBuilder().build(new CacheLoader<Invokable<?, ?>, Set<Integer>>() {
@Override
public Set<Integer> load(Invokable<?, ?> method) {
public Set<Integer> load(Invokable<?, ?> invokable) {
Builder<Integer> toReturn = ImmutableSet.builder();
for (Parameter param : method.getParameters()) {
for (Parameter param : invokable.getParameters()) {
Class<?> type = param.getType().getRawType();
if (HttpRequestOptions.class.isAssignableFrom(type)
|| HttpRequestOptions[].class.isAssignableFrom(type))
@ -660,21 +657,21 @@ public abstract class RestAnnotationProcessor {
return toReturn.build();
}
});
private Set<HttpRequestOptions> findOptionsIn(Invokable<?,?> method, List<Object> args) {
ImmutableSet.Builder<HttpRequestOptions> result = ImmutableSet.builder();
for (int index : methodToIndexesOfOptions.getUnchecked(method)) {
if (args.size() >= index + 1) {// accommodate varargs
if (args.get(index) instanceof Object[]) {
for (Object option : (Object[]) args.get(index)) {
private Set<HttpRequestOptions> findOptionsIn(Invocation invocation) {
ImmutableSet.Builder<HttpRequestOptions> result = ImmutableSet.builder();
for (int index : invokableToIndexesOfOptions.getUnchecked(invocation.getInvokable())) {
if (invocation.getArgs().size() >= index + 1) {// accommodate varinvocation.getArgs()
if (invocation.getArgs().get(index) instanceof Object[]) {
for (Object option : (Object[]) invocation.getArgs().get(index)) {
if (option instanceof HttpRequestOptions) {
result.add((HttpRequestOptions) option);
}
}
} else {
for (; index < args.size(); index++) {
if (args.get(index) instanceof HttpRequestOptions) {
result.add((HttpRequestOptions) args.get(index));
for (; index < invocation.getArgs().size(); index++) {
if (invocation.getArgs().get(index) instanceof HttpRequestOptions) {
result.add((HttpRequestOptions) invocation.getArgs().get(index));
}
}
}
@ -683,58 +680,57 @@ public abstract class RestAnnotationProcessor {
return result.build();
}
private Multimap<String, String> buildHeaders(Multimap<String, ?> tokenValues, Invokable<?, ?> method,
List<Object> args) {
private Multimap<String, String> buildHeaders(Multimap<String, ?> tokenValues, Invocation invocation) {
Multimap<String, String> headers = LinkedHashMultimap.create();
addHeaderIfAnnotationPresentOnMethod(headers, method, tokenValues);
for (Parameter headerParam : parametersWithAnnotation(method, HeaderParam.class)) {
addHeaderIfAnnotationPresentOnMethod(headers, invocation, tokenValues);
for (Parameter headerParam : parametersWithAnnotation(invocation.getInvokable(), HeaderParam.class)) {
Annotation key = headerParam.getAnnotation(HeaderParam.class);
String value = args.get(headerParam.hashCode()).toString(); // TODO position guava issue 1243
String value = invocation.getArgs().get(headerParam.hashCode()).toString(); // TODO position guava issue 1243
value = replaceTokens(value, tokenValues);
headers.put(((HeaderParam) key).value(), value);
}
addProducesIfPresentOnTypeOrMethod(headers, method);
addConsumesIfPresentOnTypeOrMethod(headers, method);
addProducesIfPresentOnTypeOrMethod(headers, invocation);
addConsumesIfPresentOnTypeOrMethod(headers, invocation);
return headers;
}
private void addConsumesIfPresentOnTypeOrMethod(Multimap<String, String> headers, Invokable<?,?> method) {
Set<String> accept = getAcceptHeaders(method);
private static void addConsumesIfPresentOnTypeOrMethod(Multimap<String, String> headers, Invocation invocation) {
Set<String> accept = getAcceptHeaders(invocation);
if (!accept.isEmpty())
headers.replaceValues(ACCEPT, accept);
}
// TODO: refactor this out
static Set<String> getAcceptHeaders(Invokable<?, ?> method) {
Optional<Consumes> accept = Optional.fromNullable(method.getAnnotation(Consumes.class)).or(
Optional.fromNullable(method.getDeclaringClass().getAnnotation(Consumes.class)));
static Set<String> getAcceptHeaders(Invocation invocation) {
Optional<Consumes> accept = Optional.fromNullable(invocation.getInvokable().getAnnotation(Consumes.class)).or(
Optional.fromNullable(invocation.getInterfaceType().getAnnotation(Consumes.class)));
return (accept.isPresent()) ? ImmutableSet.copyOf(accept.get().value()) : ImmutableSet.<String> of();
}
private void addProducesIfPresentOnTypeOrMethod(Multimap<String, String> headers, Invokable<?,?> method) {
if (declaring.isAnnotationPresent(Produces.class)) {
Produces header = declaring.getAnnotation(Produces.class);
private static void addProducesIfPresentOnTypeOrMethod(Multimap<String, String> headers, Invocation invocation) {
if (invocation.getInterfaceType().isAnnotationPresent(Produces.class)) {
Produces header = invocation.getInterfaceType().getAnnotation(Produces.class);
headers.replaceValues(CONTENT_TYPE, asList(header.value()));
}
if (method.isAnnotationPresent(Produces.class)) {
Produces header = method.getAnnotation(Produces.class);
if (invocation.getInvokable().isAnnotationPresent(Produces.class)) {
Produces header = invocation.getInvokable().getAnnotation(Produces.class);
headers.replaceValues(CONTENT_TYPE, asList(header.value()));
}
}
private void addHeaderIfAnnotationPresentOnMethod(Multimap<String, String> headers, Invokable<?,?> method,
private static void addHeaderIfAnnotationPresentOnMethod(Multimap<String, String> headers, Invocation invocation,
Multimap<String, ?> tokenValues) {
if (declaring.isAnnotationPresent(Headers.class)) {
Headers header = declaring.getAnnotation(Headers.class);
if (invocation.getInterfaceType().isAnnotationPresent(Headers.class)) {
Headers header = invocation.getInterfaceType().getAnnotation(Headers.class);
addHeader(headers, header, tokenValues);
}
if (method.isAnnotationPresent(Headers.class)) {
Headers header = method.getAnnotation(Headers.class);
if (invocation.getInvokable().isAnnotationPresent(Headers.class)) {
Headers header = invocation.getInvokable().getAnnotation(Headers.class);
addHeader(headers, header, tokenValues);
}
}
private void addHeader(Multimap<String, String> headers, Headers header, Multimap<String, ?> tokenValues) {
private static void addHeader(Multimap<String, String> headers, Headers header, Multimap<String, ?> tokenValues) {
for (int i = 0; i < header.keys().length; i++) {
String value = header.values()[i];
value = replaceTokens(value, tokenValues);
@ -742,16 +738,16 @@ public abstract class RestAnnotationProcessor {
}
}
private List<Part> getParts(Invokable<?, ?> method, List<Object> args, Multimap<String, ?> tokenValues) {
private static List<Part> getParts(Invocation invocation, Multimap<String, ?> tokenValues) {
ImmutableList.Builder<Part> parts = ImmutableList.<Part> builder();
for (Parameter param : parametersWithAnnotation(method, PartParam.class)) {
for (Parameter param : parametersWithAnnotation(invocation.getInvokable(), PartParam.class)) {
PartParam partParam = param.getAnnotation(PartParam.class);
PartOptions options = new PartOptions();
if (!PartParam.NO_CONTENT_TYPE.equals(partParam.contentType()))
options.contentType(partParam.contentType());
if (!PartParam.NO_FILENAME.equals(partParam.filename()))
options.filename(replaceTokens(partParam.filename(), tokenValues));
Object arg = args.get(param.hashCode()); // TODO position guava issue 1243
Object arg = invocation.getArgs().get(param.hashCode()); // TODO position guava issue 1243
checkNotNull(arg, partParam.name());
Part part = Part.create(partParam.name(), newPayload(arg), options);
parts.add(part);
@ -759,12 +755,12 @@ public abstract class RestAnnotationProcessor {
return parts.build();
}
private Multimap<String, Object> getPathParamKeyValues(Invokable<?, ?> method, List<Object> args) {
private Multimap<String, Object> getPathParamKeyValues(Invocation invocation) {
Multimap<String, Object> pathParamValues = LinkedHashMultimap.create();
for (Parameter param : parametersWithAnnotation(method, PathParam.class)) {
for (Parameter param : parametersWithAnnotation(invocation.getInvokable(), PathParam.class)) {
PathParam pathParam = param.getAnnotation(PathParam.class);
String paramKey = pathParam.value();
Optional<?> paramValue = getParamValue(method, args, param.getAnnotation(ParamParser.class), param.hashCode(),
Optional<?> paramValue = getParamValue(invocation, param.getAnnotation(ParamParser.class), param.hashCode(),
paramKey); // TODO position guava issue 1243
if (paramValue.isPresent())
pathParamValues.put(paramKey, paramValue.get().toString());
@ -772,29 +768,29 @@ public abstract class RestAnnotationProcessor {
return pathParamValues;
}
private Optional<?> getParamValue(Invokable<?,?> method, List<Object> args, @Nullable ParamParser extractor,
int argIndex, String paramKey) {
Object arg = args.get(argIndex);
if (extractor != null && checkPresentOrNullable(method, paramKey, argIndex, arg)) {
private Optional<?> getParamValue(Invocation invocation, @Nullable ParamParser extractor, int argIndex,
String paramKey) {
Object arg = invocation.getArgs().get(argIndex);
if (extractor != null && checkPresentOrNullable(invocation, paramKey, argIndex, arg)) {
arg = injector.getInstance(extractor.value()).apply(arg); // ParamParsers can deal with nullable parameters
}
checkPresentOrNullable(method, paramKey, argIndex, arg);
checkPresentOrNullable(invocation, paramKey, argIndex, arg);
return Optional.fromNullable(arg);
}
private static boolean checkPresentOrNullable(Invokable<?,?> method, String paramKey, int argIndex, Object arg) {
if (arg == null && !method.getParameters().get(argIndex).isAnnotationPresent(Nullable.class))
throw new NullPointerException(format("param{%s} for method %s.%s", paramKey, method
.getDeclaringClass().getSimpleName(), method.getName()));
private static boolean checkPresentOrNullable(Invocation invocation, String paramKey, int argIndex, Object arg) {
if (arg == null && !invocation.getInvokable().getParameters().get(argIndex).isAnnotationPresent(Nullable.class))
throw new NullPointerException(format("param{%s} for invocation %s.%s", paramKey, invocation
.getInterfaceType().getSimpleName(), invocation.getInvokable().getName()));
return true;
}
private Multimap<String, Object> getFormParamKeyValues(Invokable<?,?> method, List<Object> args) {
private Multimap<String, Object> getFormParamKeyValues(Invocation invocation) {
Multimap<String, Object> formParamValues = LinkedHashMultimap.create();
for (Parameter param : parametersWithAnnotation(method, FormParam.class)) {
for (Parameter param : parametersWithAnnotation(invocation.getInvokable(), FormParam.class)) {
FormParam formParam = param.getAnnotation(FormParam.class);
String paramKey = formParam.value();
Optional<?> paramValue = getParamValue(method, args, param.getAnnotation(ParamParser.class), param.hashCode(),
Optional<?> paramValue = getParamValue(invocation, param.getAnnotation(ParamParser.class), param.hashCode(),
paramKey); // TODO position guava issue 1243
if (paramValue.isPresent())
formParamValues.put(paramKey, paramValue.get().toString());
@ -802,15 +798,15 @@ public abstract class RestAnnotationProcessor {
return formParamValues;
}
private Multimap<String, Object> getQueryParamKeyValues(Invokable<?,?> method, List<Object> args) {
private Multimap<String, Object> getQueryParamKeyValues(Invocation invocation) {
Multimap<String, Object> queryParamValues = LinkedHashMultimap.create();
for (Parameter param : parametersWithAnnotation(method, QueryParam.class)) {
for (Parameter param : parametersWithAnnotation(invocation.getInvokable(), QueryParam.class)) {
QueryParam queryParam = param.getAnnotation(QueryParam.class);
String paramKey = queryParam.value();
Optional<?> paramValue = getParamValue(method, args, param.getAnnotation(ParamParser.class), param.hashCode(),
Optional<?> paramValue = getParamValue(invocation, param.getAnnotation(ParamParser.class), param.hashCode(),
paramKey); // TODO position guava issue 1243
if (paramValue.isPresent())
if (paramValue.get() instanceof Iterable) {
if (paramValue.get() instanceof Iterable) {
@SuppressWarnings("unchecked")
Iterable<String> iterableStrings = transform(Iterable.class.cast(paramValue.get()), toStringFunction());
queryParamValues.putAll(paramKey, iterableStrings);
@ -821,12 +817,12 @@ public abstract class RestAnnotationProcessor {
return queryParamValues;
}
private Map<String, Object> buildPayloadParams(Invokable<?,?> method, List<Object> args) {
private Map<String, Object> buildPayloadParams(Invocation invocation) {
Map<String, Object> payloadParamValues = Maps.newLinkedHashMap();
for (Parameter param : parametersWithAnnotation(method, PayloadParam.class)) {
for (Parameter param : parametersWithAnnotation(invocation.getInvokable(), PayloadParam.class)) {
PayloadParam payloadParam = param.getAnnotation(PayloadParam.class);
String paramKey = payloadParam.value();
Optional<?> paramValue = getParamValue(method, args, param.getAnnotation(ParamParser.class), param.hashCode(),
Optional<?> paramValue = getParamValue(invocation, param.getAnnotation(ParamParser.class), param.hashCode(),
paramKey); // TODO position guava issue 1243
if (paramValue.isPresent())
payloadParamValues.put(paramKey, paramValue.get());

View File

@ -31,23 +31,17 @@ import com.google.common.reflect.TypeToken;
* @author Adrian Cole
*/
public class Optionals2 {
public static Class<?> returnTypeOrTypeOfOptional(Invokable<?, ?> method) {
TypeToken<?> type = method.getReturnType();
return returnTypeOrTypeOfOptional(type.getRawType(), type.getType());
}
private static Class<?> returnTypeOrTypeOfOptional(Class<?> syncClass, Type genericType) {
if (syncClass.isAssignableFrom(Optional.class)) {
ParameterizedType futureType = ParameterizedType.class.cast(genericType);
public static Class<?> unwrapIfOptional(TypeToken<?> type) {
if (type.getRawType().isAssignableFrom(Optional.class)) {
ParameterizedType futureType = ParameterizedType.class.cast(type.getType());
// TODO: error checking in case this is a type, not a class.
Type t = futureType.getActualTypeArguments()[0];
if (t instanceof WildcardType) {
t = ((WildcardType) t).getUpperBounds()[0];
}
syncClass = Class.class.cast(t);
} else {
return Class.class.cast(t);
}
return syncClass;
return type.getRawType();
}
public static boolean isReturnTypeOptional(Invokable<?, ?> method) {

View File

@ -33,7 +33,6 @@ import org.jclouds.rest.ResourceNotFoundException;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Predicate;
import com.google.common.base.Throwables;
import com.google.common.reflect.TypeToken;
import com.google.inject.CreationException;
import com.google.inject.ProvisionException;
@ -119,32 +118,6 @@ public class Throwables2 {
return null;
}
// Note this needs to be kept up-to-date with all top-level exceptions jclouds works against
@SuppressWarnings( { "unchecked", "rawtypes" })
public static Exception returnFirstExceptionIfInListOrThrowStandardExceptionOrCause(Iterable<TypeToken<? extends Throwable>> throwables,
Exception exception) throws Exception {
for (TypeToken<? extends Throwable> type : throwables) {
Throwable throwable = getFirstThrowableOfType(exception, (Class<Throwable>) type.getRawType());
if (throwable != null) {
return (Exception) throwable;
}
}
for (Class<Exception> propagatableExceptionType : new Class[] { IllegalStateException.class,
AssertionError.class, UnsupportedOperationException.class, IllegalArgumentException.class,
AuthorizationException.class, ResourceNotFoundException.class, InsufficientResourcesException.class,
HttpResponseException.class }) {
Throwable throwable = getFirstThrowableOfType(exception, propagatableExceptionType);
if (throwable != null) {
if (throwable instanceof AssertionError)
throw (AssertionError) throwable;
else
throw (Exception) throwable;
}
}
Throwables.propagateIfPossible(exception.getCause(), Exception.class);
throw exception;
}
public static <T> T propagateAuthorizationOrOriginalException(Exception e) {
AuthorizationException aex = getFirstThrowableOfType(e, AuthorizationException.class);
if (aex != null)
@ -154,4 +127,24 @@ public class Throwables2 {
return null;
}
// Note this needs to be kept up-to-date with all top-level exceptions jclouds works against
@SuppressWarnings("unchecked")
public static void propagateIfPossible(Throwable exception, Iterable<TypeToken<? extends Throwable>> throwables)
throws Throwable {
for (TypeToken<? extends Throwable> type : throwables) {
Throwable throwable = Throwables2.getFirstThrowableOfType(exception, (Class<Throwable>) type.getRawType());
if (throwable != null) {
throw throwable;
}
}
for (Class<Exception> propagatableExceptionType : new Class[] { IllegalStateException.class,
AssertionError.class, UnsupportedOperationException.class, IllegalArgumentException.class,
AuthorizationException.class, ResourceNotFoundException.class, InsufficientResourcesException.class,
HttpResponseException.class }) {
Throwable throwable = Throwables2.getFirstThrowableOfType(exception, propagatableExceptionType);
if (throwable != null) {
throw throwable;
}
}
}
}

View File

@ -18,7 +18,6 @@
*/
package org.jclouds.concurrent.internal;
import static com.google.common.reflect.Reflection.newProxy;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
@ -29,7 +28,8 @@ import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import org.jclouds.internal.ClassInvokerArgs;
import org.jclouds.internal.ForwardInvocationToInterface;
import org.jclouds.reflect.FunctionalReflection;
import org.jclouds.rest.functions.AlwaysPresentImplicitOptionalConverter;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
@ -73,14 +73,12 @@ public class SyncProxyTest {
Sync withOverride = syncProxyForTimeouts(ImmutableMap.of("default", 250L));
assertEquals(withOverride.get(), "foo");
verify(future);
}
public void testWithClassPropTimeout() throws Exception {
Sync withOverride = syncProxyForTimeouts(ImmutableMap.of("default", 50L, "Sync", 250L));
assertEquals(withOverride.get(), "foo");
verify(future);
}
public void testWithMethodPropTimeout() throws Exception {
@ -99,16 +97,13 @@ public class SyncProxyTest {
assertEquals(noOverrides.get(), "foo");
verify(future);
}
private Sync syncProxyForTimeouts(ImmutableMap<String, Long> timeouts) throws NoSuchMethodException {
LoadingCache<ClassInvokerArgs, Object> cache = CacheBuilder.newBuilder().build(
LoadingCache<ForwardInvocationToInterface, Object> cache = CacheBuilder.newBuilder().build(
CacheLoader.from(Functions.<Object> constant(null)));
return newProxy(
Sync.class,
new SyncProxy(new AlwaysPresentImplicitOptionalConverter(), cache, ImmutableMap.<Class<?>, Class<?>> of(
Sync.class, Async.class), timeouts, Sync.class, new Async()));
return FunctionalReflection.newProxy(Sync.class, new SyncProxy(new AlwaysPresentImplicitOptionalConverter(),
cache, ImmutableMap.<Class<?>, Class<?>> of(Sync.class, Async.class), timeouts, Sync.class, new Async()));
}
}

View File

@ -18,11 +18,18 @@
*/
package org.jclouds.http.functions;
import static com.google.common.base.Throwables.propagate;
import java.util.List;
import org.jclouds.http.functions.config.SaxParserModule;
import org.jclouds.reflect.Invocation;
import org.jclouds.rest.internal.GeneratedHttpRequest;
import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableList;
import com.google.common.reflect.Invokable;
import com.google.inject.Guice;
import com.google.inject.Injector;
@ -30,11 +37,12 @@ import com.google.inject.Injector;
*
* @author Adrian Cole
*/
@Test(groups = "unit")
public class BaseHandlerTest {
protected Injector injector = null;
protected ParseSax.Factory factory;
protected GeneratedHttpRequest request;
private Invocation toString;
@BeforeTest
protected void setUpInjector() {
@ -43,10 +51,27 @@ public class BaseHandlerTest {
assert factory != null;
}
@BeforeTest
protected void setUpRequest() {
try {
toString = Invocation.create(Invokable.from(String.class.getDeclaredMethod("toString")), ImmutableList.of());
} catch (SecurityException e) {
throw propagate(e);
} catch (NoSuchMethodException e) {
throw propagate(e);
}
request = GeneratedHttpRequest.builder().method("POST").endpoint("http://localhost/key").invocation(toString)
.build();
}
@AfterTest
protected void tearDownInjector() {
factory = null;
injector = null;
}
protected GeneratedHttpRequest requestForArgs(List<Object> args) {
return GeneratedHttpRequest.builder().method("POST").endpoint("http://localhost/key")
.invocation(Invocation.create(toString.getInvokable(), args)).build();
}
}

View File

@ -167,7 +167,7 @@ public class BackoffLimitedRetryHandlerTest {
}
private final RestAnnotationProcessor processor = BaseJettyTest.newBuilder(8100, new Properties()).buildInjector()
.getInstance(RestAnnotationProcessor.Factory.class).declaring(IntegrationTestAsyncClient.class);
.getInstance(RestAnnotationProcessor.class);
private HttpCommand createCommand() throws SecurityException, NoSuchMethodException {
Invokable<?, Object> method = Invokable.from(IntegrationTestAsyncClient.class.getMethod("download", String.class));

View File

@ -78,11 +78,12 @@ public class TrackingJavaUrlHttpCommandExecutorService extends JavaUrlHttpComman
}
public static Invokable<?, ?> getInvokerOfRequest(HttpCommand commandInvoked) {
return GeneratedHttpRequest.class.cast(commandInvoked.getCurrentRequest()).getInvoker();
return GeneratedHttpRequest.class.cast(commandInvoked.getCurrentRequest()).getInvocation().getInvokable();
}
public static List<Object> getArgsForRequestAtIndex(final Collection<HttpCommand> commandsInvoked, int index) {
return GeneratedHttpRequest.class.cast(Iterables.get(commandsInvoked, index).getCurrentRequest()).getArgs();
return GeneratedHttpRequest.class.cast(Iterables.get(commandsInvoked, index).getCurrentRequest()).getInvocation()
.getArgs();
}
@Inject

View File

@ -31,11 +31,13 @@ import org.jclouds.http.HttpResponse;
import org.jclouds.io.Payload;
import org.jclouds.io.Payloads;
import org.jclouds.json.config.GsonModule;
import org.jclouds.reflect.Invocation;
import org.jclouds.rest.internal.AsyncRestClientProxy;
import org.testng.annotations.Test;
import com.google.common.base.Function;
import com.google.common.base.Throwables;
import com.google.common.collect.ImmutableList;
import com.google.common.reflect.Invokable;
import com.google.inject.Guice;
import com.google.inject.Injector;
@ -57,7 +59,7 @@ public abstract class BaseParserTest<T, G> {
protected Function<HttpResponse, T> parser(Injector i) {
try {
return (Function<HttpResponse, T>) AsyncRestClientProxy.getTransformerForMethod(
Invokable.from(getClass().getMethod("expected")), i);
Invocation.create(Invokable.from(getClass().getMethod("expected")), ImmutableList.of()), i);
} catch (Exception e) {
throw Throwables.propagate(e);
}

View File

@ -1,66 +0,0 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds 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.reflect;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertNull;
import static org.testng.Assert.assertTrue;
import java.io.IOException;
import java.util.List;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableList;
import com.google.common.reflect.Invokable;
import com.google.common.reflect.Reflection;
/**
*
* @author Adrian Cole
*/
@Test
public class AbstractInvocationHandlerTest {
@Test(expectedExceptions = UnsupportedOperationException.class)
public void testNullArgsAreAllowedAndUnmodifiable() throws IOException {
Reflection.newProxy(Appendable.class, new AbstractInvocationHandler() {
protected Object handleInvocation(Object proxy, Invokable<?, ?> method, List<Object> args) throws Throwable {
assertNotNull(args);
assertNull(args.get(0));
args.add("foo");
throw new AssertionError("shouldn't be able to mutate the list!");
}
}).append(null);
}
@Test(expectedExceptions = UnsupportedOperationException.class)
public void testImmutableListWhenArgsAreNotNull() throws IOException {
Reflection.newProxy(Appendable.class, new AbstractInvocationHandler() {
protected Object handleInvocation(Object proxy, Invokable<?, ?> method, List<Object> args) throws Throwable {
assertNotNull(args);
assertTrue(args instanceof ImmutableList);
assertEquals(args.get(0), "foo");
args.add("bar");
throw new AssertionError("shouldn't be able to mutate the list!");
}
}).append("foo");
}
}

View File

@ -26,6 +26,7 @@ import org.jclouds.http.IntegrationTestAsyncClient;
import org.jclouds.http.IntegrationTestClient;
import org.jclouds.predicates.validators.AllLowerCaseValidator;
import org.jclouds.providers.AnonymousProviderMetadata;
import org.jclouds.reflect.Invocation;
import org.jclouds.rest.annotations.ParamValidators;
import org.jclouds.rest.internal.RestAnnotationProcessor;
import org.testng.TestException;
@ -62,7 +63,6 @@ public class InputParamValidatorTest {
"allParamsValidated", String.class, String.class));
Invokable<?, ?> oneParamValidatedMethod = Invokable.from(InputParamValidatorForm.class.getMethod(
"oneParamValidated", String.class, String.class));
RestAnnotationProcessor restAnnotationProcessor = factory(InputParamValidatorForm.class);
restAnnotationProcessor.createRequest(allParamsValidatedMethod, ImmutableList.<Object> of("blah", "blah"));
restAnnotationProcessor.createRequest(oneParamValidatedMethod, ImmutableList.<Object> of("blah", "blah"));
@ -98,15 +98,13 @@ public class InputParamValidatorTest {
@Test(expectedExceptions = ClassCastException.class)
public void testWrongPredicateTypeLiteral() throws Exception {
Invokable<?, ?> method = Invokable.from(WrongValidator.class.getMethod("method", Integer.class));
new InputParamValidator(injector).validateMethodParametersOrThrow(method, ImmutableList.<Object> of(55));
}
private RestAnnotationProcessor factory(Class<?> clazz) {
return injector.getInstance(RestAnnotationProcessor.Factory.class).declaring(clazz);
Invocation invocation = Invocation.create(Invokable.from(WrongValidator.class.getMethod("method", Integer.class)),
ImmutableList.<Object> of(55));
new InputParamValidator(injector).validateMethodParametersOrThrow(invocation);
}
Injector injector;
RestAnnotationProcessor restAnnotationProcessor;
@BeforeClass
void setupFactory() {
@ -114,7 +112,7 @@ public class InputParamValidatorTest {
.newBuilder(
AnonymousProviderMetadata.forClientMappedToAsyncClientOnEndpoint(IntegrationTestClient.class, IntegrationTestAsyncClient.class,
"http://localhost:9999")).buildInjector();
restAnnotationProcessor = injector.getInstance(RestAnnotationProcessor.class);
}
}

View File

@ -25,6 +25,7 @@ import java.io.File;
import javax.ws.rs.PathParam;
import org.jclouds.http.HttpRequest;
import org.jclouds.reflect.Invocation;
import org.jclouds.rest.annotations.Payload;
import org.jclouds.rest.annotations.PayloadParam;
import org.jclouds.rest.internal.GeneratedHttpRequest;
@ -55,7 +56,7 @@ public class BindMapToStringPayloadTest {
public void testCorrect() throws SecurityException, NoSuchMethodException {
Invokable<?, Object> testPayload = Invokable.from(TestPayload.class.getMethod("testPayload", String.class));
GeneratedHttpRequest request = GeneratedHttpRequest.builder()
.declaring(TestPayload.class).invoker(testPayload).args(ImmutableList.<Object> of("robot"))
.invocation(Invocation.create(testPayload, ImmutableList.<Object> of("robot")))
.method("POST").endpoint("http://localhost").build();
GeneratedHttpRequest newRequest = binder()
@ -69,7 +70,7 @@ public class BindMapToStringPayloadTest {
public void testDecodes() throws SecurityException, NoSuchMethodException {
Invokable<?, Object> testPayload = Invokable.from(TestPayload.class.getMethod("changeAdminPass", String.class));
GeneratedHttpRequest request = GeneratedHttpRequest.builder()
.declaring(TestPayload.class).invoker(testPayload).args(ImmutableList.<Object> of("foo"))
.invocation(Invocation.create(testPayload, ImmutableList.<Object> of("foo")))
.method("POST").endpoint("http://localhost").build();
GeneratedHttpRequest newRequest = binder()
@ -83,7 +84,7 @@ public class BindMapToStringPayloadTest {
public void testMustHavePayloadAnnotation() throws SecurityException, NoSuchMethodException {
Invokable<?, Object> noPayload = Invokable.from(TestPayload.class.getMethod("noPayload", String.class));
GeneratedHttpRequest request = GeneratedHttpRequest.builder()
.declaring(TestPayload.class).invoker(noPayload).args(ImmutableList.<Object> of("robot"))
.invocation(Invocation.create(noPayload, ImmutableList.<Object> of("robot")))
.method("POST").endpoint("http://localhost").build();
binder().bindToRequest(request, ImmutableMap.<String,Object>of("fooble", "robot"));
}

View File

@ -25,7 +25,8 @@ import static org.testng.Assert.assertTrue;
import java.util.concurrent.TimeUnit;
import java.util.logging.Logger;
import org.jclouds.internal.ClassInvokerArgsAndReturnVal;
import org.jclouds.reflect.Invocation;
import org.jclouds.reflect.InvocationSuccess;
import org.jclouds.rest.annotations.Delegate;
import org.jclouds.rest.annotations.SinceApiVersion;
import org.jclouds.rest.functions.PresentWhenApiVersionLexicographicallyAtOrAfterSinceApiVersion.Loader;
@ -122,7 +123,7 @@ public class PresentWhenApiVersionLexicographicallyAtOrAfterSinceApiVersionTest
}
public void testCacheIsFasterWhenNoAnnotationPresent() {
ClassInvokerArgsAndReturnVal keyPairApi = getKeyPairApi();
InvocationSuccess keyPairApi = getKeyPairApi();
ImplicitOptionalConverter fn = forApiVersion("2011-07-15");
Stopwatch watch = new Stopwatch().start();
fn.apply(keyPairApi);
@ -136,7 +137,7 @@ public class PresentWhenApiVersionLexicographicallyAtOrAfterSinceApiVersionTest
}
public void testCacheIsFasterWhenAnnotationPresent() {
ClassInvokerArgsAndReturnVal floatingIpApi = getKeyPairApi();
InvocationSuccess floatingIpApi = getKeyPairApi();
ImplicitOptionalConverter fn = forApiVersion("2011-07-15");
Stopwatch watch = new Stopwatch().start();
fn.apply(floatingIpApi);
@ -150,23 +151,23 @@ public class PresentWhenApiVersionLexicographicallyAtOrAfterSinceApiVersionTest
}
ClassInvokerArgsAndReturnVal getFloatingIPApi() {
InvocationSuccess getFloatingIPApi() {
return getApi("Tag", TagAsyncApi.class);
}
ClassInvokerArgsAndReturnVal getKeyPairApi() {
InvocationSuccess getKeyPairApi() {
return getApi("KeyPair", KeyPairAsyncApi.class);
}
ClassInvokerArgsAndReturnVal getVpcApi() {
InvocationSuccess getVpcApi() {
return getApi("Vpc", VpcAsyncApi.class);
}
ClassInvokerArgsAndReturnVal getApi(String name, Class<?> type) {
InvocationSuccess getApi(String name, Class<?> target) {
try {
return ClassInvokerArgsAndReturnVal.builder().clazz(type)
.invoker(Invokable.from(EC2AsyncApi.class.getDeclaredMethod("get" + name + "ApiForRegion", String.class)))
.args(ImmutableList.<Object> of("region")).returnVal("present").build();
return InvocationSuccess.create(Invocation.create(
Invokable.from(EC2AsyncApi.class.getDeclaredMethod("get" + name + "ApiForRegion", String.class)),
ImmutableList.<Object> of("region")), "present");
} catch (Exception e) {
throw propagate(e);
}

View File

@ -33,7 +33,6 @@ import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableSet;
import com.google.common.reflect.TypeToken;
import com.google.inject.Binder;
import com.google.inject.Injector;
import com.google.inject.Module;
@ -64,9 +63,7 @@ public abstract class BaseAsyncApiTest<T> extends BaseRestApiTest {
protected void setupFactory() throws IOException {
injector = createInjector();
parserFactory = injector.getInstance(ParseSax.Factory.class);
processor = injector.getInstance(RestAnnotationProcessor.Factory.class).declaring(new TypeToken<T>(getClass()) {
private static final long serialVersionUID = 1L;
}.getRawType());
processor = injector.getInstance(RestAnnotationProcessor.class);
}
protected String identity = "identity";

View File

@ -40,11 +40,13 @@ import org.jclouds.http.config.ConfiguresHttpCommandExecutorService;
import org.jclouds.http.functions.ParseSax;
import org.jclouds.io.MutableContentMetadata;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.reflect.Invocation;
import org.jclouds.rest.annotations.Fallback;
import org.jclouds.rest.annotations.XMLResponseParser;
import org.jclouds.util.Strings2;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Multimap;
import com.google.common.collect.SortedSetMultimap;
import com.google.common.collect.TreeMultimap;
@ -176,11 +178,8 @@ public abstract class BaseRestApiTest {
}
protected void assertResponseParserClassEquals(Invokable<?, ?> method, HttpRequest request, @Nullable Class<?> parserClass) {
assertEquals(AsyncRestClientProxy.createResponseParser(parserFactory, injector, method, request).getClass(), parserClass);
assertEquals(
AsyncRestClientProxy.createResponseParser(parserFactory, injector,
Invocation.create(method, ImmutableList.of()), request).getClass(), parserClass);
}
protected RestAnnotationProcessor factory(Class<?> clazz) {
return injector.getInstance(RestAnnotationProcessor.Factory.class).declaring(clazz);
}
}

View File

@ -40,26 +40,26 @@ public class Optionals2Test {
}
public void testReturnTypeOrTypeOfOptionalWhenOptional() throws SecurityException, NoSuchMethodException {
Invokable<?, ?> method = Invokable.from(Test.class.getMethod("getOptional"));
Invokable<?, ?> invoked = Invokable.from(Test.class.getMethod("getOptional"));
assertEquals(Optionals2.returnTypeOrTypeOfOptional(method), String.class);
assertEquals(Optionals2.unwrapIfOptional(invoked.getReturnType()), String.class);
}
public void testReturnTypeOrTypeOfOptionalWhenNotOptional() throws SecurityException, NoSuchMethodException {
Invokable<?, ?> method = Invokable.from(Test.class.getMethod("getNotOptional"));
Invokable<?, ?> invoked = Invokable.from(Test.class.getMethod("getNotOptional"));
assertEquals(Optionals2.returnTypeOrTypeOfOptional(method), String.class);
assertEquals(Optionals2.unwrapIfOptional(invoked.getReturnType()), String.class);
}
public void testIsReturnTypeOptionalWhenOptional() throws SecurityException, NoSuchMethodException {
Invokable<?, ?> method = Invokable.from(Test.class.getMethod("getOptional"));
Invokable<?, ?> invoked = Invokable.from(Test.class.getMethod("getOptional"));
assertTrue(Optionals2.isReturnTypeOptional(method));
assertTrue(Optionals2.isReturnTypeOptional(invoked));
}
public void testIsReturnTypeOptionalWhenNotOptional() throws SecurityException, NoSuchMethodException {
Invokable<?, ?> method = Invokable.from(Test.class.getMethod("getNotOptional"));
Invokable<?, ?> invoked = Invokable.from(Test.class.getMethod("getNotOptional"));
assertFalse(Optionals2.isReturnTypeOptional(method));
assertFalse(Optionals2.isReturnTypeOptional(invoked));
}
}

View File

@ -21,7 +21,7 @@ package org.jclouds.util;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.createNiceMock;
import static org.jclouds.util.Throwables2.getFirstThrowableOfType;
import static org.jclouds.util.Throwables2.returnFirstExceptionIfInListOrThrowStandardExceptionOrCause;
import static org.jclouds.util.Throwables2.propagateIfPossible;
import static org.testng.Assert.assertEquals;
import java.io.IOException;
@ -52,17 +52,16 @@ import com.google.inject.spi.Message;
@Test
public class Throwables2Test {
public void testGetFirstThrowableOfTypeSubclass() {
SocketException aex = createMock(SocketException.class);
assertEquals(getFirstThrowableOfType(aex, IOException.class), aex);
}
public void testGetFirstThrowableOfTypeOuter() {
AuthorizationException aex = createMock(AuthorizationException.class);
assertEquals(getFirstThrowableOfType(aex, AuthorizationException.class), aex);
}
public void testGetCause() {
AuthorizationException aex = createMock(AuthorizationException.class);
Message message = new Message(ImmutableList.of(), "test", aex);
@ -90,7 +89,6 @@ public class Throwables2Test {
assertEquals(getFirstThrowableOfType(pex, AuthorizationException.class), null);
}
public void testGetCauseCreation() {
AuthorizationException aex = createMock(AuthorizationException.class);
Message message = new Message(ImmutableList.of(), "test", aex);
@ -146,132 +144,125 @@ public class Throwables2Test {
assertEquals(getFirstThrowableOfType(pex, AuthorizationException.class), null);
}
@Test
public void testReturnExceptionThatsInList() throws Exception {
@Test(expectedExceptions = TestException.class)
public void testPropagateExceptionThatsInList() throws Throwable {
Exception e = new TestException();
assertEquals(
returnFirstExceptionIfInListOrThrowStandardExceptionOrCause(
ImmutableSet.<TypeToken<? extends Throwable>> of(TypeToken.of(TestException.class)), e), e);
assertEquals(
returnFirstExceptionIfInListOrThrowStandardExceptionOrCause(
ImmutableSet.<TypeToken<? extends Throwable>> of(TypeToken.of(TestException.class)),
new RuntimeException(e)), e);
propagateIfPossible(e, ImmutableSet.<TypeToken<? extends Throwable>> of(TypeToken.of(TestException.class)));
}
@Test(expectedExceptions = TestException.class)
public void testThrowExceptionNotInList() throws Exception {
public void testPropagateWrappedExceptionThatsInList() throws Throwable {
Exception e = new TestException();
returnFirstExceptionIfInListOrThrowStandardExceptionOrCause(ImmutableSet.<TypeToken<? extends Throwable>> of(), e);
propagateIfPossible(new RuntimeException(e),
ImmutableSet.<TypeToken<? extends Throwable>> of(TypeToken.of(TestException.class)));
}
public void testPropagateIfPossibleDoesnThrowExceptionNotInList() throws Throwable {
Exception e = new TestException();
propagateIfPossible(e, ImmutableSet.<TypeToken<? extends Throwable>> of());
}
@Test(expectedExceptions = IllegalStateException.class)
public void testPropagateStandardExceptionIllegalStateException() throws Exception {
public void testPropagateStandardExceptionIllegalStateException() throws Throwable {
Exception e = new IllegalStateException();
returnFirstExceptionIfInListOrThrowStandardExceptionOrCause(ImmutableSet.<TypeToken<? extends Throwable>> of(),
new RuntimeException(e));
propagateIfPossible(new RuntimeException(e), ImmutableSet.<TypeToken<? extends Throwable>> of());
}
@Test(expectedExceptions = IllegalArgumentException.class)
public void testPropagateStandardExceptionIllegalArgumentException() throws Exception {
public void testPropagateStandardExceptionIllegalArgumentException() throws Throwable {
Exception e = new IllegalArgumentException();
returnFirstExceptionIfInListOrThrowStandardExceptionOrCause(ImmutableSet.<TypeToken<? extends Throwable>> of(),
new RuntimeException(e));
propagateIfPossible(new RuntimeException(e), ImmutableSet.<TypeToken<? extends Throwable>> of());
}
@Test(expectedExceptions = UnsupportedOperationException.class)
public void testPropagateStandardExceptionUnsupportedOperationException() throws Exception {
public void testPropagateStandardExceptionUnsupportedOperationException() throws Throwable {
Exception e = new UnsupportedOperationException();
returnFirstExceptionIfInListOrThrowStandardExceptionOrCause(ImmutableSet.<TypeToken<? extends Throwable>> of(),
new RuntimeException(e));
propagateIfPossible(new RuntimeException(e), ImmutableSet.<TypeToken<? extends Throwable>> of());
}
@Test(expectedExceptions = AssertionError.class)
public void testPropagateStandardExceptionAssertionError() throws Exception {
public void testPropagateStandardExceptionAssertionError() throws Throwable {
AssertionError e = new AssertionError();
returnFirstExceptionIfInListOrThrowStandardExceptionOrCause(ImmutableSet.<TypeToken<? extends Throwable>> of(),
new RuntimeException(e));
propagateIfPossible(new RuntimeException(e), ImmutableSet.<TypeToken<? extends Throwable>> of());
}
@Test(expectedExceptions = AuthorizationException.class)
public void testPropagateStandardExceptionAuthorizationException() throws Exception {
public void testPropagateStandardExceptionAuthorizationException() throws Throwable {
Exception e = new AuthorizationException();
returnFirstExceptionIfInListOrThrowStandardExceptionOrCause(ImmutableSet.<TypeToken<? extends Throwable>> of(),
new RuntimeException(e));
propagateIfPossible(new RuntimeException(e), ImmutableSet.<TypeToken<? extends Throwable>> of());
}
@Test(expectedExceptions = AuthorizationException.class)
public void testPropagateProvisionExceptionAuthorizationException() throws Exception {
public void testPropagateProvisionExceptionAuthorizationException() throws Throwable {
Exception e = new AuthorizationException();
returnFirstExceptionIfInListOrThrowStandardExceptionOrCause(ImmutableSet.<TypeToken<? extends Throwable>> of(),
new ProvisionException(ImmutableSet.of(new Message(ImmutableList.of(), "Error in custom provider", e))));
propagateIfPossible(
new ProvisionException(ImmutableSet.of(new Message(ImmutableList.of(), "Error in custom provider", e))),
ImmutableSet.<TypeToken<? extends Throwable>> of());
}
@Test(expectedExceptions = AuthorizationException.class)
public void testPropagateCreationExceptionAuthorizationException() throws Exception {
public void testPropagateCreationExceptionAuthorizationException() throws Throwable {
Exception e = new AuthorizationException();
returnFirstExceptionIfInListOrThrowStandardExceptionOrCause(ImmutableSet.<TypeToken<? extends Throwable>> of(),
new CreationException(ImmutableSet.of(new Message(ImmutableList.of(), "Error in custom provider", e))));
propagateIfPossible(
new CreationException(ImmutableSet.of(new Message(ImmutableList.of(), "Error in custom provider", e))),
ImmutableSet.<TypeToken<? extends Throwable>> of());
}
@Test(expectedExceptions = InsufficientResourcesException.class)
public void testPropagateStandardExceptionInsufficientResourcesException() throws Exception {
public void testPropagateStandardExceptionInsufficientResourcesException() throws Throwable {
Exception e = new InsufficientResourcesException();
returnFirstExceptionIfInListOrThrowStandardExceptionOrCause(ImmutableSet.<TypeToken<? extends Throwable>> of(),
new RuntimeException(e));
propagateIfPossible(new RuntimeException(e), ImmutableSet.<TypeToken<? extends Throwable>> of());
}
@Test(expectedExceptions = ResourceNotFoundException.class)
public void testPropagateStandardExceptionResourceNotFoundException() throws Exception {
public void testPropagateStandardExceptionResourceNotFoundException() throws Throwable {
Exception e = new ResourceNotFoundException();
returnFirstExceptionIfInListOrThrowStandardExceptionOrCause(ImmutableSet.<TypeToken<? extends Throwable>> of(),
new RuntimeException(e));
propagateIfPossible(new RuntimeException(e), ImmutableSet.<TypeToken<? extends Throwable>> of());
}
@Test(expectedExceptions = IllegalStateException.class)
public void testPropagateStandardExceptionIllegalStateExceptionNestedInHttpResponseException() throws Exception {
public void testPropagateStandardExceptionIllegalStateExceptionNestedInHttpResponseException() throws Throwable {
Exception e = new IllegalStateException();
returnFirstExceptionIfInListOrThrowStandardExceptionOrCause(ImmutableSet.<TypeToken<? extends Throwable>> of(),
new HttpResponseException("goo", createNiceMock(HttpCommand.class), null, e));
propagateIfPossible(new HttpResponseException("goo", createNiceMock(HttpCommand.class), null, e),
ImmutableSet.<TypeToken<? extends Throwable>> of());
}
@Test(expectedExceptions = IllegalArgumentException.class)
public void testPropagateStandardExceptionIllegalArgumentExceptionNestedInHttpResponseException() throws Exception {
public void testPropagateStandardExceptionIllegalArgumentExceptionNestedInHttpResponseException() throws Throwable {
Exception e = new IllegalArgumentException();
returnFirstExceptionIfInListOrThrowStandardExceptionOrCause(ImmutableSet.<TypeToken<? extends Throwable>> of(),
new HttpResponseException("goo", createNiceMock(HttpCommand.class), null, e));
propagateIfPossible(new HttpResponseException("goo", createNiceMock(HttpCommand.class), null, e),
ImmutableSet.<TypeToken<? extends Throwable>> of());
}
@Test(expectedExceptions = UnsupportedOperationException.class)
public void testPropagateStandardExceptionUnsupportedOperationExceptionNestedInHttpResponseException()
throws Exception {
throws Throwable {
Exception e = new UnsupportedOperationException();
returnFirstExceptionIfInListOrThrowStandardExceptionOrCause(ImmutableSet.<TypeToken<? extends Throwable>> of(),
new HttpResponseException("goo", createNiceMock(HttpCommand.class), null, e));
propagateIfPossible(new HttpResponseException("goo", createNiceMock(HttpCommand.class), null, e),
ImmutableSet.<TypeToken<? extends Throwable>> of());
}
@Test(expectedExceptions = AuthorizationException.class)
public void testPropagateStandardExceptionAuthorizationExceptionNestedInHttpResponseException() throws Exception {
public void testPropagateStandardExceptionAuthorizationExceptionNestedInHttpResponseException() throws Throwable {
Exception e = new AuthorizationException();
returnFirstExceptionIfInListOrThrowStandardExceptionOrCause(ImmutableSet.<TypeToken<? extends Throwable>> of(),
new HttpResponseException("goo", createNiceMock(HttpCommand.class), null, e));
propagateIfPossible(new HttpResponseException("goo", createNiceMock(HttpCommand.class), null, e),
ImmutableSet.<TypeToken<? extends Throwable>> of());
}
@Test(expectedExceptions = ResourceNotFoundException.class)
public void testPropagateStandardExceptionResourceNotFoundExceptionNestedInHttpResponseException() throws Exception {
public void testPropagateStandardExceptionResourceNotFoundExceptionNestedInHttpResponseException() throws Throwable {
Exception e = new ResourceNotFoundException();
returnFirstExceptionIfInListOrThrowStandardExceptionOrCause(ImmutableSet.<TypeToken<? extends Throwable>> of(),
new HttpResponseException("goo", createNiceMock(HttpCommand.class), null, e));
propagateIfPossible(new HttpResponseException("goo", createNiceMock(HttpCommand.class), null, e),
ImmutableSet.<TypeToken<? extends Throwable>> of());
}
@Test(expectedExceptions = HttpResponseException.class)
public void testPropagateStandardExceptionHttpResponseException() throws Exception {
public void testPropagateStandardExceptionHttpResponseException() throws Throwable {
Exception e = new HttpResponseException("goo", createNiceMock(HttpCommand.class), null);
returnFirstExceptionIfInListOrThrowStandardExceptionOrCause(ImmutableSet.<TypeToken<? extends Throwable>> of(),
new RuntimeException(e));
propagateIfPossible(new RuntimeException(e), ImmutableSet.<TypeToken<? extends Throwable>> of());
}
static class TestException extends Exception {
private static final long serialVersionUID = 1L;
}
}

Some files were not shown because too many files have changed in this diff Show More