Controller Blueprints Nitrogen to Oxygen Migration
[ccsdk/features.git] / blueprints-processor / adaptors / rest-adaptor-provider / src / main / java / org / onap / ccsdk / features / rest / adaptor / service / AbstractConfigRestClientAdapter.java
1 /*\r
2  * Copyright © 2017-2018 AT&T Intellectual Property.\r
3  * \r
4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except\r
5  * in compliance with the License. You may obtain a copy of the License at\r
6  * \r
7  * http://www.apache.org/licenses/LICENSE-2.0\r
8  * \r
9  * Unless required by applicable law or agreed to in writing, software distributed under the License\r
10  * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express\r
11  * or implied. See the License for the specific language governing permissions and limitations under\r
12  * the License.\r
13  */\r
14 \r
15 package org.onap.ccsdk.features.rest.adaptor.service;\r
16 \r
17 import java.io.FileInputStream;\r
18 import java.io.InputStream;\r
19 import java.security.KeyStore;\r
20 import java.security.cert.X509Certificate;\r
21 import java.util.ArrayList;\r
22 import java.util.List;\r
23 import java.util.Map;\r
24 import java.util.concurrent.ConcurrentHashMap;\r
25 import javax.net.ssl.SSLContext;\r
26 import org.apache.commons.lang3.StringUtils;\r
27 import org.apache.http.conn.ssl.NoopHostnameVerifier;\r
28 import org.apache.http.conn.ssl.SSLConnectionSocketFactory;\r
29 import org.apache.http.impl.client.CloseableHttpClient;\r
30 import org.apache.http.impl.client.HttpClients;\r
31 import org.apache.http.ssl.SSLContextBuilder;\r
32 import org.apache.http.ssl.TrustStrategy;\r
33 import org.onap.ccsdk.features.rest.adaptor.ConfigRestAdaptorConstants;\r
34 import org.onap.ccsdk.features.rest.adaptor.ConfigRestAdaptorException;\r
35 import org.onap.ccsdk.features.rest.adaptor.data.RestResponse;\r
36 import org.onap.ccsdk.features.rest.adaptor.utils.BasicAuthorizationInterceptor;\r
37 import org.springframework.http.HttpEntity;\r
38 import org.springframework.http.HttpHeaders;\r
39 import org.springframework.http.HttpMethod;\r
40 import org.springframework.http.HttpStatus;\r
41 import org.springframework.http.ResponseEntity;\r
42 import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;\r
43 import org.springframework.http.converter.ByteArrayHttpMessageConverter;\r
44 import org.springframework.http.converter.HttpMessageConverter;\r
45 import org.springframework.http.converter.ResourceHttpMessageConverter;\r
46 import org.springframework.http.converter.StringHttpMessageConverter;\r
47 import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;\r
48 import org.springframework.http.converter.xml.SourceHttpMessageConverter;\r
49 import org.springframework.util.ResourceUtils;\r
50 import org.springframework.web.client.HttpClientErrorException;\r
51 import org.springframework.web.client.RestTemplate;\r
52 import com.att.eelf.configuration.EELFLogger;\r
53 import com.att.eelf.configuration.EELFManager;\r
54 \r
55 abstract class AbstractConfigRestClientAdapter implements ConfigRestClientServiceAdapter {\r
56 \r
57     private static EELFLogger logger = EELFManager.getInstance().getLogger(AbstractConfigRestClientAdapter.class);\r
58     private static final String MS_INIT_FAIL = "Failed to initialise microservice client restTemplate.";\r
59 \r
60     protected boolean isRestClientServiceAdapaterEnabled = false;\r
61     protected boolean isSSLServiceAdapaterEnabled = true;\r
62 \r
63     protected Map<String, String> properties = new ConcurrentHashMap<>();\r
64     protected String serviceSelector;\r
65 \r
66     protected RestTemplate restTemplate;\r
67 \r
68     protected AbstractConfigRestClientAdapter(Map<String, String> properties, String serviceSelector) {\r
69         this.properties = properties;\r
70         this.serviceSelector = serviceSelector;\r
71         setRestClientServiceAdapaterEnabled();\r
72     }\r
73 \r
74     private void setRestClientServiceAdapaterEnabled() {\r
75         String isEnabledProperty = ConfigRestAdaptorConstants.REST_ADAPTOR_BASE_PROPERTY + serviceSelector\r
76                 + ConfigRestAdaptorConstants.SERVICE_EANABLED_PROPERTY;\r
77         String isRestClientServiceAdapaterEnabledStr = properties.get(isEnabledProperty);\r
78         logger.info("Service selector ({}) enable status ({}) ", serviceSelector,\r
79                 isRestClientServiceAdapaterEnabledStr);\r
80         if (StringUtils.isNotBlank(isRestClientServiceAdapaterEnabledStr)\r
81                 && Boolean.parseBoolean(isRestClientServiceAdapaterEnabledStr)) {\r
82             isRestClientServiceAdapaterEnabled = true;\r
83         }\r
84     }\r
85 \r
86     private List<HttpMessageConverter<?>> getMessageConverters() {\r
87         List<HttpMessageConverter<?>> converters = new ArrayList<>();\r
88         converters.add(new ByteArrayHttpMessageConverter());\r
89         converters.add(new StringHttpMessageConverter());\r
90         converters.add(new ResourceHttpMessageConverter());\r
91         converters.add(new SourceHttpMessageConverter());\r
92         converters.add(new MappingJackson2HttpMessageConverter());\r
93         return converters;\r
94     }\r
95 \r
96     public void initialise(String user, String pass) {\r
97         logger.trace("Config rest template factory user ({}) ", user);\r
98 \r
99         CloseableHttpClient httpClient =\r
100                 HttpClients.custom().setSSLHostnameVerifier(new NoopHostnameVerifier()).build();\r
101         HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory();\r
102         requestFactory.setHttpClient(httpClient);\r
103 \r
104         restTemplate = new RestTemplate(getMessageConverters());\r
105         restTemplate.setRequestFactory(requestFactory);\r
106         if (StringUtils.isNotBlank(user) && StringUtils.isNotBlank(pass)) {\r
107             restTemplate.getInterceptors().add(new BasicAuthorizationInterceptor(user, pass));\r
108         }\r
109     }\r
110 \r
111     public void initialiseSSL(String keyStorePath, String trustStorePath, String keyPass, String trustPass)\r
112             throws ConfigRestAdaptorException {\r
113         logger.trace("SSL rest template factory");\r
114 \r
115         TrustStrategy acceptingTrustStrategy = (X509Certificate[] chain, String authType) -> true;\r
116         SSLContext sslContext = null;\r
117 \r
118         try (InputStream keyInput = new FileInputStream(keyStorePath)) {\r
119             KeyStore keyStore = KeyStore.getInstance("PKCS12");\r
120             keyStore.load(keyInput, keyPass.toCharArray());\r
121 \r
122             logger.info("key loaded successfully");\r
123             sslContext = SSLContextBuilder.create().loadKeyMaterial(keyStore, keyPass.toCharArray()).loadTrustMaterial(\r
124                     ResourceUtils.getFile(trustStorePath), trustPass.toCharArray(), acceptingTrustStrategy).build();\r
125         } catch (Exception e) {\r
126             throw new ConfigRestAdaptorException(e.getMessage());\r
127         }\r
128 \r
129         SSLConnectionSocketFactory csf = new SSLConnectionSocketFactory(sslContext);\r
130         CloseableHttpClient httpClient = HttpClients.custom().setSSLSocketFactory(csf).build();\r
131         HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(httpClient);\r
132 \r
133         restTemplate = new RestTemplate(getMessageConverters());\r
134         restTemplate.setRequestFactory(requestFactory);\r
135     }\r
136 \r
137     public <T> T getResource(HttpHeaders headers, String url, Class<T> responseType) throws ConfigRestAdaptorException {\r
138         ResponseEntity<T> response = exchangeForEntity(headers, url, HttpMethod.GET, null, responseType);\r
139         return processResponse(response, url, HttpMethod.GET);\r
140     }\r
141 \r
142     public <T> T postResource(HttpHeaders headers, String url, Object request, Class<T> responseType)\r
143             throws ConfigRestAdaptorException {\r
144         ResponseEntity<T> response = exchangeForEntity(headers, url, HttpMethod.POST, request, responseType);\r
145         return processResponse(response, url, HttpMethod.POST);\r
146     }\r
147 \r
148     public <T> T exchangeResource(HttpHeaders headers, String url, Object request, Class<T> responseType, String method)\r
149             throws ConfigRestAdaptorException {\r
150         ResponseEntity<T> response = exchangeForEntity(headers, url, HttpMethod.valueOf(method), request, responseType);
151         return processResponse(response, url, HttpMethod.valueOf(method));
152     }\r
153 \r
154     public RestResponse getResource(HttpHeaders headers, String url) throws ConfigRestAdaptorException {\r
155         return exchangeForEntity(headers, url, HttpMethod.GET, null);\r
156     }\r
157 \r
158     public RestResponse postResource(HttpHeaders headers, String url, Object request)\r
159             throws ConfigRestAdaptorException {\r
160         return exchangeForEntity(headers, url, HttpMethod.POST, request);\r
161     }\r
162 \r
163     public RestResponse exchangeResource(HttpHeaders headers, String url, Object request, String method)\r
164             throws ConfigRestAdaptorException {\r
165         return exchangeForEntity(headers, url, HttpMethod.valueOf(method), request);
166     }\r
167 \r
168     private RestResponse exchangeForEntity(HttpHeaders headers, String url, HttpMethod httpMethod, Object request)\r
169             throws ConfigRestAdaptorException {\r
170         RestResponse restResponse = new RestResponse();\r
171         restResponse.setRequestHeaders(headers.toSingleValueMap());\r
172         ResponseEntity<String> response = null;\r
173 \r
174         try {\r
175             if (restTemplate == null) {\r
176                 logger.error(MS_INIT_FAIL);\r
177             } else {\r
178                 logger.debug("Rest Operation: {}", httpMethod);\r
179                 logger.debug("url    : ({})", url);\r
180                 logger.debug("headers: ({})", headers);\r
181                 logger.debug("request: ({})", request);\r
182 \r
183                 if (HttpMethod.GET == httpMethod) {\r
184                     HttpEntity<String> entity = new HttpEntity<>("parameters", headers);\r
185                     response = restTemplate.exchange(url, httpMethod, entity, String.class);\r
186                 } else {\r
187                     HttpEntity<?> entity = new HttpEntity<>(request, headers);\r
188                     response = restTemplate.exchange(url, httpMethod, entity, String.class);\r
189                 }\r
190                 logger.debug("response: ({})", response);\r
191 \r
192                 if (response != null) {\r
193                     logger.debug("response status code: ({})", response.getStatusCode());\r
194                     restResponse.setBody(response.getBody());\r
195                     restResponse.setStatusCode(response.getStatusCode().toString());\r
196                     restResponse.setResponseHeaders(\r
197                             response.getHeaders() != null ? response.getHeaders().toSingleValueMap() : null);\r
198                     return restResponse;\r
199                 }\r
200                 throw new ConfigRestAdaptorException("Rest exchangeForEntity failed to perform ");\r
201             }\r
202         } catch (HttpClientErrorException clientError) {\r
203             logger.debug("clientError: ({})", clientError);\r
204             restResponse.setBody(StringUtils.isBlank(clientError.getResponseBodyAsString()) ? clientError.getMessage()\r
205                     : clientError.getResponseBodyAsString());\r
206             restResponse.setStatusCode(clientError.getStatusCode().toString());\r
207         } catch (Exception e) {\r
208             throw new ConfigRestAdaptorException(\r
209                     String.format("httpMethod (%s) for url (%s) resulted in Exception (%s)", httpMethod, url, e));\r
210         }\r
211         return restResponse;\r
212     }\r
213 \r
214     private <T> ResponseEntity<T> exchangeForEntity(HttpHeaders headers, String url, HttpMethod httpMethod,\r
215             Object request, Class<T> responseType) throws ConfigRestAdaptorException {\r
216         ResponseEntity<T> response = null;\r
217 \r
218         try {\r
219             if (restTemplate == null) {\r
220                 logger.error(MS_INIT_FAIL);\r
221             } else {\r
222                 logger.debug("Rest Operation: {}", httpMethod);\r
223                 logger.debug("url    : ({})", url);\r
224                 logger.debug("headers: ({})", headers);\r
225                 logger.debug("request: ({})", request);\r
226 \r
227                 if (HttpMethod.GET == httpMethod) {\r
228                     HttpEntity<String> entity = new HttpEntity<>("parameters", headers);\r
229                     response = restTemplate.exchange(url, httpMethod, entity, responseType);\r
230                 } else {\r
231                     HttpEntity<?> entity = new HttpEntity<>(request, headers);\r
232                     response = restTemplate.exchange(url, httpMethod, entity, responseType);\r
233                 }\r
234                 logger.debug("response: ({})", response);\r
235 \r
236                 if (response != null) {\r
237                     logger.debug("response status code: ({})", response.getStatusCode());\r
238                 } else {\r
239                     throw new ConfigRestAdaptorException("exchangeForEntity failed to perform ");\r
240                 }\r
241             }\r
242         } catch (Exception e) {\r
243             throw new ConfigRestAdaptorException(\r
244                     String.format("httpMethod (%s) for url (%s) resulted in Exception (%s)", httpMethod, url, e));\r
245         }\r
246         return response;\r
247     }\r
248 \r
249     protected synchronized <T> T processResponse(ResponseEntity<T> response, String url, HttpMethod httpMethod)\r
250             throws ConfigRestAdaptorException {\r
251         if (response != null) {\r
252             if ((HttpMethod.DELETE == httpMethod && (response.getStatusCode() == HttpStatus.NO_CONTENT\r
253                     || response.getStatusCode() == HttpStatus.NOT_FOUND))\r
254                     || ((HttpMethod.GET == httpMethod || HttpMethod.PUT == httpMethod || HttpMethod.POST == httpMethod)\r
255                             && (response.getStatusCode() == HttpStatus.OK\r
256                                     || response.getStatusCode() == HttpStatus.CREATED))) {\r
257                 return response.getBody();\r
258             }\r
259             throw new ConfigRestAdaptorException(\r
260                     String.format("Rest Operation is failed with response-code (%s) for the URL (%s)",\r
261                             response.getStatusCode(), url));\r
262         }\r
263         throw new ConfigRestAdaptorException(String.format("Rest Operation is failed for the URL (%s)", url));\r
264     }\r
265 \r
266     protected synchronized String constructUrl(String baseUrl, String path) {\r
267         if (StringUtils.isNotBlank(path)) {\r
268             return baseUrl + path;\r
269         } else {\r
270             return baseUrl;\r
271         }\r
272     }\r
273 \r
274 }\r