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