This is an automated email from the ASF dual-hosted git repository.

mibo pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/olingo-odata4.git


The following commit(s) were added to refs/heads/master by this push:
     new 98d445a  [OLINGO-1411] Better header parsing
98d445a is described below

commit 98d445a87447a5424cf5405a559708323f94d94f
Author: Artem Smotrakov <[email protected]>
AuthorDate: Mon Nov 25 16:45:35 2019 +0100

    [OLINGO-1411] Better header parsing
    
    * [OLINGO-1411] Better header parsing
---
 .../request/AsyncBatchRequestWrapperImpl.java      |  16 +--
 .../request/AsyncRequestWrapperImpl.java           |  26 ++++-
 .../request/AsyncRequestWrapperTest.java           | 124 ++++++++++++++++++---
 3 files changed, 138 insertions(+), 28 deletions(-)

diff --git 
a/lib/client-core/src/main/java/org/apache/olingo/client/core/communication/request/AsyncBatchRequestWrapperImpl.java
 
b/lib/client-core/src/main/java/org/apache/olingo/client/core/communication/request/AsyncBatchRequestWrapperImpl.java
index d4821b5..c99e583 100644
--- 
a/lib/client-core/src/main/java/org/apache/olingo/client/core/communication/request/AsyncBatchRequestWrapperImpl.java
+++ 
b/lib/client-core/src/main/java/org/apache/olingo/client/core/communication/request/AsyncBatchRequestWrapperImpl.java
@@ -1,18 +1,18 @@
 /*
  * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
+ * or more contributor license agreements. See the NOTICE file
  * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
+ * 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
+ * with the License. You may obtain a copy of the License at
  *
- *   http://www.apache.org/licenses/LICENSE-2.0
+ * 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
+ * KIND, either express or implied. See the License for the
  * specific language governing permissions and limitations
  * under the License.
  */
@@ -34,7 +34,7 @@ import 
org.apache.olingo.client.api.communication.response.ODataBatchResponse;
 import org.apache.olingo.commons.api.http.HttpHeader;
 
 public class AsyncBatchRequestWrapperImpl extends 
