Handled redirects.

Change-Id: I8fda1cf8c967c1e8c62287c60eebd4656ced9d0f
diff --git a/pom.xml b/pom.xml
index 1027510..d49199c 100644
--- a/pom.xml
+++ b/pom.xml
@@ -4,7 +4,7 @@
 
 	<groupId>de.mannheim.ids</groupId>
 	<artifactId>KorapSRU</artifactId>
-	<version>1.0.2-SNAPSHOT</version>
+	<version>1.0.3-SNAPSHOT</version>
 	<packaging>war</packaging>
 
 	<name>KorapSRU</name>
@@ -61,17 +61,17 @@
 		<dependency>
 			<groupId>org.apache.httpcomponents</groupId>
 			<artifactId>httpclient</artifactId>
-			<version>4.3.3</version>
+			<version>4.5.6</version>
 		</dependency>
 		<dependency>
 			<groupId>com.fasterxml.jackson.core</groupId>
 			<artifactId>jackson-databind</artifactId>
-			<version>2.7.1</version>
+			<version>2.9.7</version>
 		</dependency>
 		<dependency>
 			<groupId>org.slf4j</groupId>
 			<artifactId>slf4j-simple</artifactId>
-			<version>1.7.6</version>
+			<version>1.7.25</version>
 		</dependency>
 		<dependency>
 			<groupId>org.apache.directory.studio</groupId>
diff --git a/src/main/java/de/ids_mannheim/korap/sru/KorapClient.java b/src/main/java/de/ids_mannheim/korap/sru/KorapClient.java
index 5bb1776..01c3b2b 100644
--- a/src/main/java/de/ids_mannheim/korap/sru/KorapClient.java
+++ b/src/main/java/de/ids_mannheim/korap/sru/KorapClient.java
@@ -11,12 +11,14 @@
 
 import org.apache.http.HttpStatus;
 import org.apache.http.NameValuePair;
+import org.apache.http.client.ClientProtocolException;
 import org.apache.http.client.HttpResponseException;
 import org.apache.http.client.methods.CloseableHttpResponse;
 import org.apache.http.client.methods.HttpGet;
 import org.apache.http.client.methods.HttpUriRequest;
 import org.apache.http.client.utils.URIBuilder;
 import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClientBuilder;
 import org.apache.http.impl.client.HttpClients;
 import org.apache.http.message.BasicNameValuePair;
 import org.slf4j.Logger;
@@ -27,6 +29,8 @@
 import com.fasterxml.jackson.databind.JsonNode;
 import com.fasterxml.jackson.databind.ObjectMapper;
 
+import de.ids_mannheim.korap.util.RedirectStrategy;
+
 /**
  * Client to KorAP public services supporting calls to the resource,
  * search and matchInfo APIs.
@@ -51,8 +55,8 @@
      * Constructs a KorapClient with the given number of records per
      * page and the maximum number of records.
      * 
-     * @param serviceUri 
-     *            KorAP service URI          
+     * @param serviceUri
+     *            KorAP service URI
      * @param numOfRecords
      *            the number of records per page
      * @param maxRecords
@@ -65,7 +69,6 @@
         this.serviceUri = serviceUri;
     }
 
-
     /**
      * Gets information about available resources to search through
      * the KorAP public services.
@@ -118,7 +121,6 @@
         return resources;
     }
 
-
     /**
      * Sends the given query to KorAP search API and creates a
      * KorapResult from the response.
@@ -166,18 +168,10 @@
             throw new IOException("Failed creating http request.");
         }
 
-        CloseableHttpClient client = HttpClients.createDefault();
         CloseableHttpResponse response = null;
         KorapResult result = null;
         try {
-            response = client.execute(httpRequest);
-
-            int statusCode = response.getStatusLine().getStatusCode();
-            if (statusCode != HttpStatus.SC_OK) {
-                logger.warn("Error response code: " + statusCode);
-                parseError(response);
-            }
-
+            response = sendRequest(httpRequest);
             BufferedInputStream jsonStream =
                     new BufferedInputStream(response.getEntity().getContent());
             try {
@@ -200,6 +194,19 @@
         return result;
     }
 
+    private CloseableHttpResponse sendRequest (HttpUriRequest httpRequest)
+            throws ClientProtocolException, IOException {
+        CloseableHttpClient client = HttpClientBuilder.create()
+                .setRedirectStrategy(new RedirectStrategy()).build();
+        CloseableHttpResponse response = client.execute(httpRequest);
+
+        int statusCode = response.getStatusLine().getStatusCode();
+        if (statusCode != HttpStatus.SC_OK) {
+            logger.warn("Error response code: " + statusCode);
+            parseError(response);
+        }
+        return response;
+    }
 
     /**
      * Parses the error message from Kustvakt (probably an old
@@ -236,7 +243,6 @@
                 errorItems[1]);
     }
 
-
     /**
      * Builds a search retrieve GET request for the given parameters.
      * 
@@ -285,7 +291,6 @@
         return request;
     }
 
-
     /**
      * Sends a request to the MatchInfo API to get the annotations of
      * a particular match identified with corpus/resource id, document
@@ -305,8 +310,8 @@
      * @throws IOException
      * @throws URISyntaxException
      */
