You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jclouds.apache.org by an...@apache.org on 2013/12/11 13:24:48 UTC

git commit: JCLOUDS-400: Allow the HeaderParam annotation to be used in a Caller.

Updated Branches:
  refs/heads/master 83e77d230 -> c40dc996d


JCLOUDS-400: Allow the HeaderParam annotation to be used in a Caller.

This allows jclouds to factor out common headers into the Caller so they don't
have to be repeated in the Callee.

The Produces/Consumes annotations (Content-Type/Accept headers) will also
propagate from the Caller to the Callee.


Project: http://git-wip-us.apache.org/repos/asf/jclouds/repo
Commit: http://git-wip-us.apache.org/repos/asf/jclouds/commit/c40dc996
Tree: http://git-wip-us.apache.org/repos/asf/jclouds/tree/c40dc996
Diff: http://git-wip-us.apache.org/repos/asf/jclouds/diff/c40dc996

Branch: refs/heads/master
Commit: c40dc996d96b05ce755f28728a4fb2bcd632b247
Parents: 83e77d2
Author: Everett Toews <ev...@rackspace.com>
Authored: Mon Dec 9 20:53:23 2013 -0600
Committer: Andrew Phillips <an...@apache.org>
Committed: Wed Dec 11 13:24:07 2013 +0100

----------------------------------------------------------------------
 .../rest/internal/RestAnnotationProcessor.java  |  12 +-
 .../internal/RestAnnotationProcessorTest.java   | 173 +++++++++++++++++++
 2 files changed, 183 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/jclouds/blob/c40dc996/core/src/main/java/org/jclouds/rest/internal/RestAnnotationProcessor.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/jclouds/rest/internal/RestAnnotationProcessor.java b/core/src/main/java/org/jclouds/rest/internal/RestAnnotationProcessor.java
index d48d876..9624c8f 100644
--- a/core/src/main/java/org/jclouds/rest/internal/RestAnnotationProcessor.java
+++ b/core/src/main/java/org/jclouds/rest/internal/RestAnnotationProcessor.java
@@ -234,9 +234,17 @@ public class RestAnnotationProcessor implements Function<Invocation, HttpRequest
          formParams.putAll(addFormParams(tokenValues, invocation));
       } else {
          formParams = addFormParams(tokenValues, invocation);
-      }      
+      }
+
       Multimap<String, Object> queryParams = addQueryParams(tokenValues, invocation);
-      Multimap<String, String> headers = buildHeaders(tokenValues, invocation);
+
+      Multimap<String, String> headers;
+      if (caller != null) {
+         headers = buildHeaders(tokenValues, caller);
+         headers.putAll(buildHeaders(tokenValues, invocation));
+      } else {
+         headers = buildHeaders(tokenValues, invocation);
+      }
 
       if (r != null)
          headers.putAll(r.getHeaders());

http://git-wip-us.apache.org/repos/asf/jclouds/blob/c40dc996/core/src/test/java/org/jclouds/rest/internal/RestAnnotationProcessorTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/jclouds/rest/internal/RestAnnotationProcessorTest.java b/core/src/test/java/org/jclouds/rest/internal/RestAnnotationProcessorTest.java
index 3506572..879bb3b 100644
--- a/core/src/test/java/org/jclouds/rest/internal/RestAnnotationProcessorTest.java
+++ b/core/src/test/java/org/jclouds/rest/internal/RestAnnotationProcessorTest.java
@@ -181,6 +181,22 @@ public class RestAnnotationProcessorTest extends BaseRestApiTest {
       @GET
       @Path("/{path}")
       ListenableFuture<Void> onePath(@PathParam("path") String path);
+
+      @POST
+      ListenableFuture<Void> testWithoutProducesAndConsumes();
+
+      @POST
+      @Produces(MediaType.APPLICATION_XML)
+      @Consumes(MediaType.APPLICATION_XML)
+      ListenableFuture<Void> testProducesAndConsumesOnMethod();
+   }
+
+   @Path("/client/{jclouds.api-version}")
+   @Produces(MediaType.APPLICATION_XML)
+   @Consumes(MediaType.APPLICATION_XML)
+   public interface AsyncCalleeWithProducesAndConsumesOnClass extends Closeable {
+      @POST
+      ListenableFuture<Void> testProducesAndConsumesOnClass();
    }
 
    @Path("/client/{jclouds.api-version}")