AsyncRequestWrapperImpl<ODataBatchResponse>
-        implements AsyncBatchRequestWrapper {
+    implements AsyncBatchRequestWrapper {
 
   private BatchManager batchManager;
 
@@ -73,7 +73,7 @@ public class AsyncBatchRequestWrapperImpl extends 
AsyncRequestWrapperImpl<ODataB
   }
 
   public class AsyncResponseWrapperImpl
-          extends 
AsyncRequestWrapperImpl<ODataBatchResponse>.AsyncResponseWrapperImpl {
+      extends 
AsyncRequestWrapperImpl<ODataBatchResponse>.AsyncResponseWrapperImpl {
 
     /**
      * Constructor.
@@ -100,7 +100,7 @@ public class AsyncBatchRequestWrapperImpl extends 
AsyncRequestWrapperImpl<ODataB
 
       headers = res.getHeader(HttpHeader.RETRY_AFTER);
       if (headers != null && !headers.isEmpty()) {
-        this.retryAfter = Integer.parseInt(headers.iterator().next());
+        this.retryAfter = parseReplyAfter(headers.iterator().next());
       }
 
       headers = res.getHeader(HttpHeader.PREFERENCE_APPLIED);
diff --git 
a/lib/client-core/src/main/java/org/apache/olingo/client/core/communication/request/AsyncRequestWrapperImpl.java
 
b/lib/client-core/src/main/java/org/apache/olingo/client/core/communication/request/AsyncRequestWrapperImpl.java
index b691c52..c82f2cf 100644
--- 
a/lib/client-core/src/main/java/org/apache/olingo/client/core/communication/request/AsyncRequestWrapperImpl.java
+++ 
b/lib/client-core/src/main/java/org/apache/olingo/client/core/communication/request/AsyncRequestWrapperImpl.java
@@ -141,11 +141,14 @@ public class AsyncRequestWrapperImpl<R extends 
ODataResponse> extends AbstractRe
 
   public class AsyncResponseWrapperImpl implements AsyncResponseWrapper<R> {
 
+    static final int DEFAULT_RETRY_AFTER = 5;
+    static final int MAX_RETRY_AFTER = 10;
+
     protected URI location = null;
 
     protected R response = null;
 
-    protected int retryAfter = 5;
+    protected int retryAfter = DEFAULT_RETRY_AFTER;
 
     protected boolean preferenceApplied = false;
 
@@ -196,12 +199,12 @@ public class AsyncRequestWrapperImpl<R extends 
ODataResponse> extends AbstractRe
 
           final Header[] headers = res.getHeaders(HttpHeader.RETRY_AFTER);
           if (ArrayUtils.isNotEmpty(headers)) {
-            this.retryAfter = Integer.parseInt(headers[0].getValue());
+            this.retryAfter = parseReplyAfter(headers[0].getValue());
           }
 
           try {
             // wait for retry-after
-            Thread.sleep((long)retryAfter * 1000);
+            Thread.sleep((long) retryAfter * 1000);
           } catch (InterruptedException ignore) {
             // ignore
           }
@@ -219,6 +222,21 @@ public class AsyncRequestWrapperImpl<R extends 
ODataResponse> extends AbstractRe
       return response;
     }
 
+    int parseReplyAfter(String value) {
+      if (value == null || value.isEmpty()) {
+        return DEFAULT_RETRY_AFTER;
+
+      try {
+        int n = Integer.parseInt(value);
+        if (n < 0) {
+          return DEFAULT_RETRY_AFTER;
+        }
+        return Math.min(n, MAX_RETRY_AFTER);
+      } catch (NumberFormatException e) {
+        return DEFAULT_RETRY_AFTER;
+      }
+    }
+
     @Override
     public ODataDeleteResponse delete() {
       final ODataDeleteRequest deleteRequest = 
odataClient.getCUDRequestFactory().getDeleteRequest(location);
@@ -264,7 +282,7 @@ public class AsyncRequestWrapperImpl<R extends 
ODataResponse> extends AbstractRe
 
       headers = res.getHeaders(HttpHeader.RETRY_AFTER);
       if (ArrayUtils.isNotEmpty(headers)) {
-        this.retryAfter = Integer.parseInt(headers[0].getValue());
+        this.retryAfter = parseReplyAfter(headers[0].getValue());
       }
 
       headers = res.getHeaders(HttpHeader.PREFERENCE_APPLIED);
diff --git 
a/lib/client-core/src/test/java/org/apache/olingo/client/core/communication/request/AsyncRequestWrapperTest.java
 
b/lib/client-core/src/test/java/org/apache/olingo/client/core/communication/request/AsyncRequestWrapperTest.java
index f61ecf3..43b0456 100644
--- 
a/lib/client-core/src/test/java/org/apache/olingo/client/core/communication/request/AsyncRequestWrapperTest.java
+++ 
b/lib/client-core/src/test/java/org/apache/olingo/client/core/communication/request/AsyncRequestWrapperTest.java
@@ -1,36 +1,55 @@
 /*
  * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
+ * or more contributor license agreements. See the NOTICE file
  * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
+ * 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
+ * with the License. You may obtain a copy of the License at
  *
- *   http://www.apache.org/licenses/LICENSE-2.0
+ * 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
+ * KIND, either express or implied. See the License for the
  * specific language governing permissions and limitations
  * under the License.
  */
 package org.apache.olingo.client.core.communication.request;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
 import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
 
+import java.io.IOException;
 import java.net.URI;
 import java.net.URISyntaxException;
 
+import org.apache.http.HttpResponse;
+import org.apache.http.HttpResponseFactory;
+import org.apache.http.HttpVersion;
+import org.apache.http.client.HttpClient;
+import org.apache.http.client.methods.HttpUriRequest;
+import org.apache.http.impl.DefaultHttpResponseFactory;
+import org.apache.http.message.BasicStatusLine;
+import org.apache.olingo.client.api.Configuration;
 import org.apache.olingo.client.api.ODataClient;
 import 
org.apache.olingo.client.api.communication.request.ODataBatchableRequest;
+import 
org.apache.olingo.client.api.communication.response.AsyncResponseWrapper;
+import org.apache.olingo.client.api.communication.response.ODataResponse;
 import org.apache.olingo.client.api.domain.ClientInvokeResult;
+import org.apache.olingo.client.api.http.HttpClientFactory;
+import org.apache.olingo.client.api.http.HttpUriRequestFactory;
 import org.apache.olingo.client.core.ODataClientFactory;
 import 
org.apache.olingo.client.core.communication.request.AsyncRequestWrapperImpl.AsyncResponseWrapperImpl;
 import 
org.apache.olingo.client.core.communication.request.batch.ODataBatchRequestImpl;
 import 
org.apache.olingo.client.core.communication.request.invoke.ODataInvokeRequestImpl;
+import org.apache.olingo.commons.api.http.HttpHeader;
 import org.apache.olingo.commons.api.http.HttpMethod;
 import org.junit.Test;
 
@@ -41,25 +60,25 @@ public class AsyncRequestWrapperTest {
 
     ODataClient client = ODataClientFactory.getClient();
     URI uri = new URI("localhost:8080");
-    AsyncBatchRequestWrapperImpl req = new 
AsyncBatchRequestWrapperImpl(client, 
+    AsyncBatchRequestWrapperImpl req = new AsyncBatchRequestWrapperImpl(client,
         client.getBatchRequestFactory().getBatchRequest("root"));
     assertNotNull(req.addChangeset());
     ODataBatchableRequest request = new 
ODataInvokeRequestImpl<ClientInvokeResult>(
         client, ClientInvokeResult.class, HttpMethod.GET, uri);
-    req.addRetrieve(request );
+    req.addRetrieve(request);
     req.addOutsideUpdate(request);
     
assertNotNull(client.getAsyncRequestFactory().getAsyncRequestWrapper(request));
     ODataBatchRequestImpl batchRequest = new ODataBatchRequestImpl(client, 
uri);
-    
assertNotNull(client.getAsyncRequestFactory().getAsyncBatchRequestWrapper(batchRequest
 ));
+    
assertNotNull(client.getAsyncRequestFactory().getAsyncBatchRequestWrapper(batchRequest));
     assertNotNull(req.wait(10));
   }
-  
+
   @Test
   public void testReq() throws URISyntaxException {
 
     ODataClient client = ODataClientFactory.getClient();
     URI uri = new URI("localhost:8080");
-    AsyncRequestWrapperImpl req = new AsyncRequestWrapperImpl(client, 
+    AsyncRequestWrapperImpl req = new AsyncRequestWrapperImpl(client,
         client.getBatchRequestFactory().getBatchRequest("root"));
     assertNotNull(req);
     ODataBatchableRequest request = new 
ODataInvokeRequestImpl<ClientInvokeResult>(
@@ -70,20 +89,93 @@ public class AsyncRequestWrapperTest {
     AsyncResponseWrapperImpl res = req.new AsyncResponseWrapperImpl();
     res.forceNextMonitorCheck(uri);
   }
-  
+
+  private AsyncRequestWrapperImpl 
createAsyncRequestWrapperImplWithRetryAfter(int retryAfter)
+      throws IOException {
+
+    HttpClient httpClient = mock(HttpClient.class);
+    ODataClient oDataClient = mock(ODataClient.class);
+    Configuration configuration = mock(Configuration.class);
+    HttpClientFactory httpClientFactory = mock(HttpClientFactory.class);
+    HttpUriRequestFactory httpUriRequestFactory = 
mock(HttpUriRequestFactory.class);
+    HttpUriRequest httpUriRequest = mock(HttpUriRequest.class);
+
+    when(oDataClient.getConfiguration()).thenReturn(configuration);
+    when(configuration.getHttpClientFactory()).thenReturn(httpClientFactory);
+    
when(configuration.getHttpUriRequestFactory()).thenReturn(httpUriRequestFactory);
+    when(httpClientFactory.create(any(), any())).thenReturn(httpClient);
+    when(httpUriRequestFactory.create(any(), 
any())).thenReturn(httpUriRequest);
+
+    HttpResponseFactory factory = new DefaultHttpResponseFactory();
+    HttpResponse firstResponse = factory.newHttpResponse(
+        new BasicStatusLine(HttpVersion.HTTP_1_1, 202, null), null);
+    firstResponse.addHeader(HttpHeader.LOCATION, "http://localhost/monitor";);
+    firstResponse.addHeader(HttpHeader.RETRY_AFTER, 
String.valueOf(retryAfter));
+    
when(httpClient.execute(any(HttpUriRequest.class))).thenReturn(firstResponse);
+
+    AbstractODataRequest oDataRequest = mock(AbstractODataRequest.class);
+    ODataResponse oDataResponse = mock(ODataResponse.class);
+    when(oDataRequest.getResponseTemplate()).thenReturn(oDataResponse);
+    
when(oDataResponse.initFromHttpResponse(any(HttpResponse.class))).thenReturn(null);
+
+    return new AsyncRequestWrapperImpl(oDataClient, oDataRequest);
+  }
+
   @Test
-  public void testWrapper(){
+  public void testTooBigRetryAfter() throws IOException {
+
+    AsyncRequestWrapperImpl req = 
createAsyncRequestWrapperImplWithRetryAfter(Integer.MAX_VALUE);
+    AsyncResponseWrapper wrappedResponse = req.execute();
+    assertTrue(wrappedResponse instanceof AsyncResponseWrapperImpl);
+    AsyncResponseWrapperImpl wrappedResponseImpl = (AsyncResponseWrapperImpl) 
wrappedResponse;
+    assertEquals(AsyncResponseWrapperImpl.MAX_RETRY_AFTER, 
wrappedResponseImpl.retryAfter);
+  }
+
+  @Test
+  public void testZeroRetryAfter() throws IOException {
+
+    AsyncRequestWrapperImpl req = 
createAsyncRequestWrapperImplWithRetryAfter(0);
+    AsyncResponseWrapper wrappedResponse = req.execute();
+    assertTrue(wrappedResponse instanceof AsyncResponseWrapperImpl);
+    AsyncResponseWrapperImpl wrappedResponseImpl = (AsyncResponseWrapperImpl) 
wrappedResponse;
+    assertEquals(0, wrappedResponseImpl.retryAfter);
+  }
+
+  @Test
+  public void testNegativeRetryAfter() throws IOException {
+
+    AsyncRequestWrapperImpl req = 
createAsyncRequestWrapperImplWithRetryAfter(-1);
+    AsyncResponseWrapper wrappedResponse = req.execute();
+    assertTrue(wrappedResponse instanceof AsyncResponseWrapperImpl);
+    AsyncResponseWrapperImpl wrappedResponseImpl = (AsyncResponseWrapperImpl) 
wrappedResponse;
+    assertEquals(AsyncResponseWrapperImpl.DEFAULT_RETRY_AFTER, 
wrappedResponseImpl.retryAfter);
+  }
+
+  @Test
+  public void testRetryAfter() throws IOException {
+
+    int retryAfter = 7;
+    assertNotEquals(retryAfter, AsyncResponseWrapperImpl.DEFAULT_RETRY_AFTER);
+    AsyncRequestWrapperImpl req = 
createAsyncRequestWrapperImplWithRetryAfter(retryAfter);
+    AsyncResponseWrapper wrappedResponse = req.execute();
+    assertTrue(wrappedResponse instanceof AsyncResponseWrapperImpl);
+    AsyncResponseWrapperImpl wrappedResponseImpl = (AsyncResponseWrapperImpl) 
wrappedResponse;
+    assertEquals(retryAfter, wrappedResponseImpl.retryAfter);
+  }
+
+  @Test
+  public void testWrapper() {
 
     Wrapper wrap = new Wrapper();
     wrap.setWrapped("test");
     assertEquals("test", wrap.getWrapped());
   }
-  
+
   @Test
-  public void testException(){
+  public void testException() {
 
-    AsyncRequestException  ex = new AsyncRequestException ("Exception");
+    AsyncRequestException ex = new AsyncRequestException("Exception");
     assertEquals("Exception", ex.getMessage());
   }
-  
+
 }

Reply via email to