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