]> git.basschouten.com Git - openhab-addons.git/blob
60c8cbac3ed991b2dda89e8e8a157bec77584768
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2023 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.evohome.internal.api;
14
15 import java.util.HashMap;
16 import java.util.Map;
17 import java.util.concurrent.ExecutionException;
18 import java.util.concurrent.TimeUnit;
19 import java.util.concurrent.TimeoutException;
20
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;
32
33 import com.google.gson.Gson;
34 import com.google.gson.GsonBuilder;
35
36 /**
37  * Provides access to (an optionally OAUTH based) API. Makes sure that all the necessary headers are set.
38  *
39  * @author Jasper van Zuijlen - Initial contribution
40  *
41  */
42 @NonNullByDefault
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();
48
49     private @Nullable Authentication authenticationData;
50     private @Nullable String applicationId;
51
52     public ApiAccess(HttpClient httpClient) {
53         this.httpClient = httpClient;
54     }
55
56     /**
57      * Sets the authentication details on the type
58      *
59      * @param authentication The authentication details to apply
60      */
61     public void setAuthentication(@Nullable Authentication authentication) {
62         authenticationData = authentication;
63     }
64
65     /**
66      * Gets the current authentication details of the type
67      *
68      * @return The current authentication details
69      */
70     public @Nullable Authentication getAuthentication() {
71         return authenticationData;
72     }
73
74     /**
75      * Sets the application id on the type
76      *
77      * @param applicationId The application id to apply
78      */
79     public void setApplicationId(@Nullable String applicationId) {
80         this.applicationId = applicationId;
81     }
82
83     /**
84      * Issues an HTTP request on the API's URL. Makes sure that the request is correctly formatted.
85      *
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
93      */
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);
97         @Nullable
98         TOut retVal = null;
99         try {
100             Request request = httpClient.newRequest(url).method(method);
101
102             for (Map.Entry<String, String> header : headers.entrySet()) {
103                 request.header(header.getKey(), header.getValue());
104             }
105
106             if (requestData != null) {
107                 request.content(new StringContentProvider(requestData), contentType);
108             }
109
110             ContentResponse response = request.timeout(REQUEST_TIMEOUT_SECONDS, TimeUnit.SECONDS).send();
111
112             logger.trace("Response: {}", response);
113             logger.trace("\n{}\n{}", response.getHeaders(), response.getContentAsString());
114
115             if ((response.getStatus() == HttpStatus.OK_200) || (response.getStatus() == HttpStatus.ACCEPTED_202)) {
116                 String reply = response.getContentAsString();
117
118                 if (outClass != null) {
119                     retVal = new Gson().fromJson(reply, outClass);
120                 }
121             } else if ((response.getStatus() == HttpStatus.CREATED_201)) {
122                 // success nothing to return ignore
123             } else {
124                 logger.debug("Request failed with unexpected response code {}", response.getStatus());
125             }
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();
131         }
132         return retVal;
133     }
134
135     /**
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.*
138      *
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
143      */
144     public @Nullable <TOut> TOut doAuthenticatedGet(String url, Class<TOut> outClass) throws TimeoutException {
145         return doAuthenticatedRequest(HttpMethod.GET, url, null, outClass);
146     }
147
148     /**
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.*
151      *
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
155      */
156     public void doAuthenticatedPut(String url, Object requestContainer) throws TimeoutException {
157         doAuthenticatedRequest(HttpMethod.PUT, url, requestContainer, null);
158     }
159
160     /**
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.*
163      *
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
171      */
172     private @Nullable <TOut> TOut doRequest(HttpMethod method, String url, Map<String, String> headers,
173             @Nullable Object requestContainer, @Nullable Class<TOut> outClass) throws TimeoutException {
174         String json = null;
175         if (requestContainer != null) {
176             json = gson.toJson(requestContainer);
177         }
178
179         return doRequest(method, url, headers, json, "application/json", outClass);
180     }
181
182     /**
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.*
186      *
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
193      */
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;
199
200         if (localAuthenticationData != null) {
201             headers.put("Authorization", "Bearer " + localAuthenticationData.getAccessToken());
202         }
203         if (localApplicationId != null) {
204             headers.put("applicationId", localApplicationId);
205         }
206         headers.put("Accept", "application/json, application/xml, text/json, text/x-json, text/javascript, text/xml");
207
208         return doRequest(method, url, headers, requestContainer, outClass);
209     }
210 }