added qualifier support to annotation parsing so that we can expose cached objects

This commit is contained in:
Adrian Cole 2011-03-21 14:57:57 -07:00
parent 8d9d7e406b
commit f2e6c72e5a
10 changed files with 177 additions and 96 deletions

View File

@ -24,13 +24,16 @@ package org.jclouds.rest.internal;
*
* @author Adrian Cole
*/
import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.NoSuchElementException;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ExecutionException;
import javax.annotation.Resource;
import javax.inject.Named;
import javax.inject.Qualifier;
import javax.inject.Singleton;
import org.jclouds.Constants;
@ -46,6 +49,9 @@ import org.jclouds.rest.annotations.Delegate;
import org.jclouds.util.Throwables2;
import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.inject.Inject;
@ -83,6 +89,15 @@ public class AsyncRestClientProxy<T> implements InvocationHandler {
this.delegateMap = delegateMap;
}
private static final Predicate<Annotation> isQualifierPresent = new Predicate<Annotation>() {
@Override
public boolean apply(Annotation input) {
return input.annotationType().isAnnotationPresent(Qualifier.class);
}
};
public Object invoke(Object o, Method method, Object[] args) throws Throwable {
if (method.getName().equals("equals")) {
return this.equals(o);
@ -91,7 +106,12 @@ public class AsyncRestClientProxy<T> implements InvocationHandler {
} else if (method.getName().equals("hashCode")) {
return this.hashCode();
} else if (method.isAnnotationPresent(Provides.class)) {
return injector.getInstance(Key.get(method.getGenericReturnType()));
try {
Annotation qualifier = Iterables.find(ImmutableList.copyOf(method.getAnnotations()), isQualifierPresent);
return injector.getInstance(Key.get(method.getGenericReturnType(), qualifier));
} catch (NoSuchElementException e) {
return injector.getInstance(Key.get(method.getGenericReturnType()));
}
} else if (method.isAnnotationPresent(Delegate.class)) {
return delegateMap.get(new ClassMethodArgs(method.getReturnType(), method, args));
} else if (annotationProcessor.getDelegateOrNull(method) != null

View File

@ -122,7 +122,7 @@ public class SyncProxyTest {
public Set<String> string() {
return ImmutableSet.of("new");
}
public ListenableFuture<String> take20Milliseconds() {
return Futures.makeListenable(executorService.submit(new Callable<String>() {

View File

@ -159,6 +159,7 @@ import com.google.inject.Key;
import com.google.inject.Module;
import com.google.inject.Provides;
import com.google.inject.TypeLiteral;
import com.google.inject.name.Names;
import com.sun.jersey.api.uri.UriBuilderImpl;
/**
@ -2173,7 +2174,11 @@ public class RestAnnotationProcessorTest extends BaseRestClientTest {
public interface TestClassForm {
@Provides
Set<String> set();
@Named("bar")
@Provides
Set<String> foo();
@POST
@Path("/")
void oneForm(@PathParam("bucket") String path);
@ -2185,6 +2190,13 @@ public class RestAnnotationProcessorTest extends BaseRestClientTest {
assertEquals(set, ImmutableSet.of("foo"));
}
@Test
public void testProvidesWithGenericQualified() throws SecurityException, NoSuchMethodException,
UnsupportedEncodingException {
Set<String> set = injector.getInstance(AsyncClientFactory.class).create(TestClassForm.class).foo();
assertEquals(set, ImmutableSet.of("bar"));
}
@Test
public void testBuildOneClassForm() throws SecurityException, NoSuchMethodException, UnsupportedEncodingException {
Method oneForm = TestClassForm.class.getMethod("oneForm", String.class);
@ -2234,6 +2246,8 @@ public class RestAnnotationProcessorTest extends BaseRestClientTest {
protected void configure() {
bind(new TypeLiteral<Set<String>>() {
}).toInstance(ImmutableSet.of("foo"));
bind(new TypeLiteral<Set<String>>() {
}).annotatedWith(Names.named("bar")).toInstance(ImmutableSet.of("bar"));
bind(URI.class).annotatedWith(Localhost2.class).toInstance(
URI.create("http://localhost:1111"));
}

View File

@ -19,8 +19,14 @@
package org.jclouds.savvis.vpdc;
import java.util.Set;
import org.jclouds.rest.annotations.Delegate;
import org.jclouds.savvis.vpdc.domain.Resource;
import org.jclouds.savvis.vpdc.features.BrowsingAsyncClient;
import org.jclouds.savvis.vpdc.internal.Org;
import com.google.inject.Provides;
/**
* Provides asynchronous access to VPDC via their REST API.
@ -38,4 +44,11 @@ public interface VPDCAsyncClient {
@Delegate
BrowsingAsyncClient getBrowsingClient();
/**
*
* @return a listing of all orgs that the current user has access to.
*/
@Provides
@Org
Set<Resource> listOrgs();
}

View File

@ -19,10 +19,12 @@
package org.jclouds.savvis.vpdc;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import org.jclouds.concurrent.Timeout;
import org.jclouds.rest.annotations.Delegate;
import org.jclouds.savvis.vpdc.domain.Resource;
import org.jclouds.savvis.vpdc.features.BrowsingClient;
/**
@ -42,4 +44,9 @@ public interface VPDCClient {
@Delegate
BrowsingClient getBrowsingClient();
/**
*
* @return a listing of all orgs that the current user has access to.
*/
Set<Resource> listOrgs();
}

View File

@ -27,6 +27,7 @@ import static org.jclouds.Constants.PROPERTY_SESSION_INTERVAL;
import static org.jclouds.savvis.vpdc.reference.VCloudConstants.PROPERTY_VCLOUD_TIMEOUT_TASK_COMPLETED;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
@ -81,7 +82,7 @@ public class VPDCRestClientModule extends RestClientModule<VPDCClient, VPDCAsync
@Provides
@org.jclouds.savvis.vpdc.internal.Org
@Singleton
protected Iterable<org.jclouds.savvis.vpdc.domain.Resource> provideOrgs(Supplier<VCloudSession> cache,
protected Set<org.jclouds.savvis.vpdc.domain.Resource> provideOrgs(Supplier<VCloudSession> cache,
@Named(PROPERTY_IDENTITY) String user) {
VCloudSession discovery = cache.get();
checkState(discovery.getOrgs().size() > 0, "No orgs present for user: " + user);
@ -91,7 +92,7 @@ public class VPDCRestClientModule extends RestClientModule<VPDCClient, VPDCAsync
@Provides
@org.jclouds.savvis.vpdc.internal.Org
@Singleton
protected String provideDefaultOrgId(@org.jclouds.savvis.vpdc.internal.Org Iterable<Resource> orgs) {
protected String provideDefaultOrgId(@org.jclouds.savvis.vpdc.internal.Org Set<Resource> orgs) {
return Iterables.get(orgs, 0).getId();
}

View File

@ -50,28 +50,29 @@ public class VPDCErrorHandler implements HttpErrorHandler {
// it is important to always read fully and close streams
String message = parseMessage(response);
Exception exception = message != null ? new HttpResponseException(command, response, message)
: new HttpResponseException(command, response);
: new HttpResponseException(command, response);
try {
message = message != null ? message : String.format("%s -> %s", command.getCurrentRequest().getRequestLine(),
response.getStatusLine());
response.getStatusLine());
switch (response.getStatusCode()) {
case 400:
exception = new IllegalArgumentException(message, exception);
break;
case 401:
exception = new AuthorizationException(message, exception);
break;
case 404:
if (!command.getCurrentRequest().getMethod().equals("DELETE")) {
exception = new ResourceNotFoundException(message, exception);
}
break;
case 405:
exception = new IllegalArgumentException(message, exception);
break;
case 409:
exception = new IllegalStateException(message, exception);
break;
case 400:
exception = new IllegalArgumentException(message, exception);
break;
case 401:
case 403:
exception = new AuthorizationException(message, exception);
break;
case 404:
if (!command.getCurrentRequest().getMethod().equals("DELETE")) {
exception = new ResourceNotFoundException(message, exception);
}
break;
case 405:
exception = new IllegalArgumentException(message, exception);
break;
case 409:
exception = new IllegalStateException(message, exception);
break;
}
} finally {
if (response.getPayload() != null)

View File

@ -19,8 +19,9 @@
package org.jclouds.savvis.vpdc;
import static org.testng.Assert.assertEquals;
import java.io.IOException;
import java.util.concurrent.ExecutionException;
import org.jclouds.http.HttpRequest;
import org.jclouds.rest.internal.RestAnnotationProcessor;
@ -42,12 +43,14 @@ public class VPDCAsyncClientTest extends BaseVPDCAsyncClientTest<VPDCAsyncClient
private VPDCAsyncClient asyncClient;
private VPDCClient syncClient;
public void testSync() throws SecurityException, NoSuchMethodException, InterruptedException, ExecutionException {
public void testSync() {
assert syncClient.getBrowsingClient() != null;
assertEquals(syncClient.listOrgs().size(), 1);
}
public void testAsync() throws SecurityException, NoSuchMethodException, InterruptedException, ExecutionException {
public void testAsync() {
assert asyncClient.getBrowsingClient() != null;
assertEquals(syncClient.listOrgs().size(), 1);
}
@Override

View File

@ -19,6 +19,7 @@
package org.jclouds.savvis.vpdc.features;
import static org.jclouds.savvis.vpdc.options.GetVAppOptions.Builder.withPowerState;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
@ -27,7 +28,6 @@ import org.jclouds.savvis.vpdc.domain.Org;
import org.jclouds.savvis.vpdc.domain.Resource;
import org.jclouds.savvis.vpdc.domain.VApp;
import org.jclouds.savvis.vpdc.domain.VDC;
import static org.jclouds.savvis.vpdc.options.GetVAppOptions.Builder.withPowerState;
import org.jclouds.savvis.vpdc.reference.VCloudMediaType;
import org.testng.annotations.BeforeGroups;
import org.testng.annotations.Test;
@ -49,86 +49,97 @@ public class BrowsingClientLiveTest extends BaseVPDCClientLiveTest {
@Test
public void testOrg() throws Exception {
Org response = client.getOrg(null);
assertNotNull(response);
assertNotNull(response.getId());
assertNotNull(response.getHref());
assertNotNull(response.getName());
// savvis leaves this null for some reason
assertEquals(response.getType(), null);
assert response.getImages().size() >= 0;
assert response.getDescription() != null;
assert response.getVDCs().size() >= 1;
assertEquals(client.getOrg(response.getId()).toString(), response.toString());
}
for (Resource org : context.getApi().listOrgs()) {
Org response = client.getOrg(org.getId());
@Test
public void testVDC() throws Exception {
Org org = client.getOrg(null);
for (Resource vdc : org.getVDCs()) {
VDC response = client.getVDCInOrg(null, vdc.getId());
assertNotNull(response);
assertNotNull(response.getId());
assertNotNull(response.getHref());
assertNotNull(response.getName());
assertNotNull(response.getStatus());
assertEquals(response.getType(), "application/vnd.vmware.vcloud.vdc+xml");
assertNotNull(response.getDescription());
assertNotNull(response.getResourceEntities());
assertNotNull(response.getAvailableNetworks());
assertEquals(client.getVDCInOrg(null, response.getId()).toString(), response.toString());
// savvis leaves this null for some reason
assertEquals(response.getType(), null);
assert response.getImages().size() >= 0;
assert response.getDescription() != null;
assert response.getVDCs().size() >= 1;
assertEquals(client.getOrg(response.getId()).toString(), response.toString());
}
}
@Test
public void testVDC() throws Exception {
for (Resource org1 : context.getApi().listOrgs()) {
Org org = client.getOrg(org1.getId());
for (Resource vdc : org.getVDCs()) {
VDC response = client.getVDCInOrg(org.getId(), vdc.getId());
assertNotNull(response);
assertNotNull(response.getId());
assertNotNull(response.getHref());
assertNotNull(response.getName());
assertNotNull(response.getStatus());
assertEquals(response.getType(), "application/vnd.vmware.vcloud.vdc+xml");
assertNotNull(response.getDescription());
assertNotNull(response.getResourceEntities());
assertNotNull(response.getAvailableNetworks());
assertEquals(client.getVDCInOrg(org.getId(), response.getId()).toString(), response.toString());
}
}
}
@Test
public void testNetwork() throws Exception {
Org org = client.getOrg(null);
for (Resource vdc : org.getVDCs()) {
VDC VDC = client.getVDCInOrg(null, vdc.getId());
for (Resource vApp : VDC.getAvailableNetworks()) {
Network response = client.getNetworkInOrgAndVDC(org.getId(), vdc.getId(), vApp.getId());
assertNotNull(response);
assertNotNull(response.getId());
assertNotNull(response.getHref());
assertNotNull(response.getName());
assertEquals(response.getType(), VCloudMediaType.NETWORK_XML);
assertNotNull(response.getNetmask());
assertNotNull(response.getGateway());
assertNotNull(response.getInternalToExternalNATRules());
assertEquals(client.getNetworkInOrgAndVDC(null, vdc.getId(), response.getId()).toString(), response
.toString());
for (Resource org1 : context.getApi().listOrgs()) {
Org org = client.getOrg(org1.getId());
for (Resource vdc : org.getVDCs()) {
VDC VDC = client.getVDCInOrg(org.getId(), vdc.getId());
for (Resource vApp : VDC.getAvailableNetworks()) {
Network response = client.getNetworkInOrgAndVDC(org.getId(), vdc.getId(), vApp.getId());
assertNotNull(response);
assertNotNull(response.getId());
assertNotNull(response.getHref());
assertNotNull(response.getName());
assertEquals(response.getType(), VCloudMediaType.NETWORK_XML);
assertNotNull(response.getNetmask());
assertNotNull(response.getGateway());
assertNotNull(response.getInternalToExternalNATRules());
assertEquals(client.getNetworkInOrgAndVDC(org.getId(), vdc.getId(), response.getId()).toString(),
response.toString());
}
}
}
}
@Test
public void testVApp() throws Exception {
Org org = client.getOrg(null);
for (Resource vdc : org.getVDCs()) {
VDC VDC = client.getVDCInOrg(null, vdc.getId());
for (Resource vApp : Iterables.filter(VDC.getResourceEntities(), new Predicate<Resource>() {
for (Resource org1 : context.getApi().listOrgs()) {
Org org = client.getOrg(org1.getId());
for (Resource vdc : org.getVDCs()) {
VDC VDC = client.getVDCInOrg(org.getId(), vdc.getId());
for (Resource vApp : Iterables.filter(VDC.getResourceEntities(), new Predicate<Resource>() {
@Override
public boolean apply(Resource arg0) {
return VCloudMediaType.VAPP_XML.equals(arg0.getType());
@Override
public boolean apply(Resource arg0) {
return VCloudMediaType.VAPP_XML.equals(arg0.getType());
}
})) {
VApp response = client.getVAppInOrgAndVDC(org.getId(), vdc.getId(), vApp.getId());
assertNotNull(response);
assertNotNull(response.getId());
assertNotNull(response.getHref());
assertNotNull(response.getName());
assertEquals(response.getType(), "application/vnd.vmware.vcloud.vApp+xml");
assertNotNull(response.getIpAddress());
assertNotNull(response.getStatus());
assertNotNull(response.getOsDescripton());
assertNotNull(response.getOsType());
assertNotNull(response.getNetworkSection());
assertNotNull(response.getResourceAllocations());
// power state is the only thing that should change
assertEquals(client.getVAppInOrgAndVDC(org.getId(), vdc.getId(), response.getId(), withPowerState())
.toString().replaceFirst("status=[A-Z]+", ""), response.toString().replaceFirst(
"status=[A-Z]+", ""));
}
})) {
VApp response = client.getVAppInOrgAndVDC(org.getId(), vdc.getId(), vApp.getId());
assertNotNull(response);
assertNotNull(response.getId());
assertNotNull(response.getHref());
assertNotNull(response.getName());
assertEquals(response.getType(), "application/vnd.vmware.vcloud.vApp+xml");
assertNotNull(response.getIpAddress());
assertNotNull(response.getStatus());
assertNotNull(response.getOsDescripton());
assertNotNull(response.getOsType());
assertNotNull(response.getNetworkSection());
assertNotNull(response.getResourceAllocations());
// power state is the only thing that should change
assertEquals(client.getVAppInOrgAndVDC(null, vdc.getId(), response.getId(), withPowerState()).toString()
.replaceFirst("status=[A-Z]+", ""), response.toString().replaceFirst("status=[A-Z]+", ""));
}
}
}

View File

@ -49,25 +49,36 @@ public class VPDCErrorHandlerTest {
@Test
public void test400MakesIllegalArgumentException() {
assertCodeMakes("GET", URI.create("https://savvis.com/foo"), 400, "", "Bad Request",
IllegalArgumentException.class);
IllegalArgumentException.class);
}
@Test
public void test401MakesAuthorizationException() {
assertCodeMakes("GET", URI.create("https://savvis.com/foo"), 401, "", "Unauthorized",
AuthorizationException.class);
AuthorizationException.class);
}
@Test
public void test403MakesAuthorizationException() {
assertCodeMakes(
"GET",
URI.create("https://savvis.com/foo"),
403,
"HTTP/1.1 403 Forbidden",
"With the User/login credentials provided, no privilege exists to process the current request. Please contact Savvis administrator for further information",
AuthorizationException.class);
}
@Test
public void test404MakesResourceNotFoundException() {
assertCodeMakes("GET", URI.create("https://savvis.com/foo"), 404, "", "Not Found",
ResourceNotFoundException.class);
ResourceNotFoundException.class);
}
@Test
public void test405MakesIllegalArgumentException() {
assertCodeMakes("GET", URI.create("https://savvis.com/foo"), 405, "", "Method Not Allowed",
IllegalArgumentException.class);
IllegalArgumentException.class);
}
@Test
@ -76,19 +87,19 @@ public class VPDCErrorHandlerTest {
}
private void assertCodeMakes(String method, URI uri, int statusCode, String message, String content,
Class<? extends Exception> expected) {
Class<? extends Exception> expected) {
assertCodeMakes(method, uri, statusCode, message, "text/xml", content, expected);
}
private void assertCodeMakes(String method, URI uri, int statusCode, String message, String contentType,
String content, Class<? extends Exception> expected) {
String content, Class<? extends Exception> expected) {
VPDCErrorHandler function = Guice.createInjector().getInstance(VPDCErrorHandler.class);
HttpCommand command = createMock(HttpCommand.class);
HttpRequest request = new HttpRequest(method, uri);
HttpResponse response = new HttpResponse(statusCode, message, Payloads.newInputStreamPayload(Strings2
.toInputStream(content)));
.toInputStream(content)));
response.getPayload().getContentMetadata().setContentType(contentType);
expect(command.getCurrentRequest()).andReturn(request).atLeastOnce();