]> git.basschouten.com Git - openhab-addons.git/blob
d68245b19cc48046e4d7d16f0c2225a13d2544df
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2024 Contributors to the openHAB project
3  *
4  * See the NOTICE file(s) distributed with this work for additional
5  * information.
6  *
7  * This program and the accompanying materials are made available under the
8  * terms of the Eclipse Public License 2.0 which is available at
9  * http://www.eclipse.org/legal/epl-2.0
10  *
11  * SPDX-License-Identifier: EPL-2.0
12  */
13 package org.openhab.binding.fronius.internal.api;
14
15 import java.io.IOException;
16 import java.io.InputStream;
17 import java.util.Properties;
18
19 import org.eclipse.jdt.annotation.NonNullByDefault;
20 import org.eclipse.jdt.annotation.Nullable;
21 import org.eclipse.jetty.http.HttpMethod;
22 import org.openhab.core.io.net.http.HttpUtil;
23 import org.slf4j.Logger;
24 import org.slf4j.LoggerFactory;
25
26 /**
27  * A version of HttpUtil implementation that retries on failure.
28  *
29  * @author Jimmy Tanagra - Initial contribution
30  */
31 @NonNullByDefault
32 public class FroniusHttpUtil {
33     private static final Logger logger = LoggerFactory.getLogger(FroniusHttpUtil.class);
34
35     /**
36      * Issue a HTTP request and retry on failure.
37      *
38      * @param httpMethod the HTTP method to use
39      * @param url the url to execute
40      * @param timeout the socket timeout in milliseconds to wait for data
41      * @return the response body
42      * @throws FroniusCommunicationException when the request execution failed or interrupted
43      */
44     public static synchronized String executeUrl(HttpMethod httpMethod, String url, int timeout)
45             throws FroniusCommunicationException {
46         return executeUrl(httpMethod, url, null, null, null, timeout);
47     }
48
49     /**
50      * Issue a HTTP request and retry on failure.
51      *
52      * @param httpMethod the {@link HttpMethod} to use
53      * @param url the url to execute
54      * @param httpHeaders optional http request headers which has to be sent within request
55      * @param content the content to be sent to the given <code>url</code> or <code>null</code> if no content should be
56      *            sent.
57      * @param contentType the content type of the given <code>content</code>
58      * @param timeout the socket timeout in milliseconds to wait for data
59      * @return the response body
60      * @throws FroniusCommunicationException when the request execution failed or interrupted
61      */
62     public static synchronized String executeUrl(HttpMethod httpMethod, String url, @Nullable Properties httpHeaders,
63             @Nullable InputStream content, @Nullable String contentType, int timeout)
64             throws FroniusCommunicationException {
65         int attemptCount = 1;
66         try {
67             while (true) {
68                 Throwable lastException = null;
69                 String result = null;
70                 try {
71                     result = HttpUtil.executeUrl(httpMethod.asString(), url, httpHeaders, content, contentType,
72                             timeout);
73                 } catch (IOException e) {
74                     // HttpUtil::executeUrl wraps InterruptedException into IOException.
75                     // Unwrap and rethrow it so that we don't retry on InterruptedException
76                     Throwable cause = e.getCause();
77                     if (cause instanceof InterruptedException interruptException) {
78                         throw interruptException;
79                     }
80                     lastException = e;
81                 }
82
83                 if (result != null) {
84                     if (attemptCount > 1) {
85                         logger.debug("Attempt #{} successful {}", attemptCount, url);
86                     }
87                     return result;
88                 }
89
90                 if (attemptCount >= 3) {
91                     logger.debug("Failed connecting to {} after {} attempts.", url, attemptCount, lastException);
92                     throw new FroniusCommunicationException("Unable to connect", lastException);
93                 }
94
95                 logger.debug("HTTP error on attempt #{} {}", attemptCount, url);
96                 Thread.sleep(500 * attemptCount);
97                 attemptCount++;
98             }
99         } catch (InterruptedException e) {
100             Thread.currentThread().interrupt();
101             throw new FroniusCommunicationException("Interrupted", e);
102         }
103     }
104 }