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