@@ -213,10 +229,28 @@ public class RestAnnotationProcessorTest extends BaseRestApiTest {
       @Delegate
       @Path("/testing/testing/{wibble}")
       Callee getCalleeWithPath(@EndpointParam URI endpoint, @PathParam("wibble") String wibble);
+
+      @Delegate
+      Callee getCalleeWithHeader(@EndpointParam URI endpoint, @HeaderParam("header") String header);
+
+      @Delegate
+      Callee getCalleeWithoutProducesAndConsumes();
+
+      @Delegate
+      Callee getCalleeWithProducesAndConsumesOnMethod();
+
+      @Delegate
+      CalleeWithProducesAndConsumesOnClass getCalleeWithProducesAndConsumesOnClass();
    }
 
    public interface Callee extends Closeable {
       void onePath(String path);
+      void testWithoutProducesAndConsumes();
+      void testProducesAndConsumesOnMethod();
+   }
+
+   public interface CalleeWithProducesAndConsumesOnClass extends Closeable {
+      void testProducesAndConsumesOnClass();
    }
 
    public interface Callee2 {
@@ -243,6 +277,24 @@ public class RestAnnotationProcessorTest extends BaseRestApiTest {
       @Delegate
       @Path("/testing/testing/{wibble}")
       AsyncCallee getCalleeWithPath(@EndpointParam URI endpoint, @PathParam("wibble") String wibble);
+
+      @Delegate
+      AsyncCallee getCalleeWithHeader(@EndpointParam URI endpoint, @HeaderParam("header") String header);
+
+      @Delegate
+      @Produces(MediaType.APPLICATION_JSON)
+      @Consumes(MediaType.APPLICATION_JSON)
+      AsyncCallee getCalleeWithoutProducesAndConsumes();
+
+      @Delegate
+      @Produces(MediaType.APPLICATION_JSON)
+      @Consumes(MediaType.APPLICATION_JSON)
+      AsyncCallee getCalleeWithProducesAndConsumesOnMethod();
+
+      @Delegate
+      @Produces(MediaType.APPLICATION_JSON)
+      @Consumes(MediaType.APPLICATION_JSON)
+      AsyncCalleeWithProducesAndConsumesOnClass getCalleeWithProducesAndConsumesOnClass();
    }
 
    public void testAsyncDelegateIsLazyLoadedAndRequestIncludesVersionAndPath() throws InterruptedException,
@@ -371,6 +423,127 @@ public class RestAnnotationProcessorTest extends BaseRestApiTest {
       assertEquals(child.getInstance(AsyncCaller.class).getURI(), URI.create("http://localhost:1111"));
    }
 
+   public void testAsyncDelegateWithHeaderParamIsLazyLoadedAndRequestIncludesEndpointVersionAndHeader()
+         throws InterruptedException, ExecutionException {
+      Injector child = injectorForCaller(new HttpCommandExecutorService() {
+
+         @Override
+         public ListenableFuture<HttpResponse> submit(HttpCommand command) {
+            return Futures.immediateFuture(invoke(command));
+         }
+
+         @Override
+         public HttpResponse invoke(HttpCommand command) {
+            assertEquals(command.getCurrentRequest().getFirstHeaderOrNull("header"), "theheaderparam");
+            return HttpResponse.builder().build();
+         }
+
+      });
+
+      try {
+         child.getInstance(AsyncCallee.class);
+         fail("Callee shouldn't be bound yet");
+      } catch (ConfigurationException e) {
+
+      }
+
+      child.getInstance(AsyncCaller.class).getCalleeWithHeader(URI.create("http://howdyboys"), "theheaderparam")
+            .onePath("foo").get();
+   }
+
+   public void testAsyncDelegateWithoutProducesAndConsumes()
+         throws InterruptedException, ExecutionException {
+      Injector child = injectorForCaller(new HttpCommandExecutorService() {
+
+         @Override
+         public ListenableFuture<HttpResponse> submit(HttpCommand command) {
+            return Futures.immediateFuture(invoke(command));
+         }
+
+         @Override
+         public HttpResponse invoke(HttpCommand command) {
+            assertEquals(
+                  command.getCurrentRequest().getPayload().getContentMetadata().getContentType(),
+                  MediaType.APPLICATION_JSON);
+            assertTrue(command.getCurrentRequest().getHeaders().get("Accept").contains(MediaType.APPLICATION_JSON));
+            return HttpResponse.builder().build();
+         }
+
+      });
+
+      try {
+         child.getInstance(AsyncCallee.class);
+         fail("Callee shouldn't be bound yet");
+      } catch (ConfigurationException e) {
+
+      }
+
+      child.getInstance(AsyncCaller.class).getCalleeWithoutProducesAndConsumes()
+            .testWithoutProducesAndConsumes().get();
+   }
+
+   public void testAsyncDelegateWithProducesAndConsumesOnMethodIsLazyLoaded()
+         throws InterruptedException, ExecutionException {
+      Injector child = injectorForCaller(new HttpCommandExecutorService() {
+
+         @Override
+         public ListenableFuture<HttpResponse> submit(HttpCommand command) {
+            return Futures.immediateFuture(invoke(command));
+         }
+
+         @Override
+         public HttpResponse invoke(HttpCommand command) {
+            assertEquals(
+                  command.getCurrentRequest().getPayload().getContentMetadata().getContentType(),
+                  MediaType.APPLICATION_XML);
+            assertTrue(command.getCurrentRequest().getHeaders().get("Accept").contains(MediaType.APPLICATION_XML));
+            return HttpResponse.builder().build();
+         }
+
+      });
+
+      try {
+         child.getInstance(AsyncCallee.class);
+         fail("Callee shouldn't be bound yet");
+      } catch (ConfigurationException e) {
+
+      }
+
+      child.getInstance(AsyncCaller.class).getCalleeWithProducesAndConsumesOnMethod()
+            .testProducesAndConsumesOnMethod().get();
+   }
+
+   public void testAsyncDelegateWithProducesAndConsumesOnClassIsLazyLoaded()
+         throws InterruptedException, ExecutionException {
+      Injector child = injectorForCaller(new HttpCommandExecutorService() {
+
+         @Override
+         public ListenableFuture<HttpResponse> submit(HttpCommand command) {
+            return Futures.immediateFuture(invoke(command));
+         }
+
+         @Override
+         public HttpResponse invoke(HttpCommand command) {
+            assertEquals(
+                  command.getCurrentRequest().getPayload().getContentMetadata().getContentType(),
+                  MediaType.APPLICATION_XML);
+            assertTrue(command.getCurrentRequest().getHeaders().get("Accept").contains(MediaType.APPLICATION_XML));
+            return HttpResponse.builder().build();
+         }
+
+      });
+
+      try {
+         child.getInstance(AsyncCallee.class);
+         fail("Callee shouldn't be bound yet");
+      } catch (ConfigurationException e) {
+
+      }
+
+      child.getInstance(AsyncCaller.class).getCalleeWithProducesAndConsumesOnClass()
+            .testProducesAndConsumesOnClass().get();
+   }
+
    public void testAsyncDelegateIsLazyLoadedAndRequestIncludesEndpointVersionAndPathOptionalPresent()
          throws InterruptedException, ExecutionException {
       Injector child = injectorForCaller(new HttpCommandExecutorService() {