Repository: jclouds
Updated Branches:
  refs/heads/master f832ad00a -> 07e64a2d0


Allow to globally configure the 'Connection: close' header


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

Branch: refs/heads/master
Commit: 07e64a2d0743b8925887ac802cec648befdc112f
Parents: f832ad0
Author: Ignasi Barrera <[email protected]>
Authored: Fri Oct 2 15:15:41 2015 +0200
Committer: Ignasi Barrera <[email protected]>
Committed: Fri Oct 2 15:44:24 2015 +0200

----------------------------------------------------------------------
 core/src/main/java/org/jclouds/Constants.java   |  6 ++++
 .../jclouds/apis/internal/BaseApiMetadata.java  |  2 ++
 .../http/filters/ConnectionCloseHeader.java     | 33 +++++++++++++++++
 .../rest/internal/RestAnnotationProcessor.java  | 10 +++++-
 .../http/filters/ConnectionCloseHeaderTest.java | 38 ++++++++++++++++++++
 .../internal/RestAnnotationProcessorTest.java   | 29 +++++++++++++++
 6 files changed, 117 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/jclouds/blob/07e64a2d/core/src/main/java/org/jclouds/Constants.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/jclouds/Constants.java 
b/core/src/main/java/org/jclouds/Constants.java
index a658026..115edf1 100644
--- a/core/src/main/java/org/jclouds/Constants.java
+++ b/core/src/main/java/org/jclouds/Constants.java
@@ -308,6 +308,12 @@ public final class Constants {
    public static final String PROPERTY_STRIP_EXPECT_HEADER = 
"jclouds.strip-expect-header";
 
    /**
+    * When true, add the Connection: close header. Useful when interacting with
+    * providers that don't properly support persistent connections. Defaults 
to false.
+    */
+   public static final String PROPERTY_CONNECTION_CLOSE_HEADER = 
"jclouds.connection-close-header";
+
+   /**
     * The maximum number of blob deletes happening in parallel at any point in 
time.
     */
    public static final String PROPERTY_MAX_PARALLEL_DELETES = 
"jclouds.max-parallel-deletes";

http://git-wip-us.apache.org/repos/asf/jclouds/blob/07e64a2d/core/src/main/java/org/jclouds/apis/internal/BaseApiMetadata.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/jclouds/apis/internal/BaseApiMetadata.java 
b/core/src/main/java/org/jclouds/apis/internal/BaseApiMetadata.java
index 7b5ff35..1cfbb6f 100644
--- a/core/src/main/java/org/jclouds/apis/internal/BaseApiMetadata.java
+++ b/core/src/main/java/org/jclouds/apis/internal/BaseApiMetadata.java
@@ -18,6 +18,7 @@ package org.jclouds.apis.internal;
 
 import static com.google.common.base.Objects.equal;
 import static com.google.common.base.Preconditions.checkNotNull;
+import static org.jclouds.Constants.PROPERTY_CONNECTION_CLOSE_HEADER;
 import static org.jclouds.Constants.PROPERTY_CONNECTION_TIMEOUT;
 import static org.jclouds.Constants.PROPERTY_ISO3166_CODES;
 import static org.jclouds.Constants.PROPERTY_MAX_CONNECTIONS_PER_CONTEXT;
@@ -73,6 +74,7 @@ public abstract class BaseApiMetadata implements ApiMetadata {
       props.setProperty(PROPERTY_SESSION_INTERVAL, 60 + "");
       props.setProperty(PROPERTY_PRETTY_PRINT_PAYLOADS, "true");
       props.setProperty(PROPERTY_STRIP_EXPECT_HEADER, "false");
+      props.setProperty(PROPERTY_CONNECTION_CLOSE_HEADER, "false");
 
       // By default, we allow maximum parallel deletes to be equal to the 
number
       // of user threads since one thread is used to delete on blob.

http://git-wip-us.apache.org/repos/asf/jclouds/blob/07e64a2d/core/src/main/java/org/jclouds/http/filters/ConnectionCloseHeader.java
----------------------------------------------------------------------
diff --git 
a/core/src/main/java/org/jclouds/http/filters/ConnectionCloseHeader.java 
b/core/src/main/java/org/jclouds/http/filters/ConnectionCloseHeader.java
new file mode 100644
index 0000000..ba2b55c
--- /dev/null
+++ b/core/src/main/java/org/jclouds/http/filters/ConnectionCloseHeader.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.jclouds.http.filters;
+
+import org.jclouds.http.HttpException;
+import org.jclouds.http.HttpRequest;
+import org.jclouds.http.HttpRequestFilter;
+
+import com.google.common.net.HttpHeaders;
+import com.google.inject.Singleton;
+
+@Singleton
+public class ConnectionCloseHeader implements HttpRequestFilter {
+   @Override
+   public HttpRequest filter(HttpRequest request) throws HttpException {
+      return request.toBuilder().addHeader(HttpHeaders.CONNECTION, 
"close").build();
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/07e64a2d/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 74b1ac1..f6ebc8c 100644
--- a/core/src/main/java/org/jclouds/rest/internal/RestAnnotationProcessor.java
+++ b/core/src/main/java/org/jclouds/rest/internal/RestAnnotationProcessor.java
@@ -51,6 +51,7 @@ import java.util.Map;
 import java.util.Map.Entry;
 import java.util.NoSuchElementException;
 import java.util.Set;
+
 import javax.annotation.Resource;
 import javax.inject.Named;
 import javax.ws.rs.FormParam;
@@ -65,6 +66,7 @@ import org.jclouds.http.HttpRequest;
 import org.jclouds.http.HttpRequestFilter;
 import org.jclouds.http.HttpUtils;
 import org.jclouds.http.Uris.UriBuilder;
+import org.jclouds.http.filters.ConnectionCloseHeader;
 import org.jclouds.http.filters.StripExpectHeader;
 import org.jclouds.http.options.HttpRequestOptions;
 import org.jclouds.io.ContentMetadataCodec;
@@ -147,12 +149,14 @@ public class RestAnnotationProcessor implements 
Function<Invocation, HttpRequest
    private final GetAcceptHeaders getAcceptHeaders;
    private final Invocation caller;
    private final boolean stripExpectHeader;
+   private final boolean connectionCloseHeader;
 
    @Inject
    private RestAnnotationProcessor(Injector injector, @ApiVersion String 
apiVersion, @BuildVersion String buildVersion,
          HttpUtils utils, ContentMetadataCodec contentMetadataCodec, 
InputParamValidator inputParamValidator,
          GetAcceptHeaders getAcceptHeaders, @Nullable @Named("caller") 
Invocation caller,
-         @Named(Constants.PROPERTY_STRIP_EXPECT_HEADER) boolean 
stripExpectHeader) {
+         @Named(Constants.PROPERTY_STRIP_EXPECT_HEADER) boolean 
stripExpectHeader,
+         @Named(Constants.PROPERTY_CONNECTION_CLOSE_HEADER) boolean 
connectionCloseHeader) {
       this.injector = injector;
       this.utils = utils;
       this.contentMetadataCodec = contentMetadataCodec;
@@ -162,6 +166,7 @@ public class RestAnnotationProcessor implements 
Function<Invocation, HttpRequest
       this.getAcceptHeaders = getAcceptHeaders;
       this.caller = caller;
       this.stripExpectHeader = stripExpectHeader;
+      this.connectionCloseHeader = connectionCloseHeader;
    }
 
    /**
@@ -211,6 +216,9 @@ public class RestAnnotationProcessor implements 
Function<Invocation, HttpRequest
       if (stripExpectHeader) {
          requestBuilder.filter(new StripExpectHeader());
       }
+      if (connectionCloseHeader) {
+         requestBuilder.filter(new ConnectionCloseHeader());
+      }
 
       Multimap<String, Object> tokenValues = LinkedHashMultimap.create();
 

http://git-wip-us.apache.org/repos/asf/jclouds/blob/07e64a2d/core/src/test/java/org/jclouds/http/filters/ConnectionCloseHeaderTest.java
----------------------------------------------------------------------
diff --git 
a/core/src/test/java/org/jclouds/http/filters/ConnectionCloseHeaderTest.java 
b/core/src/test/java/org/jclouds/http/filters/ConnectionCloseHeaderTest.java
new file mode 100644
index 0000000..342b14c
--- /dev/null
+++ b/core/src/test/java/org/jclouds/http/filters/ConnectionCloseHeaderTest.java
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.jclouds.http.filters;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+
+import org.jclouds.http.HttpRequest;
+import org.testng.annotations.Test;
+
+import com.google.common.net.HttpHeaders;
+
+@Test(groups = "unit")
+public class ConnectionCloseHeaderTest {
+   public void testConnectionHeaderIsAdded() {
+      HttpRequest request = 
HttpRequest.builder().method("POST").endpoint("http://localhost";).build();
+      request = new ConnectionCloseHeader().filter(request);
+
+      assertTrue(request.getHeaders().containsKey(HttpHeaders.CONNECTION));
+      assertEquals(request.getHeaders().get(HttpHeaders.CONNECTION).size(), 1);
+      
assertEquals(request.getHeaders().get(HttpHeaders.CONNECTION).iterator().next(),
 "close");
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/07e64a2d/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 40e8f83..7e43551 100644
--- 
a/core/src/test/java/org/jclouds/rest/internal/RestAnnotationProcessorTest.java
+++ 
b/core/src/test/java/org/jclouds/rest/internal/RestAnnotationProcessorTest.java
@@ -78,6 +78,7 @@ import org.jclouds.http.HttpRequest;
 import org.jclouds.http.HttpRequestFilter;
 import org.jclouds.http.HttpResponse;
 import org.jclouds.http.IOExceptionRetryHandler;
+import org.jclouds.http.filters.ConnectionCloseHeader;
 import org.jclouds.http.filters.StripExpectHeader;
 import org.jclouds.http.functions.ParseFirstJsonValueNamed;
 import org.jclouds.http.functions.ParseJson;
@@ -1440,6 +1441,34 @@ public class RestAnnotationProcessorTest extends 
BaseRestApiTest {
       assertEquals(request.getFilters().get(1).getClass(), 
StripExpectHeader.class);
    }
 
+   @Test
+   public void testRequestFilterAddConnection() {
+      // First, verify that by default, the StripExpectHeader filter is not 
applied
+      Invokable<?, ?> method = method(TestRequestFilter.class, "post");
+      Invocation invocation = Invocation.create(method,
+         
ImmutableList.<Object>of(HttpRequest.builder().method("POST").endpoint("http://localhost";).build()));
+      GeneratedHttpRequest request = processor.apply(invocation);
+      assertEquals(request.getFilters().size(), 1);
+      assertEquals(request.getFilters().get(0).getClass(), 
TestRequestFilter1.class);
+
+      // Now let's create a new injector with the property set. Use that to 
create the annotation processor.
+      Properties overrides = new Properties();
+      overrides.setProperty(Constants.PROPERTY_CONNECTION_CLOSE_HEADER, 
"true");
+      Injector injector = 
ContextBuilder.newBuilder(forApiOnEndpoint(Callee.class, 
"http://localhost:9999";))
+         .modules(ImmutableSet.<Module> of(new MockModule(), new 
NullLoggingModule(), new AbstractModule() {
+            protected void configure() {
+               bind(new TypeLiteral<Supplier<URI>>() {
+               }).annotatedWith(Localhost2.class).toInstance(
+                  Suppliers.ofInstance(URI.create("http://localhost:1111";)));
+            }}))
+         .overrides(overrides).buildInjector();
+      RestAnnotationProcessor newProcessor = 
injector.getInstance(RestAnnotationProcessor.class);
+      // Verify that this time the filter is indeed applied as expected.
+      request = newProcessor.apply(invocation);
+      assertEquals(request.getFilters().size(), 2);
+      assertEquals(request.getFilters().get(1).getClass(), 
ConnectionCloseHeader.class);
+   }
+
    public class TestEncoding {
       @GET
       @Path("/{path1}/{path2}")

Reply via email to