17af75200c444c8d4396db36106422f1685d61a1
[vid.git] / vid-app-common / src / main / java / org / onap / vid / mso / RestMsoImplementation.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * VID
4  * ================================================================================
5  * Copyright (C) 2017 - 2019 AT&T Intellectual Property. All rights reserved.
6  * ================================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  * 
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  * 
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  * ============LICENSE_END=========================================================
19  */
20
21 package org.onap.vid.mso;
22
23 import com.att.eelf.configuration.EELFLogger;
24 import com.fasterxml.jackson.databind.ObjectMapper;
25 import org.apache.commons.codec.binary.Base64;
26 import org.apache.http.HttpException;
27 import org.eclipse.jetty.util.security.Password;
28 import org.onap.portalsdk.core.logging.logic.EELFLoggerDelegate;
29 import org.onap.vid.aai.ExceptionWithRequestInfo;
30 import org.onap.vid.aai.util.HttpClientMode;
31 import org.onap.vid.aai.util.HttpsAuthClient;
32 import org.onap.vid.client.HttpBasicClient;
33 import org.onap.vid.exceptions.GenericUncheckedException;
34 import org.onap.vid.mso.rest.RestInterface;
35 import org.onap.vid.utils.Logging;
36 import org.onap.vid.utils.SystemPropertiesWrapper;
37 import org.springframework.beans.factory.annotation.Autowired;
38 import org.springframework.http.HttpMethod;
39
40 import javax.ws.rs.client.Client;
41 import javax.ws.rs.client.Entity;
42 import javax.ws.rs.client.Invocation;
43 import javax.ws.rs.core.MediaType;
44 import javax.ws.rs.core.MultivaluedHashMap;
45 import javax.ws.rs.core.Response;
46 import java.util.Collections;
47 import java.util.Optional;
48
49 import static org.onap.vid.utils.Logging.*;
50
51 /**
52  * Created by pickjonathan on 26/06/2017.
53  */
54 public class RestMsoImplementation implements RestInterface {
55
56     /**
57      * The logger.
58      */
59     protected EELFLoggerDelegate logger = EELFLoggerDelegate.getLogger(RestMsoImplementation.class);
60     private final EELFLogger outgoingRequestsLogger = Logging.getRequestsLogger("mso");
61
62     /** The client. */
63     private Client client = null;
64
65
66     protected HttpsAuthClient httpsAuthClient;
67     protected SystemPropertiesWrapper systemProperties;
68
69     private static final String START_LOG = " start";
70     private static final String APPLICATION_JSON = "application/json";
71     private static final String WITH_STATUS = " with status=";
72     private static final String URL_LOG = ", url=";
73     private static final String NO_RESPONSE_ENTITY_LOG = " No response entity, this is probably ok, e=";
74     private static final String WITH_URL_LOG = " with url=";
75     private static final String EXCEPTION_LOG = ", Exception: ";
76     private static final String REST_API_SUCCESSFULL_LOG = " REST api was successfull!";
77     private static final String REST_MSG_TEMPLATE = "start {}->{}({}, {}, {})";
78     /** The common headers. */
79     /**
80      * Instantiates a new mso rest interface.
81      */
82
83     @Autowired
84     protected RestMsoImplementation(HttpsAuthClient httpsAuthClient, SystemPropertiesWrapper systemProperties){
85         this.httpsAuthClient=httpsAuthClient;
86         this.systemProperties = systemProperties;
87     }
88
89     @SuppressWarnings("Duplicates")
90     protected MultivaluedHashMap<String, Object> initMsoClient()
91     {
92         final String methodname = "initRestClient()";
93
94         final String username = systemProperties.getProperty(MsoProperties.MSO_USER_NAME);
95         final String password = systemProperties.getProperty(MsoProperties.MSO_PASSWORD);
96         final String mso_url = systemProperties.getProperty(MsoProperties.MSO_SERVER_URL);
97         final String decrypted_password = Password.deobfuscate(password);
98
99         String authString = username + ":" + decrypted_password;
100
101         byte[] authEncBytes = Base64.encodeBase64(authString.getBytes());
102         String authStringEnc = new String(authEncBytes);
103
104         MultivaluedHashMap<String, Object> commonHeaders = new MultivaluedHashMap();
105         commonHeaders.put("Authorization",  Collections.singletonList(("Basic " + authStringEnc)));
106         commonHeaders.put("X-ONAP-PartnerName", Collections.singletonList("VID"));
107
108         String requestIdValue = Logging.extractOrGenerateRequestId();
109         commonHeaders.put(REQUEST_ID_HEADER_KEY, Collections.singletonList(requestIdValue));
110         commonHeaders.put(ONAP_REQUEST_ID_HEADER_KEY, Collections.singletonList(requestIdValue));
111
112
113         boolean useSsl = true;
114         if ( (mso_url != null) && ( !(mso_url.isEmpty()) ) ) {
115             useSsl = mso_url.startsWith("https");
116         }
117         if (client == null) {
118
119             try {
120                 if ( useSsl ) {
121                     client = httpsAuthClient.getClient(HttpClientMode.WITHOUT_KEYSTORE);
122                 }
123                 else {
124                     client = HttpBasicClient.getClient();
125                 }
126             } catch (Exception e) {
127                 logger.info(EELFLoggerDelegate.errorLogger,methodname + " Unable to get the SSL client");
128             }
129         }
130
131         return commonHeaders;
132     }
133
134     public <T> RestObjectWithRequestInfo<T> Get(T t, String path, RestObject<T> restObject, boolean warpException) {
135         String methodName = "Get";
136
137         logger.debug(EELFLoggerDelegate.debugLogger, methodName + START_LOG);
138
139         String url = null;
140         String rawData = null;
141         Integer status = null;
142
143         try {
144             restObject.set(t);
145             url = systemProperties.getProperty(MsoProperties.MSO_SERVER_URL) + path;
146
147             MultivaluedHashMap<String, Object> commonHeaders = initMsoClient();
148             Logging.logRequest(outgoingRequestsLogger, HttpMethod.GET, url);
149                 final Response cres = client.target(url)
150                     .request()
151                     .accept(APPLICATION_JSON)
152                     .headers(commonHeaders)
153                     .get();
154             Logging.logResponse(outgoingRequestsLogger, HttpMethod.GET, url, cres);
155
156             cres.bufferEntity();
157             status = cres.getStatus();
158             rawData = cres.readEntity(String.class);
159
160             restObject.setStatusCode(status);
161
162             if (status == 200 || status == 202) {
163                 t = (T) cres.readEntity(t.getClass());
164                 restObject.set(t);
165                 logger.debug(EELFLoggerDelegate.debugLogger, methodName + REST_API_SUCCESSFULL_LOG);
166
167             } else {
168                 throw new GenericUncheckedException(new HttpException(methodName + WITH_STATUS + status + " (200 or 202 expected), url= " + url));
169             }
170
171             logger.debug(EELFLoggerDelegate.debugLogger, methodName + " received status=" + status);
172
173             return new RestObjectWithRequestInfo<>(HttpMethod.GET, url, restObject, status, rawData);
174         } catch (RuntimeException e) {
175             throw warpException ? new ExceptionWithRequestInfo(HttpMethod.GET, url, rawData, status, e) : e;
176         }
177     }
178
179     @Override
180     public <T> RestObject<T> GetForObject(String path, Class<T> clazz) {
181         final String methodName = getMethodName();
182         logger.debug(EELFLoggerDelegate.debugLogger, "start {}->{}({}, {})", getMethodCallerName(), methodName, path, clazz);
183
184         String url = systemProperties.getProperty(MsoProperties.MSO_SERVER_URL) + path;
185         logger.debug(EELFLoggerDelegate.debugLogger, "<== " +  methodName + " sending request to url= " + url);
186
187         MultivaluedHashMap<String, Object> commonHeaders = initMsoClient();
188         Logging.logRequest(outgoingRequestsLogger, HttpMethod.GET, url);
189         final Response cres = client.target(url)
190                 .request()
191                 .accept(APPLICATION_JSON)
192                 .headers(commonHeaders)
193                 .get();
194         Logging.logResponse(outgoingRequestsLogger, HttpMethod.GET, url, cres);
195         final RestObject<T> restObject = cresToRestObject(cres, clazz);
196         int status = cres.getStatus();
197
198         if (status == 200 || status == 202) {
199             logger.debug(EELFLoggerDelegate.debugLogger, methodName + REST_API_SUCCESSFULL_LOG);
200         } else {
201             logger.debug(EELFLoggerDelegate.debugLogger,"<== " + methodName + WITH_STATUS +status+ URL_LOG +url);
202         }
203
204         logger.debug(EELFLoggerDelegate.debugLogger,methodName + " received status=" + status );
205
206         return restObject;
207     }
208
209     @Override
210     public <T> void Delete(T t, Object r, String path, RestObject<T> restObject) {
211
212         String methodName = "Delete";
213         String url="";
214         Response cres;
215
216         logger.debug(EELFLoggerDelegate.debugLogger,"<== " +  methodName + START_LOG);
217
218         try {
219             MultivaluedHashMap<String, Object> commonHeaders = initMsoClient();
220
221             url = systemProperties.getProperty(MsoProperties.MSO_SERVER_URL) + path;
222             Logging.logRequest(outgoingRequestsLogger, HttpMethod.DELETE, url, r);
223             cres = client.target(url)
224                     .request()
225
226                     .accept(APPLICATION_JSON)
227                     .headers(commonHeaders)
228                     //.entity(r)
229                     .build("DELETE", Entity.entity(r, MediaType.APPLICATION_JSON))
230                     .invoke();
231             Logging.logResponse(outgoingRequestsLogger, HttpMethod.DELETE, url, cres);
232             int status = cres.getStatus();
233             restObject.setStatusCode (status);
234
235             if (status == 404) { // resource not found
236                 String msg = "Resource does not exist...: " + cres.getStatus();
237                 logger.debug(EELFLoggerDelegate.debugLogger,"<== " + msg);
238             } else if (status == 200  || status == 204){
239                 logger.debug(EELFLoggerDelegate.debugLogger,"<== " + "Resource " + url + " deleted");
240             } else if (status == 202) {
241                 String      msg = "Delete in progress: " + status;
242                 logger.debug(EELFLoggerDelegate.debugLogger,"<== " + msg);
243             }
244             else {
245                 String msg = "Deleting Resource failed: " + status;
246                 logger.debug(EELFLoggerDelegate.debugLogger,"<== " + msg);
247             }
248
249             try {
250                 t = (T) cres.readEntity(t.getClass());
251                 restObject.set(t);
252             }
253             catch ( Exception e ) {
254                 logger.debug(EELFLoggerDelegate.debugLogger,"<== " + methodName + NO_RESPONSE_ENTITY_LOG
255                         + e.getMessage());
256                 throw e;
257             }
258
259         }
260         catch (Exception e)
261         {
262             logger.debug(EELFLoggerDelegate.debugLogger,"<== " + methodName + WITH_URL_LOG +url+ EXCEPTION_LOG + e.toString());
263             throw e;
264         }
265     }
266
267     public <T> RestObject<T> PostForObject(Object requestDetails, String path, Class<T> clazz) {
268         logger.debug(EELFLoggerDelegate.debugLogger, REST_MSG_TEMPLATE, getMethodCallerName(), getMethodName(), requestDetails, path, clazz);
269         return restCall(HttpMethod.POST, clazz, requestDetails, path);
270     }
271
272     public <T> RestObject<T> DeleteForObject(Object requestDetails, String path, Class<T> clazz) {
273         logger.debug(EELFLoggerDelegate.debugLogger, REST_MSG_TEMPLATE, getMethodCallerName(), getMethodName(), requestDetails, path, clazz);
274         return restCall(HttpMethod.DELETE, clazz, requestDetails, path);
275     }
276
277     @Override
278     public void Post(String t, Object r, String path, RestObject<String> restObject) {
279         logger.debug(EELFLoggerDelegate.debugLogger, REST_MSG_TEMPLATE, getMethodCallerName(), getMethodName(), t.getClass(), r, path);
280         restObject.copyFrom(restCall(HttpMethod.POST, String.class, r, path));
281     }
282
283     public Invocation.Builder prepareClient(String path, String methodName) {
284         MultivaluedHashMap<String, Object> commonHeaders = initMsoClient();
285
286         String url = systemProperties.getProperty(MsoProperties.MSO_SERVER_URL) + path;
287         logger.debug(EELFLoggerDelegate.debugLogger,"<== " +  methodName + " sending request to url= " + url);
288         // Change the content length
289         return client.target(url)
290                 .request()
291                 .accept(APPLICATION_JSON)
292                 .headers(commonHeaders);
293     }
294
295     public <T> RestObject<T> restCall(HttpMethod httpMethod, Class<T> tClass, Object payload, String path) {
296         return restCall(httpMethod, tClass, payload, path, Optional.empty());
297     }
298
299
300     /*
301     user id is needed to be pass as X-RequestorID in new MSO flows like Delete instanceGroup
302      */
303     public <T> RestObject<T> restCall(HttpMethod httpMethod, Class<T> tClass, Object payload, String path, Optional<String> userId)  {
304         String methodName = httpMethod.name();
305         String url="";
306
307         try {
308
309             MultivaluedHashMap<String, Object> commonHeaders = initMsoClient();
310             userId.ifPresent(id->commonHeaders.put("X-RequestorID", Collections.singletonList(id)));
311
312             url = systemProperties.getProperty(MsoProperties.MSO_SERVER_URL) + path;
313             Logging.logRequest(outgoingRequestsLogger, httpMethod, url, payload);
314             // Change the content length
315             final Invocation.Builder restBuilder = client.target(url)
316                     .request()
317                     .accept(APPLICATION_JSON)
318                     .headers(commonHeaders);
319
320             Invocation restInvocation = payload==null ?
321                     restBuilder.build(httpMethod.name()) :
322                     restBuilder.build(httpMethod.name(), Entity.entity(payload, MediaType.APPLICATION_JSON));
323             final Response cres = restInvocation.invoke();
324
325             Logging.logResponse(outgoingRequestsLogger, httpMethod, url, cres);
326             return cresToRestObject(cres, tClass);
327         }
328         catch (Exception e) {
329             logger.debug(EELFLoggerDelegate.debugLogger,"<== " + methodName + WITH_URL_LOG +url+ EXCEPTION_LOG + e.toString());
330             throw e;
331         }
332
333     }
334
335     private <T> RestObject<T> cresToRestObject(Response cres, Class<?> tClass) {
336         RestObject<T> restObject = new RestObject<>();
337
338         String rawEntity = null;
339         try {
340             cres.bufferEntity();
341             rawEntity = cres.readEntity(String.class);
342             restObject.setRaw(rawEntity);
343             T t = (T) new ObjectMapper().readValue(rawEntity, tClass);
344             restObject.set(t);
345         }
346         catch ( Exception e ) {
347             try {
348                 logger.debug(EELFLoggerDelegate.debugLogger, "<== " + getMethodCallerName() + " Error reading response entity as " + tClass + ": , e="
349                         + e.getMessage() + ", Entity=" + rawEntity);
350             } catch (Exception e2) {
351                 logger.debug(EELFLoggerDelegate.debugLogger, "<== " + getMethodCallerName() + NO_RESPONSE_ENTITY_LOG
352                         + e.getMessage());
353             }
354         }
355
356         int status = cres.getStatus();
357         restObject.setStatusCode (status);
358
359         return restObject;
360     }
361
362     @Override
363     public <T> void Put(T t, org.onap.vid.changeManagement.RequestDetailsWrapper r, String path, RestObject<T> restObject) {
364
365         String methodName = "Put";
366         String url="";
367
368         logger.debug(EELFLoggerDelegate.debugLogger,"<== " +  methodName + START_LOG);
369
370         try {
371
372             MultivaluedHashMap<String, Object> commonHeaders = initMsoClient();
373
374             url = systemProperties.getProperty(MsoProperties.MSO_SERVER_URL) + path;
375             Logging.logRequest(outgoingRequestsLogger, HttpMethod.PUT, url, r);
376             // Change the content length
377             final Response cres = client.target(url)
378                     .request()
379                     .accept(APPLICATION_JSON)
380                     .headers(commonHeaders)
381                     //.header("content-length", 201)
382                     .put(Entity.entity(r, MediaType.APPLICATION_JSON));
383
384             Logging.logResponse(outgoingRequestsLogger, HttpMethod.PUT, url, cres);
385
386             try {
387                 t = (T) cres.readEntity(t.getClass());
388                 restObject.set(t);
389             }
390             catch ( Exception e ) {
391                 logger.debug(EELFLoggerDelegate.debugLogger,"<== " + methodName + NO_RESPONSE_ENTITY_LOG
392                         + e.getMessage());
393                 throw e;
394             }
395
396             int status = cres.getStatus();
397             restObject.setStatusCode (status);
398
399             if ( status >= 200 && status <= 299 ) {
400                 logger.info(EELFLoggerDelegate.errorLogger, "<== " + methodName + REST_API_SUCCESSFULL_LOG);
401                 logger.debug(EELFLoggerDelegate.debugLogger,"<== " + methodName + REST_API_SUCCESSFULL_LOG);
402
403             } else {
404                 logger.debug(EELFLoggerDelegate.debugLogger,"<== " + methodName + WITH_STATUS +status+ URL_LOG +url);
405             }
406
407         } catch (Exception e)
408         {
409             logger.debug(EELFLoggerDelegate.debugLogger,"<== " + methodName + WITH_URL_LOG +url+ EXCEPTION_LOG + e.toString());
410             throw e;
411
412         }
413     }
414 }