/*******************************************************************************
 * This file is part of OpenNMS(R).
 *
 * Copyright (C) 2017-2017 The OpenNMS Group, Inc.
 * OpenNMS(R) is Copyright (C) 1999-2017 The OpenNMS Group, Inc.
 *
 * OpenNMS(R) is a registered trademark of The OpenNMS Group, Inc.
 *
 * OpenNMS(R) is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published
 * by the Free Software Foundation, either version 3 of the License,
 * or (at your option) any later version.
 *
 * OpenNMS(R) is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with OpenNMS(R).  If not, see:
 *      http://www.gnu.org/licenses/
 *
 * For more information contact:
 *     OpenNMS(R) Licensing <license@opennms.org>
 *     http://www.opennms.org/
 *     http://www.opennms.com/
 *******************************************************************************/

package org.opennms.plugins.elasticsearch.rest.executors;

import java.io.IOException;

import org.opennms.plugins.elasticsearch.rest.RequestExecutorFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import io.searchbox.action.Action;
import io.searchbox.client.JestClient;
import io.searchbox.client.JestResult;
import io.searchbox.client.config.exception.CouldNotConnectException;

public class DefaultRequestExecutor implements RequestExecutor, RequestExecutorFactory {

    private static Logger LOG = LoggerFactory.getLogger(DefaultRequestExecutor.class);

    private final long cooldownInMs;

    public DefaultRequestExecutor(long cooldownInMs) {
        if (cooldownInMs < 0) {
            LOG.warn("Retry cooldown must be >= 0. Using a value of 0 instead.");
        }
        this.cooldownInMs = Math.max(0, cooldownInMs);
    }

    @Override
    public <T extends JestResult> T execute(JestClient client, Action<T> clientRequest) {
        try {
            T result = client.execute(clientRequest);
            return result;
        } catch (CouldNotConnectException connectException) {
            return retry(client, clientRequest);
        } catch (IOException ex) {
            return retry(client, clientRequest);
        } catch (com.google.gson.JsonSyntaxException gsonException) {
            return retry(client, clientRequest);
        }
    }

    public <T extends JestResult> T retry(JestClient client, Action<T> clientRequest) {
        LOG.debug("Retry request");
        if (cooldownInMs > 0) {
            LOG.debug("Sleep " + cooldownInMs + " before retrying");
            try {
                Thread.sleep(cooldownInMs);
            } catch (InterruptedException e) {
                throw new RuntimeException("Thread interrupted.", e);
            }
        }
        LOG.debug("Retrying now");
        final T result = execute(client, clientRequest);
        return result;
    }

    @Override
    public RequestExecutor createExecutor(int timeout, int retryCount) {
        return new DefaultRequestExecutor(cooldownInMs);
    }
}


@@ -2153,32 +2153,111 @@
 lientRequest) %7B%0A
+        do %7B%0A            LOG.debug(%22Executing request %7B%7D%22, clientRequest);%0A    
         try %7B%0A  
@@ -2246,32 +2246,36 @@
           try %7B%0A
+    
             T re
@@ -2316,32 +2316,36 @@
 t);%0A            
+ 
+   
 return result;%0A 
@@ -2339,24 +2339,28 @@
 urn result;%0A
+    
         %7D ca
@@ -2425,245 +2425,422 @@
     
+  
-return retry(client, clientRequest);%0A        %7D catch (IOException ex) %7B%0A            return retry(client, clientRequest);%0A        %7D catch (com.google.gson.JsonSyntaxException gsonException) %7B%0A            return retry(client, clientRequest
+  LOG.error(%22Could not connect to elastic endpoint: %7B%7D%22, connectException.getHost(), connectException);%0A            %7D catch (IOException ex) %7B%0A                LOG.error(%22Could not perform request %7B%7D: %7B%7D%22, clientRequest, ex.getMessage(), ex);%0A            %7D catch (com.google.gson.JsonSyntaxException gsonException) %7B%0A                LOG.error(%22A Json error occurred: %7B%7D%22, gsonException.getMessage(), gsonException
 );%0A 
@@ -2842,26 +2842,24 @@
 n);%0A        
-%7D%0A
     %7D%0A%0A    p
@@ -2861,128 +2861,116 @@
     
-public %3CT extends JestResult%3E T retry(JestClient client, Action%3CT%3E clientRequest) %7B%0A        LOG.debug(%22Retry request%22);%0A
+        // Retry-Logic%0A            LOG.debug(%22Request was not executed properly. Attempting Retry...%22);%0A    
     
@@ -2993,24 +2993,28 @@
 InMs %3E 0) %7B%0A
+    
             
@@ -3074,38 +3074,46 @@
 %22);%0A            
+   
+ 
 try %7B%0A
+    
                 
@@ -3136,24 +3136,28 @@
 ldownInMs);%0A
+    
             
@@ -3207,16 +3207,20 @@
         
+    
 throw ne
@@ -3269,32 +3269,36 @@
 e);%0A            
+    
 %7D%0A        %7D%0A    
@@ -3283,34 +3283,42 @@
       %7D%0A        
+ 
-%7D%0A
+   %7D%0A    
         LOG.debu
@@ -3348,78 +3348,22 @@
     
-final T result = execute(client, clientRequest);%0A        return result
+%7D while (true)
 ;%0A  

Fix possible stack overflow by implementing retry-strategy iterative