-    public String retrieveAnnotations (String resourceId,
-            String documentId, String textId, String matchId, String foundry)
+    public String retrieveAnnotations (String resourceId, String documentId,
+            String textId, String matchId, String foundry)
             throws IOException, URISyntaxException {
 
         if (resourceId == null) {
@@ -337,22 +342,14 @@
             foundry = DEFAULT_FOUNDRY;
         }
 
-        HttpUriRequest httpRequest;
-        httpRequest = createMatchInfoRequest(resourceId, documentId, textId,
-                matchId, foundry);
+        HttpUriRequest httpRequest = createMatchInfoRequest(resourceId,
+                documentId, textId, matchId, foundry);
 
         String annotationSnippet = null;
 
-        CloseableHttpClient client = HttpClients.createDefault();
         CloseableHttpResponse response = null;
         try {
-            response = client.execute(httpRequest);
-
-            int statusCode = response.getStatusLine().getStatusCode();
-            if (statusCode != HttpStatus.SC_OK) {
-                logger.warn("Error response code: " + statusCode);
-                parseError(response);
-            }
+            response = sendRequest(httpRequest);
 
             BufferedInputStream jsonStream =
                     new BufferedInputStream(response.getEntity().getContent());
@@ -375,7 +372,6 @@
         return annotationSnippet;
     }
 
-
     /**
      * Builds a request URL to send to the KorAP MatchInfo service.
      * 
diff --git a/src/main/java/de/ids_mannheim/korap/util/RedirectStrategy.java b/src/main/java/de/ids_mannheim/korap/util/RedirectStrategy.java
new file mode 100644
index 0000000..30fc19f
--- /dev/null
+++ b/src/main/java/de/ids_mannheim/korap/util/RedirectStrategy.java
@@ -0,0 +1,68 @@
+package de.ids_mannheim.korap.util;
+
+import java.net.URI;
+
+import org.apache.http.Header;
+import org.apache.http.HttpRequest;
+import org.apache.http.HttpResponse;
+import org.apache.http.HttpStatus;
+import org.apache.http.ProtocolException;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.client.methods.HttpHead;
+import org.apache.http.client.methods.HttpUriRequest;
+import org.apache.http.client.methods.RequestBuilder;
+import org.apache.http.impl.client.LaxRedirectStrategy;
+import org.apache.http.protocol.HttpContext;
+import org.apache.http.util.Args;
+
+public class RedirectStrategy extends LaxRedirectStrategy {
+
+    @Override
+    public boolean isRedirected (final HttpRequest request,
+            final HttpResponse response, final HttpContext context)
+            throws ProtocolException {
+        Args.notNull(request, "HTTP request");
+        Args.notNull(response, "HTTP response");
+
+        final int statusCode = response.getStatusLine().getStatusCode();
+        final String method = request.getRequestLine().getMethod();
+        final Header locationHeader = response.getFirstHeader("location");
+        switch (statusCode) {
+            case HttpStatus.SC_MOVED_TEMPORARILY:
+                return isRedirectable(method) && locationHeader != null;
+            case HttpStatus.SC_MOVED_PERMANENTLY:
+            case HttpStatus.SC_TEMPORARY_REDIRECT:
+                return isRedirectable(method);
+            case HttpStatus.SC_SEE_OTHER:
+                return true;
+            case 308: // permanent redirect
+                return isRedirectable(method);
+            default:
+                return false;
+        } // end of switch
+    }
+
+    @Override
+    public HttpUriRequest getRedirect (final HttpRequest request,
+            final HttpResponse response, final HttpContext context)
+            throws ProtocolException {
+        final URI uri = getLocationURI(request, response, context);
+        final String method = request.getRequestLine().getMethod();
+        if (method.equalsIgnoreCase(HttpHead.METHOD_NAME)) {
+            return new HttpHead(uri);
+        }
+        else if (method.equalsIgnoreCase(HttpGet.METHOD_NAME)) {
+            return new HttpGet(uri);
+        }
+        else {
+            final int status = response.getStatusLine().getStatusCode();
+            if (status == HttpStatus.SC_TEMPORARY_REDIRECT
+                    || status == 308) { // permanent redirect
+                return RequestBuilder.copy(request).setUri(uri).build();
+            }
+            else {
+                return new HttpGet(uri);
+            }
+        }
+    }
+}
diff --git a/src/test/java/de/ids_mannheim/korap/test/RedirectTest.java b/src/test/java/de/ids_mannheim/korap/test/RedirectTest.java
new file mode 100644
index 0000000..209fb73
--- /dev/null
+++ b/src/test/java/de/ids_mannheim/korap/test/RedirectTest.java
@@ -0,0 +1,27 @@
+package de.ids_mannheim.korap.test;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.IOException;
+
+import org.apache.http.HttpResponse;
+import org.apache.http.client.ClientProtocolException;
+import org.apache.http.client.HttpClient;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.impl.client.HttpClientBuilder;
+import org.junit.Test;
+
+import de.ids_mannheim.korap.util.RedirectStrategy;
+
+public class RedirectTest {
+
+    @Test
+    public void testRedirect () throws ClientProtocolException, IOException {
+        HttpClient client = HttpClientBuilder.create()
+                .setRedirectStrategy(new RedirectStrategy()).build();
+        HttpResponse response = client.execute(new HttpGet(
+                "http://localhost:8089/api/search?q=Wasser&ql=poliqarp"));
+        assertEquals(200, response.getStatusLine().getStatusCode());
+
+    }
+}