2 * Copyright (c) 2010-2023 Contributors to the openHAB project
4 * See the NOTICE file(s) distributed with this work for additional
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
11 * SPDX-License-Identifier: EPL-2.0
13 package org.openhab.binding.evohome.internal.api;
15 import java.util.HashMap;
17 import java.util.concurrent.ExecutionException;
18 import java.util.concurrent.TimeUnit;
19 import java.util.concurrent.TimeoutException;
21 import org.eclipse.jdt.annotation.NonNullByDefault;
22 import org.eclipse.jdt.annotation.Nullable;
23 import org.eclipse.jetty.client.HttpClient;
24 import org.eclipse.jetty.client.api.ContentResponse;
25 import org.eclipse.jetty.client.api.Request;
26 import org.eclipse.jetty.client.util.StringContentProvider;
27 import org.eclipse.jetty.http.HttpMethod;
28 import org.eclipse.jetty.http.HttpStatus;
29 import org.openhab.binding.evohome.internal.api.models.v2.dto.response.Authentication;
30 import org.slf4j.Logger;
31 import org.slf4j.LoggerFactory;
33 import com.google.gson.Gson;
34 import com.google.gson.GsonBuilder;
37 * Provides access to (an optionally OAUTH based) API. Makes sure that all the necessary headers are set.
39 * @author Jasper van Zuijlen - Initial contribution
43 public class ApiAccess {
44 private static final int REQUEST_TIMEOUT_SECONDS = 5;
45 private final Logger logger = LoggerFactory.getLogger(ApiAccess.class);
46 private final HttpClient httpClient;
47 private final Gson gson = new GsonBuilder().create();
49 private @Nullable Authentication authenticationData;
50 private @Nullable String applicationId;
52 public ApiAccess(HttpClient httpClient) {
53 this.httpClient = httpClient;
57 * Sets the authentication details on the type
59 * @param authentication The authentication details to apply
61 public void setAuthentication(@Nullable Authentication authentication) {
62 authenticationData = authentication;
66 * Gets the current authentication details of the type
68 * @return The current authentication details
70 public @Nullable Authentication getAuthentication() {
71 return authenticationData;
75 * Sets the application id on the type
77 * @param applicationId The application id to apply
79 public void setApplicationId(@Nullable String applicationId) {
80 this.applicationId = applicationId;
84 * Issues an HTTP request on the API's URL. Makes sure that the request is correctly formatted.
86 * @param method The HTTP method to use (POST, GET, ...)
87 * @param url The URL to query
88 * @param headers The optional additional headers to apply, can be null
89 * @param requestData The optional request data to use, can be null
90 * @param contentType The content type to use with the request data. Required when using requestData
91 * @return The result of the request or null
92 * @throws TimeoutException Thrown when a request times out
94 public @Nullable <TOut> TOut doRequest(HttpMethod method, String url, Map<String, String> headers,
95 @Nullable String requestData, String contentType, @Nullable Class<TOut> outClass) throws TimeoutException {
96 logger.debug("Requesting: [{}]", url);
100 Request request = httpClient.newRequest(url).method(method);
102 for (Map.Entry<String, String> header : headers.entrySet()) {
103 request.header(header.getKey(), header.getValue());
106 if (requestData != null) {
107 request.content(new StringContentProvider(requestData), contentType);
110 ContentResponse response = request.timeout(REQUEST_TIMEOUT_SECONDS, TimeUnit.SECONDS).send();
112 logger.trace("Response: {}", response);
113 logger.trace("\n{}\n{}", response.getHeaders(), response.getContentAsString());
115 if ((response.getStatus() == HttpStatus.OK_200) || (response.getStatus() == HttpStatus.ACCEPTED_202)) {
116 String reply = response.getContentAsString();
118 if (outClass != null) {
119 retVal = new Gson().fromJson(reply, outClass);
121 } else if ((response.getStatus() == HttpStatus.CREATED_201)) {
122 // success nothing to return ignore
124 logger.debug("Request failed with unexpected response code {}", response.getStatus());
126 } catch (ExecutionException e) {
127 logger.debug("Error in handling request: ", e);
128 } catch (InterruptedException e) {
129 logger.debug("Handling request interrupted: ", e);
130 Thread.currentThread().interrupt();
136 * Issues an HTTP GET request on the API's URL, using an object that is serialized to JSON as input.
137 * Makes sure that the request is correctly formatted.*
139 * @param url The URL to query
140 * @param outClass The type of the requested result
141 * @return The result of the request or null
142 * @throws TimeoutException Thrown when a request times out
144 public @Nullable <TOut> TOut doAuthenticatedGet(String url, Class<TOut> outClass) throws TimeoutException {
145 return doAuthenticatedRequest(HttpMethod.GET, url, null, outClass);
149 * Issues an HTTP request on the API's URL, using an object that is serialized to JSON as input.
150 * Makes sure that the request is correctly formatted.*
152 * @param url The URL to query
153 * @param requestContainer The object to use as JSON data for the request
154 * @throws TimeoutException Thrown when a request times out
156 public void doAuthenticatedPut(String url, Object requestContainer) throws TimeoutException {
157 doAuthenticatedRequest(HttpMethod.PUT, url, requestContainer, null);
161 * Issues an HTTP request on the API's URL, using an object that is serialized to JSON as input.
162 * Makes sure that the request is correctly formatted.*
164 * @param method The HTTP method to use (POST, GET, ...)
165 * @param url The URL to query
166 * @param headers The optional additional headers to apply, can be null
167 * @param requestContainer The object to use as JSON data for the request, can be null
168 * @param outClass The type of the requested result, can be null
169 * @return The result of the request or null
170 * @throws TimeoutException Thrown when a request times out
172 private @Nullable <TOut> TOut doRequest(HttpMethod method, String url, Map<String, String> headers,
173 @Nullable Object requestContainer, @Nullable Class<TOut> outClass) throws TimeoutException {
175 if (requestContainer != null) {
176 json = gson.toJson(requestContainer);
179 return doRequest(method, url, headers, json, "application/json", outClass);
183 * Issues an HTTP request on the API's URL, using an object that is serialized to JSON as input and
184 * using the authentication applied to the type.
185 * Makes sure that the request is correctly formatted.*
187 * @param method The HTTP method to use (POST, GET, ...)
188 * @param url The URL to query
189 * @param requestContainer The object to use as JSON data for the request
190 * @param outClass The type of the requested result
191 * @return The result of the request or null
192 * @throws TimeoutException Thrown when a request times out
194 private @Nullable <TOut> TOut doAuthenticatedRequest(HttpMethod method, String url,
195 @Nullable Object requestContainer, @Nullable Class<TOut> outClass) throws TimeoutException {
196 Map<String, String> headers = new HashMap<>();
197 Authentication localAuthenticationData = authenticationData;
198 String localApplicationId = applicationId;
200 if (localAuthenticationData != null) {
201 headers.put("Authorization", "Bearer " + localAuthenticationData.getAccessToken());
203 if (localApplicationId != null) {
204 headers.put("applicationId", localApplicationId);
206 headers.put("Accept", "application/json, application/xml, text/json, text/x-json, text/javascript, text/xml");
208 return doRequest(method, url, headers, requestContainer, outClass);