Merge "Remove actor and recipe checks from ControlLoopCompiler.java"
[policy/models.git] / models-interactions / model-impl / rest / src / main / java / org / onap / policy / rest / RestManager.java
1 /*
2  * ============LICENSE_START=======================================================
3  * rest
4  * ================================================================================
5  * Copyright (C) 2017-2019 AT&T Intellectual Property. All rights reserved.
6  * Modifications Copyright (C) 2019 Nordix Foundation.
7  * ================================================================================
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  * ============LICENSE_END=========================================================
20  */
21
22 package org.onap.policy.rest;
23
24 import java.nio.charset.Charset;
25 import java.util.Map;
26 import java.util.Map.Entry;
27 import javax.xml.bind.DatatypeConverter;
28 import org.apache.http.HttpHeaders;
29 import org.apache.http.HttpResponse;
30 import org.apache.http.client.methods.HttpDelete;
31 import org.apache.http.client.methods.HttpGet;
32 import org.apache.http.client.methods.HttpPost;
33 import org.apache.http.client.methods.HttpPut;
34 import org.apache.http.client.methods.HttpRequestBase;
35 import org.apache.http.conn.ssl.NoopHostnameVerifier;
36 import org.apache.http.entity.StringEntity;
37 import org.apache.http.impl.client.CloseableHttpClient;
38 import org.apache.http.impl.client.HttpClientBuilder;
39 import org.apache.http.util.EntityUtils;
40 import org.slf4j.Logger;
41 import org.slf4j.LoggerFactory;
42
43 public class RestManager {
44     private static final Logger logger = LoggerFactory.getLogger(RestManager.class);
45
46     // Constants for string literals
47     private static final String CONTENT_TYPE = "Content-Type";
48
49     public class Pair<A, B> {
50         public final A first;
51         public final B second;
52
53         public Pair(A first, B second) {
54             this.first = first;
55             this.second = second;
56         }
57     }
58
59     /**
60      * Perform REST PUT.
61      *
62      * @param url         the url
63      * @param username    the user name
64      * @param password    the password
65      * @param headers     any headers
66      * @param contentType what the content type is
67      * @param body        body to send
68      * @return the response status code and the body
69      */
70     public Pair<Integer, String> put(String url, String username, String password,
71                                       Map<String, String> headers, String contentType, String body) {
72         HttpPut put = new HttpPut(url);
73         addHeaders(put, username, password, headers);
74         put.addHeader(CONTENT_TYPE, contentType);
75         try {
76             StringEntity input = new StringEntity(body);
77             input.setContentType(contentType);
78             put.setEntity(input);
79         } catch (Exception e) {
80             logger.error("put threw: ", e);
81             return null;
82         }
83         return sendRequest(put);
84     }
85
86     /**
87      * Perform REST Post.
88      *
89      * @param url         the url
90      * @param username    the user name
91      * @param password    the password
92      * @param headers     any headers
93      * @param contentType what the content type is
94      * @param body        body to send
95      * @return the response status code and the body
96      */
97     public Pair<Integer, String> post(String url, String username, String password,
98                                       Map<String, String> headers, String contentType, String body) {
99         HttpPost post = new HttpPost(url);
100         addHeaders(post, username, password, headers);
101         post.addHeader(CONTENT_TYPE, contentType);
102         try {
103             StringEntity input = new StringEntity(body);
104             input.setContentType(contentType);
105             post.setEntity(input);
106         } catch (Exception e) {
107             logger.error("post threw: ", e);
108             return null;
109         }
110         return sendRequest(post);
111     }
112
113     /**
114      * Do a REST get.
115      *
116      * @param url      URL
117      * @param username user name
118      * @param password password
119      * @param headers  any headers to add
120      * @return a Pair for the response status and the body
121      */
122     public Pair<Integer, String> get(String url, String username, String password,
123                                      Map<String, String> headers) {
124         HttpGet get = new HttpGet(url);
125         addHeaders(get, username, password, headers);
126         return sendRequest(get);
127     }
128
129     /**
130      * Perform REST Delete. <br/>
131      * <i>Note: Many REST endpoints will return a 400 error for delete requests with a non-empty body</i>
132      *
133      * @param url         the url
134      * @param username    the user name
135      * @param password    the password
136      * @param headers     any headers
137      * @param contentType what the content type is
138      * @param body        body (optional) to send
139      * @return the response status code and the body
140      */
141     public Pair<Integer, String> delete(String url, String username, String password, Map<String, String> headers,
142                                         String contentType, String body) {
143         HttpDeleteWithBody delete = new HttpDeleteWithBody(url);
144         addHeaders(delete, username, password, headers);
145         if (body != null && !body.isEmpty()) {
146             delete.addHeader(CONTENT_TYPE, contentType);
147             try {
148                 StringEntity input = new StringEntity(body);
149                 input.setContentType(contentType);
150                 delete.setEntity(input);
151             } catch (Exception e) {
152                 logger.error("delete threw: ", e);
153                 return null;
154             }
155         }
156         return sendRequest(delete);
157     }
158
159     /**
160      * Perform REST Delete.
161      *
162      * @param url         the url
163      * @param username    the user name
164      * @param password    the password
165      * @param headers     any headers
166      * @return the response status code and the body
167      */
168     public Pair<Integer, String> delete(String url, String username, String password, Map<String, String> headers) {
169         HttpDelete delete = new HttpDelete(url);
170         addHeaders(delete, username, password, headers);
171         return sendRequest(delete);
172     }
173
174     /**
175      * Send REST request.
176      *
177      * @param request http request to send
178      * @return the response status code and the body
179      */
180     private Pair<Integer, String> sendRequest(HttpRequestBase request) {
181         if (logger.isDebugEnabled()) {
182             logger.debug("***** sendRequest to url {}:", request.getURI());
183         }
184
185         try (CloseableHttpClient client =
186                      HttpClientBuilder
187                              .create()
188                              .setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE)
189                              .build()) {
190             HttpResponse response = client.execute(request);
191             if (response != null) {
192                 String returnBody = EntityUtils.toString(response.getEntity(), "UTF-8");
193                 logger.debug("HTTP Response Status Code: {}",
194                         response.getStatusLine().getStatusCode());
195                 logger.debug("HTTP Response Body:");
196                 logger.debug(returnBody);
197
198                 return new Pair<>(response.getStatusLine().getStatusCode(),
199                         returnBody);
200             } else {
201                 logger.error("Response from {} is null", request.getURI());
202                 return null;
203             }
204         } catch (Exception e) {
205             logger.error("Request failed to {}", request.getURI(), e);
206             return null;
207         }
208     }
209
210     /**
211      * Add header to the request.
212      *
213      * @param request  http request to send
214      * @param username the user name
215      * @param password the password
216      * @param headers  any headers
217      */
218     private void addHeaders(HttpRequestBase request, String username, String password, Map<String,
219             String> headers) {
220         String authHeader = makeAuthHeader(username, password);
221         if (headers != null) {
222             for (Entry<String, String> entry : headers.entrySet()) {
223                 request.addHeader(entry.getKey(), headers.get(entry.getKey()));
224             }
225         }
226         if (authHeader != null) {
227             request.setHeader(HttpHeaders.AUTHORIZATION, authHeader);
228         }
229     }
230
231     private String makeAuthHeader(String username, String password) {
232         if (username == null || username.isEmpty()) {
233             return null;
234         }
235
236         String auth = username + ":" + (password == null ? "" : password);
237         return "Basic " + DatatypeConverter.printBase64Binary(auth.getBytes(Charset.forName("ISO-8859-1")));
238     }
239 }