mirror of https://github.com/apache/jclouds.git
refactored internal code and tests to use FunctionalReflection
This commit is contained in:
parent
bd9e998b12
commit
3089111621
|
@ -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"))))));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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[]) {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
*
|
||||
|
@ -50,33 +52,33 @@ public class PresentWhenExtensionAnnotationNamespaceEqualsAnyNamespaceInExtensio
|
|||
|
||||
@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();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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());
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -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() + "");
|
||||
|
|
|
@ -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"))))));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,9 +59,14 @@ 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
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -48,18 +48,17 @@ 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);
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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)))
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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();
|
||||
|
||||
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(200).message("ok").payload("")
|
||||
.addHeader("Last-Modified", "Fri, 12 Jun 2007 13:40:18 GMT")
|
||||
.addHeader("Content-Length", "0")
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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[]) {
|
||||
|
|
|
@ -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()) {
|
||||
|
|
|
@ -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()) {
|
||||
|
|
|
@ -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[]) {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,25 +36,14 @@ 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);
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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!
|
||||
|
|
|
@ -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[]) {
|
||||
|
|
|
@ -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[]) {
|
||||
|
|
|
@ -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[]) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
@ -59,9 +60,7 @@ public class BindCloneVAppParamsToXmlPayloadTest {
|
|||
|
||||
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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
@ -116,17 +108,12 @@ public class BindVAppConfigurationToXmlPayloadTest {
|
|||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,130 +58,174 @@ 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
|
||||
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);
|
||||
}
|
||||
|
||||
@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);
|
||||
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();
|
||||
|
@ -190,6 +233,6 @@ public final class SyncProxy extends AbstractInvocationHandler {
|
|||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "blocking invocation handler for: " + delegate.getClass().getSimpleName();
|
||||
return String.format("%s->%s", declaring.getClass().getSimpleName(), delegate.getClass().getSimpleName());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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() + "]";
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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()));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -32,6 +32,8 @@ 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
|
||||
|
@ -44,9 +46,10 @@ public class BindMapToStringPayload implements MapBinder {
|
|||
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));
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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>> {
|
||||
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
|
@ -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));
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
public final static class Builder extends HttpRequest.Builder<Builder> {
|
||||
protected Invocation invocation;
|
||||
protected Optional<Invocation> caller = Optional.absent();
|
||||
|
||||
/**
|
||||
* @see GeneratedHttpRequest#getDeclaring()
|
||||
* @see GeneratedHttpRequest#getInvocation()
|
||||
*/
|
||||
public Builder declaring(Class<?> declaring) {
|
||||
this.declaring = checkNotNull(declaring, "declaring");
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see GeneratedHttpRequest#getInvoker()
|
||||
*/
|
||||
public Builder invoker(Invokable<?, ?> invoker) {
|
||||
this.invoker = checkNotNull(invoker, "invoker");
|
||||
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);
|
||||
public Builder invocation(Invocation invocation) {
|
||||
this.invocation = checkNotNull(invocation, "invocation");
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,7 +182,6 @@ public abstract class RestAnnotationProcessor {
|
|||
}
|
||||
};
|
||||
|
||||
private final Class<?> declaring;
|
||||
private final Injector injector;
|
||||
private final HttpUtils utils;
|
||||
private final ContentMetadataCodec contentMetadataCodec;
|
||||
|
@ -205,47 +189,52 @@ public abstract class RestAnnotationProcessor {
|
|||
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();
|
||||
|
||||
|
@ -254,18 +243,18 @@ public abstract class RestAnnotationProcessor {
|
|||
|
||||
UriBuilder uriBuilder = uriBuilder(endpoint.get().toString()); // URI template in rfc6570 form
|
||||
|
||||
overridePathEncoding(uriBuilder, invoker);
|
||||
overridePathEncoding(uriBuilder, invocation);
|
||||
|
||||
tokenValues.putAll(addPathAndGetTokens(declaring, invoker, args, uriBuilder));
|
||||
tokenValues.putAll(addPathAndGetTokens(invocation, 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);
|
||||
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));
|
||||
|
@ -303,13 +292,13 @@ public abstract class RestAnnotationProcessor {
|
|||
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) {
|
||||
|
@ -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,7 +336,7 @@ 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());
|
||||
}
|
||||
|
||||
|
@ -363,12 +352,13 @@ public abstract class RestAnnotationProcessor {
|
|||
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()));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -383,63 +373,59 @@ public abstract class RestAnnotationProcessor {
|
|||
}
|
||||
}
|
||||
|
||||
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)));
|
||||
|
||||
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))
|
||||
|
@ -661,20 +658,20 @@ public abstract class RestAnnotationProcessor {
|
|||
}
|
||||
});
|
||||
|
||||
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,12 +798,12 @@ 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) {
|
||||
|
@ -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());
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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()));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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"));
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,7 +52,6 @@ import com.google.inject.spi.Message;
|
|||
@Test
|
||||
public class Throwables2Test {
|
||||
|
||||
|
||||
public void testGetFirstThrowableOfTypeSubclass() {
|
||||
SocketException aex = createMock(SocketException.class);
|
||||
assertEquals(getFirstThrowableOfType(aex, IOException.class), 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
Loading…
Reference in New Issue